From 265e33241a806d3c3462f1c0701a8617190be01b Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Fri, 10 Mar 2023 14:45:49 +0100 Subject: [PATCH 001/397] version set to 3.6.0-SNAPSHOT --- application/pom.xml | 2 +- common/actor/pom.xml | 2 +- common/cache/pom.xml | 2 +- common/cluster-api/pom.xml | 2 +- common/coap-server/pom.xml | 2 +- common/dao-api/pom.xml | 2 +- common/data/pom.xml | 2 +- common/edge-api/pom.xml | 2 +- common/message/pom.xml | 2 +- common/pom.xml | 2 +- common/queue/pom.xml | 2 +- common/script/pom.xml | 2 +- common/script/remote-js-client/pom.xml | 2 +- common/script/script-api/pom.xml | 2 +- common/stats/pom.xml | 2 +- common/transport/coap/pom.xml | 2 +- common/transport/http/pom.xml | 2 +- common/transport/lwm2m/pom.xml | 2 +- common/transport/mqtt/pom.xml | 2 +- common/transport/pom.xml | 2 +- common/transport/snmp/pom.xml | 2 +- common/transport/transport-api/pom.xml | 2 +- common/util/pom.xml | 2 +- common/version-control/pom.xml | 2 +- dao/pom.xml | 2 +- msa/black-box-tests/pom.xml | 2 +- msa/js-executor/package.json | 2 +- msa/js-executor/pom.xml | 2 +- msa/pom.xml | 2 +- msa/tb-node/pom.xml | 2 +- msa/tb/pom.xml | 2 +- msa/transport/coap/pom.xml | 2 +- msa/transport/http/pom.xml | 2 +- msa/transport/lwm2m/pom.xml | 2 +- msa/transport/mqtt/pom.xml | 2 +- msa/transport/pom.xml | 2 +- msa/transport/snmp/pom.xml | 2 +- msa/vc-executor-docker/pom.xml | 2 +- msa/vc-executor/pom.xml | 2 +- msa/web-ui/package.json | 2 +- msa/web-ui/pom.xml | 2 +- netty-mqtt/pom.xml | 4 ++-- pom.xml | 2 +- rest-client/pom.xml | 2 +- rule-engine/pom.xml | 2 +- rule-engine/rule-engine-api/pom.xml | 2 +- rule-engine/rule-engine-components/pom.xml | 2 +- tools/pom.xml | 2 +- transport/coap/pom.xml | 2 +- transport/http/pom.xml | 2 +- transport/lwm2m/pom.xml | 2 +- transport/mqtt/pom.xml | 2 +- transport/pom.xml | 2 +- transport/snmp/pom.xml | 2 +- ui-ngx/package.json | 2 +- ui-ngx/pom.xml | 2 +- 56 files changed, 57 insertions(+), 57 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index b653465050..d2fc75b1cb 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard application diff --git a/common/actor/pom.xml b/common/actor/pom.xml index 2bc3335ded..2de85be932 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/cache/pom.xml b/common/cache/pom.xml index 9c887cd7cd..440860fda6 100644 --- a/common/cache/pom.xml +++ b/common/cache/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml index bd45c1c7ca..c9fa6d0894 100644 --- a/common/cluster-api/pom.xml +++ b/common/cluster-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/coap-server/pom.xml b/common/coap-server/pom.xml index a48a0c31bc..420fc4dae6 100644 --- a/common/coap-server/pom.xml +++ b/common/coap-server/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index 71f872b353..029c660500 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index e50ccd9dd2..f6fd744a02 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/edge-api/pom.xml b/common/edge-api/pom.xml index cf03facf55..60562efbf2 100644 --- a/common/edge-api/pom.xml +++ b/common/edge-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index ac7814bc49..e64d4676ce 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index 812a05abaf..0edd153a3c 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index 200867d022..edd4574bdd 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/script/pom.xml b/common/script/pom.xml index 42593f033c..26f60bd358 100644 --- a/common/script/pom.xml +++ b/common/script/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/script/remote-js-client/pom.xml b/common/script/remote-js-client/pom.xml index 8fbef37bdb..8fa852d977 100644 --- a/common/script/remote-js-client/pom.xml +++ b/common/script/remote-js-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT script org.thingsboard.common.script diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml index 24cf7d832d..c4e069f695 100644 --- a/common/script/script-api/pom.xml +++ b/common/script/script-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT script org.thingsboard.common.script diff --git a/common/stats/pom.xml b/common/stats/pom.xml index 19243d9b28..0869243e7a 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index 14c105c3b7..2ac15d3e42 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index b02491768e..8cf3e0efe8 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/lwm2m/pom.xml b/common/transport/lwm2m/pom.xml index ddd8f227cf..4433eae2b9 100644 --- a/common/transport/lwm2m/pom.xml +++ b/common/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index ae0b35e44d..bb4767640c 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index 4f319abfad..6879a4924d 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/snmp/pom.xml b/common/transport/snmp/pom.xml index 30d14a4b28..1865f498fa 100644 --- a/common/transport/snmp/pom.xml +++ b/common/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.common - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 26dde924f7..2e2174e0a9 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index a222724acd..83036d536f 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/common/version-control/pom.xml b/common/version-control/pom.xml index 381f4ed292..a8acdf2be9 100644 --- a/common/version-control/pom.xml +++ b/common/version-control/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index 4fc8a3c08d..4d4dd2a30b 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard dao diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index ae0b12ead7..12d36272c0 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index add59eb610..dc72a2bb22 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "3.5.0", + "version": "3.6.0", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 05775ef137..0bd7bf4d60 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/pom.xml b/msa/pom.xml index ad40e574ec..e80dc54269 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index 8779dd6dd1..8437cc35c3 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index 4b8439e0e9..7c4af55497 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 6a4ce4dd69..386b91ea76 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index 37fe6efc91..344219a660 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/lwm2m/pom.xml b/msa/transport/lwm2m/pom.xml index 77f5a1e2fd..8dfef617cd 100644 --- a/msa/transport/lwm2m/pom.xml +++ b/msa/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index 962025a917..e1d740c877 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index 8f6acf590e..e0bd5a9457 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/snmp/pom.xml b/msa/transport/snmp/pom.xml index 6353419382..b6a4e15b04 100644 --- a/msa/transport/snmp/pom.xml +++ b/msa/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.msa transport - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT org.thingsboard.msa.transport diff --git a/msa/vc-executor-docker/pom.xml b/msa/vc-executor-docker/pom.xml index b076cf14cb..9b6fc493cd 100644 --- a/msa/vc-executor-docker/pom.xml +++ b/msa/vc-executor-docker/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/vc-executor/pom.xml b/msa/vc-executor/pom.xml index 37ba0da564..9bd2befa90 100644 --- a/msa/vc-executor/pom.xml +++ b/msa/vc-executor/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index 18cc80481f..3338d2ae76 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "3.5.0", + "version": "3.6.0", "description": "ThingsBoard Web UI Microservice", "main": "server.ts", "bin": "server.js", diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index fd73ce686c..e9500cf5e0 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index b15e8235b4..0ae03f3980 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard netty-mqtt - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index 49f30df835..b70be187ed 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index cb85c2134e..10a8cd311b 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index e005b5a543..fe8cb3fab5 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 5a200fc14a..47d13e5658 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index e85f0094b5..34c6e315f7 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index ae6eb95a15..c0b74bb0a9 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index 5cc87640d7..3b1e0a9e62 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index d685b8d1ab..3d4b806d03 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/lwm2m/pom.xml b/transport/lwm2m/pom.xml index dcdfaac0c8..efe76111f3 100644 --- a/transport/lwm2m/pom.xml +++ b/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index 11a73d7e51..75daa483a1 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index 3e14199411..203ea6cbbb 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard transport diff --git a/transport/snmp/pom.xml b/transport/snmp/pom.xml index 8ba98a9924..c04e7d1f1f 100644 --- a/transport/snmp/pom.xml +++ b/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT transport diff --git a/ui-ngx/package.json b/ui-ngx/package.json index a8abb6fbeb..a1564630f3 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -1,6 +1,6 @@ { "name": "thingsboard", - "version": "3.5.0", + "version": "3.6.0", "scripts": { "ng": "ng", "start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --configuration development --host 0.0.0.0 --open", diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index 01d0ece37d..d6dc28490f 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard org.thingsboard From 98ea8298c3a4a73f238e783e7b2abf1e9c42aa0c Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Fri, 21 Apr 2023 20:03:25 +0200 Subject: [PATCH 002/397] set 3.6 version for monitoring --- monitoring/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monitoring/pom.xml b/monitoring/pom.xml index e044635e98..399e34092d 100644 --- a/monitoring/pom.xml +++ b/monitoring/pom.xml @@ -21,7 +21,7 @@ 4.0.0 org.thingsboard - 3.5.0-SNAPSHOT + 3.6.0-SNAPSHOT thingsboard From 40d6e6713141ee6273bf2f91bfce2c824b57f18a Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Tue, 2 May 2023 00:46:34 +0200 Subject: [PATCH 003/397] migrate to java 17 --- .../sync/vc/VersionControlTaskRedisCache.java | 4 +- .../AutoCommitSettingsRedisCache.java | 4 +- .../RepositorySettingsRedisCache.java | 4 +- .../server/controller/AbstractWebTest.java | 14 ++++- ...alizer.java => TbJavaRedisSerializer.java} | 8 +-- .../server/cache/device/DeviceRedisCache.java | 4 +- .../UsersSessionInvalidationRedisCache.java | 4 +- common/data/pom.xml | 4 -- .../server/common/data/FSTUtils.java | 35 ------------ .../server/common/data/JavaSerDesUtil.java | 57 +++++++++++++++++++ .../bootstrap/LwM2MServerSecurityConfig.java | 4 +- .../NoSecLwM2MBootstrapServerCredential.java | 3 + .../msg/TbMsgProcessingStackItemTest.java | 6 +- ...a => JavaDataDecodingEncodingService.java} | 20 ++----- common/script/script-api/pom.xml | 4 ++ .../store/TbLwM2MDtlsSessionRedisStore.java | 8 +-- .../store/TbLwM2mRedisSecurityStore.java | 21 +++---- .../dao/asset/AssetProfileRedisCache.java | 4 +- .../server/dao/asset/AssetRedisCache.java | 4 +- .../dashboard/DashboardTitlesRedisCache.java | 4 +- .../device/DeviceCredentialsRedisCache.java | 4 +- .../dao/device/DeviceProfileRedisCache.java | 4 +- .../server/dao/edge/EdgeRedisCache.java | 4 +- .../entity/count/EntityCountRedisCache.java | 4 +- .../dao/entityview/EntityViewRedisCache.java | 4 +- .../server/dao/ota/OtaPackageRedisCache.java | 4 +- .../dao/relation/RelationRedisCache.java | 4 +- .../dao/tenant/TenantExistsRedisCache.java | 4 +- .../dao/tenant/TenantProfileRedisCache.java | 4 +- .../server/dao/tenant/TenantRedisCache.java | 4 +- .../dao/user/UserSettingsRedisCache.java | 5 +- pom.xml | 17 +++--- 32 files changed, 148 insertions(+), 130 deletions(-) rename common/cache/src/main/java/org/thingsboard/server/cache/{TbFSTRedisSerializer.java => TbJavaRedisSerializer.java} (80%) delete mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/FSTUtils.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/JavaSerDesUtil.java rename common/queue/src/main/java/org/thingsboard/server/queue/util/{ProtoWithFSTService.java => JavaDataDecodingEncodingService.java} (61%) diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/VersionControlTaskRedisCache.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/VersionControlTaskRedisCache.java index 5fccbb3cbb..a849577d0c 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/VersionControlTaskRedisCache.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/VersionControlTaskRedisCache.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import java.util.UUID; @@ -31,6 +31,6 @@ import java.util.UUID; public class VersionControlTaskRedisCache extends RedisTbTransactionalCache { public VersionControlTaskRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.VERSION_CONTROL_TASK_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.VERSION_CONTROL_TASK_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/autocommit/AutoCommitSettingsRedisCache.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/autocommit/AutoCommitSettingsRedisCache.java index b3c47cf2a7..be9bbfa443 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/autocommit/AutoCommitSettingsRedisCache.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/autocommit/AutoCommitSettingsRedisCache.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings; @@ -31,6 +31,6 @@ import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings; public class AutoCommitSettingsRedisCache extends RedisTbTransactionalCache { public AutoCommitSettingsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.AUTO_COMMIT_SETTINGS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.AUTO_COMMIT_SETTINGS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/repository/RepositorySettingsRedisCache.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/repository/RepositorySettingsRedisCache.java index 27fba3459c..1e71a51d00 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/repository/RepositorySettingsRedisCache.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/repository/RepositorySettingsRedisCache.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.sync.vc.RepositorySettings; @@ -31,6 +31,6 @@ import org.thingsboard.server.common.data.sync.vc.RepositorySettings; public class RepositorySettingsRedisCache extends RedisTbTransactionalCache { public RepositorySettingsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.REPOSITORY_SETTINGS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.REPOSITORY_SETTINGS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index c7580867e0..d128c8ed91 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -116,6 +116,8 @@ import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRequest; import org.thingsboard.server.service.security.auth.rest.LoginRequest; import java.io.IOException; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.sql.SQLException; @@ -927,9 +929,15 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { protected static void setStaticFinalFieldValue(Class targetCls, String fieldName, Object value) throws Exception { Field field = targetCls.getDeclaredField(fieldName); field.setAccessible(true); - Field modifiers = Field.class.getDeclaredField("modifiers"); - modifiers.setAccessible(true); - modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + // Get the VarHandle for the 'modifiers' field in the Field class + MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup()); + VarHandle modifiersHandle = lookup.findVarHandle(Field.class, "modifiers", int.class); + + // Remove the final modifier from the field + int currentModifiers = field.getModifiers(); + modifiersHandle.set(field, currentModifiers & ~Modifier.FINAL); + + // Set the new value field.set(null, value); } diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/TbFSTRedisSerializer.java b/common/cache/src/main/java/org/thingsboard/server/cache/TbJavaRedisSerializer.java similarity index 80% rename from common/cache/src/main/java/org/thingsboard/server/cache/TbFSTRedisSerializer.java rename to common/cache/src/main/java/org/thingsboard/server/cache/TbJavaRedisSerializer.java index 3d8bf66542..9a5e2fa078 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/TbFSTRedisSerializer.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/TbJavaRedisSerializer.java @@ -16,17 +16,17 @@ package org.thingsboard.server.cache; import org.springframework.data.redis.serializer.SerializationException; -import org.thingsboard.server.common.data.FSTUtils; +import org.thingsboard.server.common.data.JavaSerDesUtil; -public class TbFSTRedisSerializer implements TbRedisSerializer { +public class TbJavaRedisSerializer implements TbRedisSerializer { @Override public byte[] serialize(V value) throws SerializationException { - return FSTUtils.encode(value); + return JavaSerDesUtil.encode(value); } @Override public V deserialize(K key, byte[] bytes) throws SerializationException { - return FSTUtils.decode(bytes); + return JavaSerDesUtil.decode(bytes); } } diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceRedisCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceRedisCache.java index 591555a3a1..a7b7a047fb 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceRedisCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceRedisCache.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.Device; @@ -30,6 +30,6 @@ import org.thingsboard.server.common.data.Device; public class DeviceRedisCache extends RedisTbTransactionalCache { public DeviceRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.DEVICE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.DEVICE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/usersUpdateTime/UsersSessionInvalidationRedisCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/usersUpdateTime/UsersSessionInvalidationRedisCache.java index 83360fb8af..38a9104679 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/usersUpdateTime/UsersSessionInvalidationRedisCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/usersUpdateTime/UsersSessionInvalidationRedisCache.java @@ -22,7 +22,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @@ -31,6 +31,6 @@ public class UsersSessionInvalidationRedisCache extends RedisTbTransactionalCach @Autowired public UsersSessionInvalidationRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.USERS_SESSION_INVALIDATION_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.USERS_SESSION_INVALIDATION_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/common/data/pom.xml b/common/data/pom.xml index d81203cd4d..c1fa964caa 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -108,10 +108,6 @@ io.swagger swagger-annotations - - de.ruedigermoeller - fst - com.google.protobuf protobuf-java-util diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/FSTUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/FSTUtils.java deleted file mode 100644 index 83447d7a6b..0000000000 --- a/common/data/src/main/java/org/thingsboard/server/common/data/FSTUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright © 2016-2023 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.data; - -import lombok.extern.slf4j.Slf4j; -import org.nustaq.serialization.FSTConfiguration; - -@Slf4j -public class FSTUtils { - - public static final FSTConfiguration CONFIG = FSTConfiguration.createDefaultConfiguration(); - - @SuppressWarnings("unchecked") - public static T decode(byte[] byteArray) { - return byteArray != null && byteArray.length > 0 ? (T) CONFIG.asObject(byteArray) : null; - } - - public static byte[] encode(T msq) { - return CONFIG.asByteArray(msq); - } - -} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/JavaSerDesUtil.java b/common/data/src/main/java/org/thingsboard/server/common/data/JavaSerDesUtil.java new file mode 100644 index 0000000000..636fda5fc5 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/JavaSerDesUtil.java @@ -0,0 +1,57 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data; + +import lombok.extern.slf4j.Slf4j; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +@Slf4j +public class JavaSerDesUtil { + + @SuppressWarnings("unchecked") + public static T decode(byte[] byteArray) { + if (byteArray == null || byteArray.length == 0) { + return null; + } + InputStream is = new ByteArrayInputStream(byteArray); + try (ObjectInputStream ois = new ObjectInputStream(is)) { + return (T) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + log.error("Error during deserialization message, [{}]", e.getMessage()); + return null; + } + } + + public static byte[] encode(T msq) { + if (msq == null) { + return null; + } + ByteArrayOutputStream boas = new ByteArrayOutputStream(); + try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { + ois.writeObject(msq); + return boas.toByteArray(); + } catch (IOException e) { + log.error("Error during serialization message, [{}]", e.getMessage()); + throw new RuntimeException(e); + } + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfig.java index eb052da126..4405115905 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfig.java @@ -19,9 +19,11 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.io.Serializable; + @ApiModel @Data -public class LwM2MServerSecurityConfig { +public class LwM2MServerSecurityConfig implements Serializable { @ApiModelProperty(position = 1, value = "Server short Id. Used as link to associate server Object Instance. This identifier uniquely identifies each LwM2M Server configured for the LwM2M Client. " + "This Resource MUST be set when the Bootstrap-Server Resource has a value of 'false'. " + diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/NoSecLwM2MBootstrapServerCredential.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/NoSecLwM2MBootstrapServerCredential.java index 6bd7b7c427..43b9a0763e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/NoSecLwM2MBootstrapServerCredential.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/NoSecLwM2MBootstrapServerCredential.java @@ -17,8 +17,11 @@ package org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; +import java.io.Serial; + public class NoSecLwM2MBootstrapServerCredential extends AbstractLwM2MBootstrapServerCredential { + @Serial private static final long serialVersionUID = 5540417758424747066L; @Override diff --git a/common/message/src/test/java/org/thingsboard/server/common/msg/TbMsgProcessingStackItemTest.java b/common/message/src/test/java/org/thingsboard/server/common/msg/TbMsgProcessingStackItemTest.java index 1f3fa2050a..86d061b57c 100644 --- a/common/message/src/test/java/org/thingsboard/server/common/msg/TbMsgProcessingStackItemTest.java +++ b/common/message/src/test/java/org/thingsboard/server/common/msg/TbMsgProcessingStackItemTest.java @@ -16,7 +16,7 @@ package org.thingsboard.server.common.msg; import org.junit.jupiter.api.Test; -import org.thingsboard.server.common.data.FSTUtils; +import org.thingsboard.server.common.data.JavaSerDesUtil; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; @@ -29,8 +29,8 @@ class TbMsgProcessingStackItemTest { @Test void testSerialization() { TbMsgProcessingStackItem item = new TbMsgProcessingStackItem(new RuleChainId(UUID.randomUUID()), new RuleNodeId(UUID.randomUUID())); - byte[] bytes = FSTUtils.encode(item); - TbMsgProcessingStackItem itemDecoded = FSTUtils.decode(bytes); + byte[] bytes = JavaSerDesUtil.encode(item); + TbMsgProcessingStackItem itemDecoded = JavaSerDesUtil.decode(bytes); assertThat(item).isEqualTo(itemDecoded); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/util/ProtoWithFSTService.java b/common/queue/src/main/java/org/thingsboard/server/queue/util/JavaDataDecodingEncodingService.java similarity index 61% rename from common/queue/src/main/java/org/thingsboard/server/queue/util/ProtoWithFSTService.java rename to common/queue/src/main/java/org/thingsboard/server/queue/util/JavaDataDecodingEncodingService.java index b0d0b182e9..493d6f31f2 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/util/ProtoWithFSTService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/util/JavaDataDecodingEncodingService.java @@ -16,33 +16,21 @@ package org.thingsboard.server.queue.util; import lombok.extern.slf4j.Slf4j; -import org.nustaq.serialization.FSTConfiguration; import org.springframework.stereotype.Service; -import org.thingsboard.server.common.data.FSTUtils; +import org.thingsboard.server.common.data.JavaSerDesUtil; import java.util.Optional; @Slf4j @Service -public class ProtoWithFSTService implements DataDecodingEncodingService { - - public static final FSTConfiguration CONFIG = FSTConfiguration.createDefaultConfiguration(); - +public class JavaDataDecodingEncodingService implements DataDecodingEncodingService { @Override public Optional decode(byte[] byteArray) { - try { - return Optional.ofNullable(FSTUtils.decode(byteArray)); - } catch (IllegalArgumentException e) { - log.error("Error during deserialization message, [{}]", e.getMessage()); - return Optional.empty(); - } + return Optional.ofNullable(JavaSerDesUtil.decode(byteArray)); } - @Override public byte[] encode(T msq) { - return FSTUtils.encode(msq); + return JavaSerDesUtil.encode(msq); } - - } diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml index 24cf7d832d..b5d652f0d9 100644 --- a/common/script/script-api/pom.xml +++ b/common/script/script-api/pom.xml @@ -52,6 +52,10 @@ org.javadelight delight-nashorn-sandbox + + org.openjdk.nashorn + nashorn-core + com.google.code.gson gson diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2MDtlsSessionRedisStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2MDtlsSessionRedisStore.java index a1ffad9946..737ce96c41 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2MDtlsSessionRedisStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2MDtlsSessionRedisStore.java @@ -15,25 +15,23 @@ */ package org.thingsboard.server.transport.lwm2m.server.store; -import org.nustaq.serialization.FSTConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.thingsboard.server.common.data.JavaSerDesUtil; import org.thingsboard.server.transport.lwm2m.secure.TbX509DtlsSessionInfo; public class TbLwM2MDtlsSessionRedisStore implements TbLwM2MDtlsSessionStore { private static final String SESSION_EP = "SESSION#EP#"; private final RedisConnectionFactory connectionFactory; - private final FSTConfiguration serializer; public TbLwM2MDtlsSessionRedisStore(RedisConnectionFactory redisConnectionFactory) { this.connectionFactory = redisConnectionFactory; - this.serializer = FSTConfiguration.createDefaultConfiguration(); } @Override public void put(String endpoint, TbX509DtlsSessionInfo msg) { try (var c = connectionFactory.getConnection()) { - var serializedMsg = serializer.asByteArray(msg); + var serializedMsg = JavaSerDesUtil.encode(msg); if (serializedMsg != null) { c.set(getKey(endpoint), serializedMsg); } else { @@ -47,7 +45,7 @@ public class TbLwM2MDtlsSessionRedisStore implements TbLwM2MDtlsSessionStore { try (var c = connectionFactory.getConnection()) { var data = c.get(getKey(endpoint)); if (data != null) { - return (TbX509DtlsSessionInfo) serializer.asObject(data); + return JavaSerDesUtil.decode(data); } else { return null; } diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisSecurityStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisSecurityStore.java index f6539556e5..87e92c8cca 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisSecurityStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisSecurityStore.java @@ -18,9 +18,9 @@ package org.thingsboard.server.transport.lwm2m.server.store; import org.eclipse.leshan.core.SecurityMode; import org.eclipse.leshan.server.security.NonUniqueSecurityInfoException; import org.eclipse.leshan.server.security.SecurityInfo; -import org.nustaq.serialization.FSTConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.integration.redis.util.RedisLockRegistry; +import org.thingsboard.server.common.data.JavaSerDesUtil; import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo; import java.util.concurrent.locks.Lock; @@ -31,13 +31,11 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { private static final String PSKID_SEC = "PSKID#SEC"; private final RedisConnectionFactory connectionFactory; - private final FSTConfiguration serializer; private final RedisLockRegistry redisLock; public TbLwM2mRedisSecurityStore(RedisConnectionFactory connectionFactory) { this.connectionFactory = connectionFactory; redisLock = new RedisLockRegistry(connectionFactory, "Security"); - serializer = FSTConfiguration.createDefaultConfiguration(); } @Override @@ -50,12 +48,11 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { if (data == null || data.length == 0) { return null; } else { - if (SecurityMode.NO_SEC.equals(((TbLwM2MSecurityInfo) serializer.asObject(data)).getSecurityMode())) { + if (SecurityMode.NO_SEC.equals(((TbLwM2MSecurityInfo) JavaSerDesUtil.decode(data)).getSecurityMode())) { return SecurityInfo.newPreSharedKeyInfo(SecurityMode.NO_SEC.toString(), SecurityMode.NO_SEC.toString(), SecurityMode.NO_SEC.toString().getBytes()); - } - else { - return ((TbLwM2MSecurityInfo) serializer.asObject(data)).getSecurityInfo(); + } else { + return ((TbLwM2MSecurityInfo) JavaSerDesUtil.decode(data)).getSecurityInfo(); } } } finally { @@ -79,7 +76,7 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { if (data == null || data.length == 0) { return null; } else { - return ((TbLwM2MSecurityInfo) serializer.asObject(data)).getSecurityInfo(); + return ((TbLwM2MSecurityInfo) JavaSerDesUtil.decode(data)).getSecurityInfo(); } } } finally { @@ -92,7 +89,7 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { @Override public void put(TbLwM2MSecurityInfo tbSecurityInfo) throws NonUniqueSecurityInfoException { SecurityInfo info = tbSecurityInfo.getSecurityInfo(); - byte[] tbSecurityInfoSerialized = serializer.asByteArray(tbSecurityInfo); + byte[] tbSecurityInfoSerialized = JavaSerDesUtil.encode(tbSecurityInfo); Lock lock = null; try (var connection = connectionFactory.getConnection()) { lock = redisLock.obtain(tbSecurityInfo.getEndpoint()); @@ -110,7 +107,7 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { byte[] previousData = connection.getSet((SEC_EP + tbSecurityInfo.getEndpoint()).getBytes(), tbSecurityInfoSerialized); if (previousData != null && info != null) { - String previousIdentity = ((TbLwM2MSecurityInfo) serializer.asObject(previousData)).getSecurityInfo().getIdentity(); + String previousIdentity = ((TbLwM2MSecurityInfo) JavaSerDesUtil.decode(previousData)).getSecurityInfo().getIdentity(); if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) { connection.hDel(PSKID_SEC.getBytes(), previousIdentity.getBytes()); } @@ -130,7 +127,7 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { lock.lock(); byte[] data = connection.get((SEC_EP + endpoint).getBytes()); if (data != null && data.length > 0) { - return (TbLwM2MSecurityInfo) serializer.asObject(data); + return JavaSerDesUtil.decode(data); } else { return null; } @@ -149,7 +146,7 @@ public class TbLwM2mRedisSecurityStore implements TbEditableSecurityStore { lock.lock(); byte[] data = connection.get((SEC_EP + endpoint).getBytes()); if (data != null && data.length > 0) { - SecurityInfo info = ((TbLwM2MSecurityInfo) serializer.asObject(data)).getSecurityInfo(); + SecurityInfo info = ((TbLwM2MSecurityInfo) JavaSerDesUtil.decode(data)).getSecurityInfo(); if (info != null && info.getIdentity() != null) { connection.hDel(PSKID_SEC.getBytes(), info.getIdentity().getBytes()); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileRedisCache.java index 25f919e881..1e4463cbea 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileRedisCache.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.asset.AssetProfile; @@ -30,6 +30,6 @@ import org.thingsboard.server.common.data.asset.AssetProfile; public class AssetProfileRedisCache extends RedisTbTransactionalCache { public AssetProfileRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.ASSET_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.ASSET_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetRedisCache.java index c0fb23c5a4..b423edae43 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetRedisCache.java @@ -23,13 +23,13 @@ import org.thingsboard.server.cache.TBRedisCacheConfiguration; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.cache.RedisTbTransactionalCache; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @Service("AssetCache") public class AssetRedisCache extends RedisTbTransactionalCache { public AssetRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.ASSET_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.ASSET_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardTitlesRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardTitlesRedisCache.java index 990a175b71..ef59fb6f6d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardTitlesRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardTitlesRedisCache.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.id.DashboardId; @@ -30,6 +30,6 @@ import org.thingsboard.server.common.data.id.DashboardId; public class DashboardTitlesRedisCache extends RedisTbTransactionalCache { public DashboardTitlesRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.DASHBOARD_TITLES_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.DASHBOARD_TITLES_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsRedisCache.java index 86a1086207..2c33e53c10 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceCredentialsRedisCache.java @@ -20,7 +20,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.cache.RedisTbTransactionalCache; @@ -30,6 +30,6 @@ import org.thingsboard.server.cache.RedisTbTransactionalCache; public class DeviceCredentialsRedisCache extends RedisTbTransactionalCache { public DeviceCredentialsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.DEVICE_CREDENTIALS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.DEVICE_CREDENTIALS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileRedisCache.java index 726f19b74e..86628b4466 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileRedisCache.java @@ -20,7 +20,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.cache.RedisTbTransactionalCache; @@ -30,6 +30,6 @@ import org.thingsboard.server.cache.RedisTbTransactionalCache; public class DeviceProfileRedisCache extends RedisTbTransactionalCache { public DeviceProfileRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.DEVICE_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.DEVICE_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeRedisCache.java index cd788f2695..2c6f4a80ad 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeRedisCache.java @@ -23,13 +23,13 @@ import org.thingsboard.server.cache.TBRedisCacheConfiguration; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.cache.RedisTbTransactionalCache; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @Service("EdgeCache") public class EdgeRedisCache extends RedisTbTransactionalCache { public EdgeRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.EDGE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.EDGE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/count/EntityCountRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/entity/count/EntityCountRedisCache.java index af431f3085..791921bbba 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/count/EntityCountRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/count/EntityCountRedisCache.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.dao.entity.EntityCountCacheKey; @@ -30,6 +30,6 @@ import org.thingsboard.server.dao.entity.EntityCountCacheKey; public class EntityCountRedisCache extends RedisTbTransactionalCache { public EntityCountRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.ENTITY_COUNT_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.ENTITY_COUNT_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewRedisCache.java index 9343b4a205..9234ea57d5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewRedisCache.java @@ -22,13 +22,13 @@ import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.TBRedisCacheConfiguration; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.cache.RedisTbTransactionalCache; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @Service("EntityViewCache") public class EntityViewRedisCache extends RedisTbTransactionalCache { public EntityViewRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.ENTITY_VIEW_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.ENTITY_VIEW_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageRedisCache.java index 69ff998712..11c13eabca 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/ota/OtaPackageRedisCache.java @@ -20,7 +20,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.OtaPackageInfo; import org.thingsboard.server.cache.RedisTbTransactionalCache; @@ -30,6 +30,6 @@ import org.thingsboard.server.cache.RedisTbTransactionalCache; public class OtaPackageRedisCache extends RedisTbTransactionalCache { public OtaPackageRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.OTA_PACKAGE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.OTA_PACKAGE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationRedisCache.java index 35b52d7fe1..0154b1d9e1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/RelationRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/RelationRedisCache.java @@ -20,7 +20,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.cache.RedisTbTransactionalCache; @@ -29,6 +29,6 @@ import org.thingsboard.server.cache.RedisTbTransactionalCache; public class RelationRedisCache extends RedisTbTransactionalCache { public RelationRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.RELATIONS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.RELATIONS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantExistsRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantExistsRedisCache.java index 9cd5ba18cb..3c223cbd36 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantExistsRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantExistsRedisCache.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.id.TenantId; @@ -30,6 +30,6 @@ import org.thingsboard.server.common.data.id.TenantId; public class TenantExistsRedisCache extends RedisTbTransactionalCache { public TenantExistsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.TENANTS_EXIST_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.TENANTS_EXIST_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileRedisCache.java index 302006fa00..4cf47f9a62 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileRedisCache.java @@ -23,13 +23,13 @@ import org.thingsboard.server.cache.TBRedisCacheConfiguration; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.cache.RedisTbTransactionalCache; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis") @Service("TenantProfileCache") public class TenantProfileRedisCache extends RedisTbTransactionalCache { public TenantProfileRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.TENANT_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.TENANT_PROFILE_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantRedisCache.java index 29ebcd9767..e9b225866b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantRedisCache.java @@ -21,7 +21,7 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.TenantId; @@ -31,6 +31,6 @@ import org.thingsboard.server.common.data.id.TenantId; public class TenantRedisCache extends RedisTbTransactionalCache { public TenantRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.TENANTS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.TENANTS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsRedisCache.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsRedisCache.java index de321f3eb9..384336006e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsRedisCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsRedisCache.java @@ -21,9 +21,8 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.cache.CacheSpecsMap; import org.thingsboard.server.cache.RedisTbTransactionalCache; import org.thingsboard.server.cache.TBRedisCacheConfiguration; -import org.thingsboard.server.cache.TbFSTRedisSerializer; +import org.thingsboard.server.cache.TbJavaRedisSerializer; import org.thingsboard.server.common.data.CacheConstants; -import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.settings.UserSettings; import org.thingsboard.server.common.data.settings.UserSettingsCompositeKey; @@ -32,6 +31,6 @@ import org.thingsboard.server.common.data.settings.UserSettingsCompositeKey; public class UserSettingsRedisCache extends RedisTbTransactionalCache { public UserSettingsRedisCache(TBRedisCacheConfiguration configuration, CacheSpecsMap cacheSpecsMap, RedisConnectionFactory connectionFactory) { - super(CacheConstants.USER_SETTINGS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbFSTRedisSerializer<>()); + super(CacheConstants.USER_SETTINGS_CACHE, cacheSpecsMap, connectionFactory, configuration, new TbJavaRedisSerializer<>()); } } diff --git a/pom.xml b/pom.xml index f78a4826bc..6e6500c742 100755 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ 3.21.9 1.42.1 1.0.6 - 1.18.18 + 1.18.26 1.2.4 1.2.5 4.1.91.Final @@ -100,12 +100,12 @@ 5.0.2 0.2.1 + 15.4 3.2.0 4.1.1 - 2.57 2.7.7 2.0 1.11.747 @@ -607,7 +607,7 @@ maven-compiler-plugin 3.8.1 - 11 + 17 -Xlint:deprecation -Xlint:removal @@ -664,6 +664,7 @@ --illegal-access=permit -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=20 + --add-opens java.base/java.lang.reflect=ALL-UNNAMED @@ -1797,11 +1798,6 @@ bucket4j-core ${bucket4j.version} - - de.ruedigermoeller - fst - ${fst.version} - org.locationtech.spatial4j spatial4j @@ -2007,6 +2003,11 @@ oshi-core ${oshi.version} + + org.openjdk.nashorn + nashorn-core + ${nashorn-core.version} + From 9add2962a64e6c1eb139d77802d09306a6ee0072 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 10 May 2023 18:20:36 +0300 Subject: [PATCH 004/397] Push-notifications to mobile --- application/pom.xml | 4 + .../controller/SystemInfoController.java | 2 +- .../channels/MobileNotificationChannel.java | 109 ++++++++++++++++++ .../NotificationDeliveryMethod.java | 3 +- ...obileNotificationDeliveryMethodConfig.java | 35 ++++++ .../NotificationDeliveryMethodConfig.java | 3 +- .../targets/NotificationTargetType.java | 2 +- .../DeliveryMethodNotificationTemplate.java | 3 +- ...ileDeliveryMethodNotificationTemplate.java | 56 +++++++++ pom.xml | 6 + 10 files changed, 218 insertions(+), 5 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/notification/channels/MobileNotificationChannel.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/MobileNotificationDeliveryMethodConfig.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileDeliveryMethodNotificationTemplate.java diff --git a/application/pom.xml b/application/pom.xml index 3093dcfb57..f76a0709c7 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -354,6 +354,10 @@ com.slack.api slack-api-client + + com.google.firebase + firebase-admin + diff --git a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java index e586f079ca..86131b41af 100644 --- a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java +++ b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java @@ -149,7 +149,7 @@ public class SystemInfoController extends BaseController { infoObject.put("artifact", buildProperties.getArtifact()); infoObject.put("name", buildProperties.getName()); } else { - infoObject.put("version", "unknown"); + infoObject.put("version", "3.5.5"); } return infoObject; } diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileNotificationChannel.java new file mode 100644 index 0000000000..75ff7866ab --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileNotificationChannel.java @@ -0,0 +1,109 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.notification.channels; + +import com.fasterxml.jackson.databind.JsonNode; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; +import com.google.firebase.messaging.FirebaseMessaging; +import com.google.firebase.messaging.Message; +import com.google.firebase.messaging.Notification; +import lombok.RequiredArgsConstructor; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; +import org.thingsboard.server.common.data.notification.settings.MobileNotificationDeliveryMethodConfig; +import org.thingsboard.server.common.data.notification.settings.NotificationSettings; +import org.thingsboard.server.common.data.notification.template.MobileDeliveryMethodNotificationTemplate; +import org.thingsboard.server.dao.notification.NotificationSettingsService; +import org.thingsboard.server.service.executors.ExternalCallExecutorService; +import org.thingsboard.server.service.notification.NotificationProcessingContext; + +import java.nio.charset.StandardCharsets; +import java.util.Optional; + +@Component +@RequiredArgsConstructor +public class MobileNotificationChannel implements NotificationChannel { + + private final ExternalCallExecutorService executor; + private final NotificationSettingsService notificationSettingsService; + + @Override + public ListenableFuture sendNotification(User recipient, MobileDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) { + String fcmToken = Optional.ofNullable(recipient.getAdditionalInfo()) + .map(info -> info.get("fcmToken")).filter(JsonNode::isTextual).map(JsonNode::asText) + .orElse(null); + if (StringUtils.isEmpty(fcmToken)) { + return Futures.immediateFailedFuture(new RuntimeException("User doesn't have the mobile app installed")); + } + + MobileNotificationDeliveryMethodConfig config = ctx.getDeliveryMethodConfig(NotificationDeliveryMethod.MOBILE); + return executor.submit(() -> { + FirebaseOptions firebaseOptions = FirebaseOptions.builder() + .setCredentials(GoogleCredentials.fromStream(IOUtils.toInputStream(config.getFirebaseServiceAccountCredentials(), StandardCharsets.UTF_8))) + .build(); + String appName = ctx.getTenantId().toString(); + + FirebaseApp firebaseApp = FirebaseApp.getApps().stream() + .filter(app -> app.getName().equals(appName)) + .findFirst().orElseGet(() -> { + try { + return FirebaseApp.initializeApp(firebaseOptions, appName); + } catch (IllegalStateException e) { + return FirebaseApp.getInstance(appName); + } + }); + FirebaseMessaging firebaseMessaging; + try { + firebaseMessaging = FirebaseMessaging.getInstance(firebaseApp); + } catch (IllegalArgumentException e) { + // because of concurrency issues: FirebaseMessaging.getInstance lazily loads FirebaseMessagingService + firebaseMessaging = FirebaseMessaging.getInstance(firebaseApp); + } + + Message message = Message.builder() + .setNotification(Notification.builder() + .setTitle(processedTemplate.getSubject()) + .setBody(processedTemplate.getBody()) + .build()) + .setToken(fcmToken) + .build(); + firebaseMessaging.send(message); + return null; + }); + } + + @Override + public void check(TenantId tenantId) throws Exception { + NotificationSettings settings = notificationSettingsService.findNotificationSettings(tenantId); + if (!settings.getDeliveryMethodsConfigs().containsKey(NotificationDeliveryMethod.MOBILE)) { + throw new RuntimeException("Push-notifications to mobile are not configured"); + } + } + + @Override + public NotificationDeliveryMethod getDeliveryMethod() { + return NotificationDeliveryMethod.MOBILE; + } + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java index 4a2c4657d5..5b9e84d37d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java @@ -24,7 +24,8 @@ public enum NotificationDeliveryMethod { WEB("web"), EMAIL("email"), SMS("SMS"), - SLACK("Slack"); + SLACK("Slack"), + MOBILE("mobile"); @Getter private final String name; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/MobileNotificationDeliveryMethodConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/MobileNotificationDeliveryMethodConfig.java new file mode 100644 index 0000000000..4e443227ee --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/MobileNotificationDeliveryMethodConfig.java @@ -0,0 +1,35 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.notification.settings; + +import lombok.Data; +import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; + +import javax.validation.constraints.NotEmpty; + +@Data +public class MobileNotificationDeliveryMethodConfig implements NotificationDeliveryMethodConfig { + + private String firebaseServiceAccountCredentialsFileName; + @NotEmpty + private String firebaseServiceAccountCredentials; + + @Override + public NotificationDeliveryMethod getMethod() { + return NotificationDeliveryMethod.MOBILE; + } + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationDeliveryMethodConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationDeliveryMethodConfig.java index 962eba6d06..28020d6c4e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationDeliveryMethodConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationDeliveryMethodConfig.java @@ -27,7 +27,8 @@ import java.io.Serializable; @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "method") @JsonSubTypes({ - @Type(name = "SLACK", value = SlackNotificationDeliveryMethodConfig.class) + @Type(name = "SLACK", value = SlackNotificationDeliveryMethodConfig.class), + @Type(name = "MOBILE", value = MobileNotificationDeliveryMethodConfig.class) }) public interface NotificationDeliveryMethodConfig extends Serializable { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetType.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetType.java index 1254654ecf..2180679cb2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetType.java @@ -25,7 +25,7 @@ import java.util.Set; @RequiredArgsConstructor public enum NotificationTargetType { - PLATFORM_USERS(Set.of(NotificationDeliveryMethod.WEB, NotificationDeliveryMethod.EMAIL, NotificationDeliveryMethod.SMS)), + PLATFORM_USERS(Set.of(NotificationDeliveryMethod.WEB, NotificationDeliveryMethod.EMAIL, NotificationDeliveryMethod.SMS, NotificationDeliveryMethod.MOBILE)), SLACK(Set.of(NotificationDeliveryMethod.SLACK)); @Getter diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java index ecb7f2d2b6..f033fe5092 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java @@ -33,7 +33,8 @@ import javax.validation.constraints.NotEmpty; @Type(name = "WEB", value = WebDeliveryMethodNotificationTemplate.class), @Type(name = "EMAIL", value = EmailDeliveryMethodNotificationTemplate.class), @Type(name = "SMS", value = SmsDeliveryMethodNotificationTemplate.class), - @Type(name = "SLACK", value = SlackDeliveryMethodNotificationTemplate.class) + @Type(name = "SLACK", value = SlackDeliveryMethodNotificationTemplate.class), + @Type(name = "MOBILE", value = MobileDeliveryMethodNotificationTemplate.class) }) @Data @NoArgsConstructor diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileDeliveryMethodNotificationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileDeliveryMethodNotificationTemplate.java new file mode 100644 index 0000000000..91786db48a --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileDeliveryMethodNotificationTemplate.java @@ -0,0 +1,56 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.notification.template; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.apache.commons.lang3.StringUtils; +import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; + +import javax.validation.constraints.NotEmpty; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MobileDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate implements HasSubject { + + @NotEmpty + private String subject; + + public MobileDeliveryMethodNotificationTemplate(MobileDeliveryMethodNotificationTemplate other) { + super(other); + this.subject = other.subject; + } + + @Override + public NotificationDeliveryMethod getMethod() { + return NotificationDeliveryMethod.MOBILE; + } + + @Override + public MobileDeliveryMethodNotificationTemplate copy() { + return new MobileDeliveryMethodNotificationTemplate(this); + } + + @Override + public boolean containsAny(String... params) { + return super.containsAny(params) || StringUtils.containsAny(subject, params); + } + +} diff --git a/pom.xml b/pom.xml index f78a4826bc..f58e80480a 100755 --- a/pom.xml +++ b/pom.xml @@ -150,6 +150,7 @@ 2.21.0 2.12.0 1.12.1 + 8.0.1 3.4.0 @@ -1987,6 +1988,11 @@ slack-api-client ${slack-api.version} + + com.google.firebase + firebase-admin + ${firebase-admin.version} + org.eclipse.jgit org.eclipse.jgit From 1c624949737d4c006558f644196077f4a39a30ef Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 10 May 2023 18:20:58 +0300 Subject: [PATCH 005/397] UI: push-notifications to mobile --- .../pages/admin/sms-provider.component.html | 25 ++++++++++- .../pages/admin/sms-provider.component.ts | 18 +++++--- .../sent-notification-dialog.component.html | 43 +++++++++++++++++++ .../sent/sent-notification-dialog.componet.ts | 3 +- .../template/template-configuration.ts | 9 +++- ...emplate-notification-dialog.component.html | 26 +++++++++++ .../app/shared/models/notification.models.ts | 19 ++++++-- .../assets/locale/locale.constant-en_US.json | 9 +++- 8 files changed, 135 insertions(+), 17 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.html b/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.html index 0ea223e8b8..0f21bd0fd9 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.html @@ -58,7 +58,7 @@
-
+
@@ -66,8 +66,29 @@
+
+
+
+ + + admin.mobile-settings + + + + + +
+
+
+ + +
-
diff --git a/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.ts b/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.ts index e56f02c4e4..99eea3ab23 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.ts @@ -42,7 +42,7 @@ export class SmsProviderComponent extends PageComponent implements HasConfirmFor smsProvider: FormGroup; private adminSettings: AdminSettings; - slackSettingsForm: FormGroup; + notificationSettingsForm: FormGroup; private notificationSettings: NotificationSettings; private readonly authUser: AuthUser; @@ -60,7 +60,7 @@ export class SmsProviderComponent extends PageComponent implements HasConfirmFor this.notificationService.getNotificationSettings().subscribe( (settings) => { this.notificationSettings = settings; - this.slackSettingsForm.reset(this.notificationSettings); + this.notificationSettingsForm.reset(this.notificationSettings); } ); if (this.isSysAdmin()) { @@ -108,24 +108,28 @@ export class SmsProviderComponent extends PageComponent implements HasConfirmFor } confirmForm(): FormGroup { - return this.smsProvider.dirty ? this.smsProvider : this.slackSettingsForm; + return this.smsProvider.dirty ? this.smsProvider : this.notificationSettingsForm; } private buildGeneralServerSettingsForm() { - this.slackSettingsForm = this.fb.group({ + this.notificationSettingsForm = this.fb.group({ deliveryMethodsConfigs: this.fb.group({ SLACK: this.fb.group({ botToken: [''] + }), + MOBILE: this.fb.group({ + firebaseServiceAccountCredentialsFileName: [''], + firebaseServiceAccountCredentials: [''] }) }) }); - this.registerDisableOnLoadFormControl(this.slackSettingsForm.get('deliveryMethodsConfigs')); + this.registerDisableOnLoadFormControl(this.notificationSettingsForm.get('deliveryMethodsConfigs')); } saveNotification(): void { this.notificationSettings = deepTrim({ ...this.notificationSettings, - ...this.slackSettingsForm.value + ...this.notificationSettingsForm.value }); // eslint-disable-next-line guard-for-in for (const method in this.notificationSettings.deliveryMethodsConfigs) { @@ -138,7 +142,7 @@ export class SmsProviderComponent extends PageComponent implements HasConfirmFor } this.notificationService.saveNotificationSettings(this.notificationSettings).subscribe(setting => { this.notificationSettings = setting; - this.slackSettingsForm.reset(this.notificationSettings); + this.notificationSettingsForm.reset(this.notificationSettings); }); } diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html index 27b8968344..e5ebab3947 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html @@ -334,6 +334,40 @@ + + {{ 'notification.delivery-method.mobile' | translate }} +
+ {{ 'notification.input-field-support-templatization' | translate}} + +
+
+ + notification.subject + + + {{ 'notification.subject-required' | translate }} + + + + notification.message + + + {{ 'notification.message-required' | translate }} + + +
+
{{ 'notification.review' | translate }} +
+
+ +
notification.delivery-method.mobile-preview
+
+
+ {{ preview.processedTemplates.MOBILE.body }} +
+
supervisor_account diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts index 4846cd063d..938ec2756f 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts @@ -315,7 +315,7 @@ export class SentNotificationDialogComponent extends if(this.isSysAdmin()) { return true; } else if (this.isTenantAdmin()) { - return deliveryMethod === NotificationDeliveryMethod.SLACK; + return deliveryMethod === NotificationDeliveryMethod.SLACK || deliveryMethod === NotificationDeliveryMethod.MOBILE; } return false; } @@ -330,6 +330,7 @@ export class SentNotificationDialogComponent extends return '/settings/outgoing-mail'; case NotificationDeliveryMethod.SMS: case NotificationDeliveryMethod.SLACK: + case NotificationDeliveryMethod.MOBILE: return '/settings/notifications'; } } diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-configuration.ts b/ui-ngx/src/app/modules/home/pages/notification/template/template-configuration.ts index b3fa00ef72..90115738a6 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-configuration.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-configuration.ts @@ -43,6 +43,7 @@ export abstract class TemplateConfiguration extends DialogComponent< emailTemplateForm: FormGroup; smsTemplateForm: FormGroup; slackTemplateForm: FormGroup; + mobileTemplateForm: FormGroup; notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[]; notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap; @@ -163,11 +164,17 @@ export abstract class TemplateConfiguration extends DialogComponent< body: ['', Validators.required] }); + this.mobileTemplateForm = this.fb.group({ + subject: ['', Validators.required], + body: ['', Validators.required] + }); + this.deliveryMethodFormsMap = new Map([ [NotificationDeliveryMethod.WEB, this.webTemplateForm], [NotificationDeliveryMethod.EMAIL, this.emailTemplateForm], [NotificationDeliveryMethod.SMS, this.smsTemplateForm], - [NotificationDeliveryMethod.SLACK, this.slackTemplateForm] + [NotificationDeliveryMethod.SLACK, this.slackTemplateForm], + [NotificationDeliveryMethod.MOBILE, this.mobileTemplateForm] ]); } diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html index 067258fa24..1a623af7b9 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html @@ -259,6 +259,32 @@ + + {{ 'notification.delivery-method.mobile' | translate }} +
+ {{ 'notification.input-field-support-templatization' | translate}} + +
+
+ + notification.message + + + {{ 'notification.message-required' | translate }} + + +
+
diff --git a/ui-ngx/src/app/shared/models/notification.models.ts b/ui-ngx/src/app/shared/models/notification.models.ts index fe554ba7f2..55dcb35b66 100644 --- a/ui-ngx/src/app/shared/models/notification.models.ts +++ b/ui-ngx/src/app/shared/models/notification.models.ts @@ -89,7 +89,7 @@ export interface NotificationSettings { deliveryMethodsConfigs: { [key in NotificationDeliveryMethod]: NotificationDeliveryMethodConfig }; } -export interface NotificationDeliveryMethodConfig extends Partial{ +export interface NotificationDeliveryMethodConfig extends Partial{ enabled: boolean; method: NotificationDeliveryMethod; } @@ -98,6 +98,10 @@ interface SlackNotificationDeliveryMethodConfig { botToken: string; } +interface MobileNotificationDeliveryMethodConfig { + firebaseServiceAccountCredentials: string; +} + export interface SlackConversation { id: string; title: string; @@ -292,7 +296,8 @@ interface NotificationTemplateConfig { } export interface DeliveryMethodNotificationTemplate extends - Partial{ + Partial { body?: string; enabled: boolean; method: NotificationDeliveryMethod; @@ -329,6 +334,10 @@ interface SlackDeliveryMethodNotificationTemplate { conversationId: string; } +interface MobileDeliveryMethodNotificationTemplate { + subject: string; +} + export enum NotificationStatus { SENT = 'SENT', READ = 'READ' @@ -338,14 +347,16 @@ export enum NotificationDeliveryMethod { WEB = 'WEB', SMS = 'SMS', EMAIL = 'EMAIL', - SLACK = 'SLACK' + SLACK = 'SLACK', + MOBILE = 'MOBILE' } export const NotificationDeliveryMethodTranslateMap = new Map([ [NotificationDeliveryMethod.WEB, 'notification.delivery-method.web'], [NotificationDeliveryMethod.SMS, 'notification.delivery-method.sms'], [NotificationDeliveryMethod.EMAIL, 'notification.delivery-method.email'], - [NotificationDeliveryMethod.SLACK, 'notification.delivery-method.slack'] + [NotificationDeliveryMethod.SLACK, 'notification.delivery-method.slack'], + [NotificationDeliveryMethod.MOBILE, 'notification.delivery-method.mobile'] ]); export enum NotificationRequestStatus { 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 bcaa4a183f..14734c1a57 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -420,7 +420,10 @@ "notifications-settings": "Notifications settings", "slack-api-token": "Slack API token", "slack": "Slack", - "slack-settings": "Slack settings" + "slack-settings": "Slack settings", + "mobile-settings": "Mobile settings", + "firebase-service-account-file": "Firebase service account credentials JSON file", + "select-firebase-service-account-file": "Drag and drop your Firebase service account credentials file or " }, "alarm": { "alarm": "Alarm", @@ -2847,7 +2850,9 @@ "sms": "SMS", "sms-preview": "SMS notification preview", "web": "Web", - "web-preview": "Web notification preview" + "web-preview": "Web notification preview", + "mobile": "Mobile", + "mobile-preview": "Mobile notification preview" }, "delivery-method-not-configure-click": "Delivery method is not configured. Click to setup.", "delivery-method-not-configure-contact": "Delivery method is not configured. Contact your system administrator.", From 592ab5858bc704005644a873e3f6d91fe8c244af Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Thu, 11 May 2023 11:41:27 +0300 Subject: [PATCH 006/397] Revert SystemInfoController changes --- .../org/thingsboard/server/controller/SystemInfoController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java index 86131b41af..e586f079ca 100644 --- a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java +++ b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java @@ -149,7 +149,7 @@ public class SystemInfoController extends BaseController { infoObject.put("artifact", buildProperties.getArtifact()); infoObject.put("name", buildProperties.getName()); } else { - infoObject.put("version", "3.5.5"); + infoObject.put("version", "unknown"); } return infoObject; } From 184900761059a96a55776ac76b5952b3e4e32dd4 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Fri, 19 May 2023 19:08:03 +0200 Subject: [PATCH 007/397] msa and packaging java 17 support --- msa/monitoring/docker/Dockerfile | 2 +- msa/tb-node/docker/Dockerfile | 4 ++-- msa/tb/docker-cassandra/Dockerfile | 2 +- msa/tb/docker-postgres/Dockerfile | 2 +- msa/transport/coap/docker/Dockerfile | 2 +- msa/transport/http/docker/Dockerfile | 2 +- msa/transport/lwm2m/docker/Dockerfile | 2 +- msa/transport/mqtt/docker/Dockerfile | 2 +- msa/transport/snmp/docker/Dockerfile | 2 +- msa/vc-executor-docker/docker/Dockerfile | 2 +- packaging/java/build.gradle | 4 ++-- packaging/java/scripts/windows/install.bat | 6 +++--- pom.xml | 4 ++-- 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/msa/monitoring/docker/Dockerfile b/msa/monitoring/docker/Dockerfile index 5da050eb91..14c6246280 100644 --- a/msa/monitoring/docker/Dockerfile +++ b/msa/monitoring/docker/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim COPY start-tb-monitoring.sh ${pkg.name}.deb /tmp/ diff --git a/msa/tb-node/docker/Dockerfile b/msa/tb-node/docker/Dockerfile index 68e428992a..2c8af18f9a 100644 --- a/msa/tb-node/docker/Dockerfile +++ b/msa/tb-node/docker/Dockerfile @@ -14,11 +14,11 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim COPY start-tb-node.sh ${pkg.name}.deb /tmp/ -RUN echo 'networkaddress.cache.ttl=60' >> /etc/java-11-openjdk/security/java.security \ +RUN echo 'networkaddress.cache.ttl=60' >> /etc/java-17-openjdk/security/java.security \ && chmod a+x /tmp/*.sh \ && mv /tmp/start-tb-node.sh /usr/bin && \ (yes | dpkg -i /tmp/${pkg.name}.deb) && \ diff --git a/msa/tb/docker-cassandra/Dockerfile b/msa/tb/docker-cassandra/Dockerfile index 2f23aec399..f871d57ff8 100644 --- a/msa/tb/docker-cassandra/Dockerfile +++ b/msa/tb/docker-cassandra/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim ENV PG_MAJOR=12 diff --git a/msa/tb/docker-postgres/Dockerfile b/msa/tb/docker-postgres/Dockerfile index 1c25624adf..2520bee62b 100644 --- a/msa/tb/docker-postgres/Dockerfile +++ b/msa/tb/docker-postgres/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim ENV PG_MAJOR 12 diff --git a/msa/transport/coap/docker/Dockerfile b/msa/transport/coap/docker/Dockerfile index 1786e93cb2..526a8620a8 100644 --- a/msa/transport/coap/docker/Dockerfile +++ b/msa/transport/coap/docker/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim COPY start-tb-coap-transport.sh ${pkg.name}.deb /tmp/ diff --git a/msa/transport/http/docker/Dockerfile b/msa/transport/http/docker/Dockerfile index 0ba4f713b0..399df84000 100644 --- a/msa/transport/http/docker/Dockerfile +++ b/msa/transport/http/docker/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim COPY start-tb-http-transport.sh ${pkg.name}.deb /tmp/ diff --git a/msa/transport/lwm2m/docker/Dockerfile b/msa/transport/lwm2m/docker/Dockerfile index c9270dd4f3..d17f368c8f 100644 --- a/msa/transport/lwm2m/docker/Dockerfile +++ b/msa/transport/lwm2m/docker/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim COPY start-tb-lwm2m-transport.sh ${pkg.name}.deb /tmp/ diff --git a/msa/transport/mqtt/docker/Dockerfile b/msa/transport/mqtt/docker/Dockerfile index 2037d629bb..769164b86e 100644 --- a/msa/transport/mqtt/docker/Dockerfile +++ b/msa/transport/mqtt/docker/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim COPY start-tb-mqtt-transport.sh ${pkg.name}.deb /tmp/ diff --git a/msa/transport/snmp/docker/Dockerfile b/msa/transport/snmp/docker/Dockerfile index 9edb97fbc4..2835c56bc7 100644 --- a/msa/transport/snmp/docker/Dockerfile +++ b/msa/transport/snmp/docker/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim COPY start-tb-snmp-transport.sh ${pkg.name}.deb /tmp/ diff --git a/msa/vc-executor-docker/docker/Dockerfile b/msa/vc-executor-docker/docker/Dockerfile index 653a5f2d35..70a3d3e18f 100644 --- a/msa/vc-executor-docker/docker/Dockerfile +++ b/msa/vc-executor-docker/docker/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM thingsboard/openjdk11:bullseye-slim +FROM thingsboard/openjdk17:bullseye-slim COPY start-tb-vc-executor.sh ${pkg.name}.deb /tmp/ diff --git a/packaging/java/build.gradle b/packaging/java/build.gradle index d4aa399d70..86dc908426 100644 --- a/packaging/java/build.gradle +++ b/packaging/java/build.gradle @@ -92,7 +92,7 @@ buildRpm { archiveVersion = projectVersion.replace('-', '') archiveFileName = "${pkgName}.rpm" - requires("java-11") + requires("java-17") from("${buildDir}/conf") { include "${pkgName}.conf" @@ -131,7 +131,7 @@ buildDeb { archiveFileName = "${pkgName}.deb" - requires("openjdk-11-jre").or("java11-runtime").or("oracle-java11-installer").or("openjdk-11-jre-headless") + requires("openjdk-17-jre").or("java17-runtime").or("oracle-java17-installer").or("openjdk-17-jre-headless") from("${buildDir}/conf") { include "${pkgName}.conf" diff --git a/packaging/java/scripts/windows/install.bat b/packaging/java/scripts/windows/install.bat index 6f168c76d8..5f71149c83 100644 --- a/packaging/java/scripts/windows/install.bat +++ b/packaging/java/scripts/windows/install.bat @@ -11,7 +11,7 @@ if %jver% NEQ 110 GOTO JAVA_NOT_INSTALLED :JAVA_INSTALLED -@ECHO Java 11 found! +@ECHO Java 17 found! @ECHO Installing thingsboard ... SET loadDemo=false @@ -50,8 +50,8 @@ POPD GOTO END :JAVA_NOT_INSTALLED -@ECHO Java 11 is not installed. Only Java 11 is supported -@ECHO Please go to https://adoptopenjdk.net/index.html and install Java 11. Then retry installation. +@ECHO Java 17 is not installed. Only Java 17 is supported +@ECHO Please go to https://adoptopenjdk.net/index.html and install Java 17. Then retry installation. PAUSE GOTO END diff --git a/pom.xml b/pom.xml index 825138a8dd..4d456b8f4e 100755 --- a/pom.xml +++ b/pom.xml @@ -605,7 +605,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.11.0 17 @@ -650,7 +650,7 @@ org.thingsboard gradle-maven-plugin - 1.0.11 + 1.0.12 com.github.eirslett From 3caae012d65b1cbf0ec98a3baaac8de947951049 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Fri, 19 May 2023 19:39:45 +0200 Subject: [PATCH 008/397] minor improvements --- common/util/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/util/pom.xml b/common/util/pom.xml index df09e302ba..14ae1748b2 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -92,6 +92,10 @@ com.github.oshi oshi-core + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + From 2a1259570bc06f63ec008d2a99c1f1434d78a34d Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Mon, 29 May 2023 13:43:10 +0300 Subject: [PATCH 009/397] Temporary version set to 3.5.2-SNAPSHOT to merge --- application/pom.xml | 2 +- common/actor/pom.xml | 2 +- common/cache/pom.xml | 2 +- common/cluster-api/pom.xml | 2 +- common/coap-server/pom.xml | 2 +- common/dao-api/pom.xml | 2 +- common/data/pom.xml | 2 +- common/edge-api/pom.xml | 2 +- common/message/pom.xml | 2 +- common/pom.xml | 2 +- common/queue/pom.xml | 2 +- common/script/pom.xml | 2 +- common/script/remote-js-client/pom.xml | 2 +- common/script/script-api/pom.xml | 2 +- common/stats/pom.xml | 2 +- common/transport/coap/pom.xml | 2 +- common/transport/http/pom.xml | 2 +- common/transport/lwm2m/pom.xml | 2 +- common/transport/mqtt/pom.xml | 2 +- common/transport/pom.xml | 2 +- common/transport/snmp/pom.xml | 2 +- common/transport/transport-api/pom.xml | 2 +- common/util/pom.xml | 2 +- common/version-control/pom.xml | 2 +- dao/pom.xml | 2 +- monitoring/pom.xml | 2 +- msa/black-box-tests/pom.xml | 2 +- msa/js-executor/pom.xml | 2 +- msa/monitoring/pom.xml | 2 +- msa/pom.xml | 2 +- msa/tb-node/pom.xml | 2 +- msa/tb/pom.xml | 2 +- msa/transport/coap/pom.xml | 2 +- msa/transport/http/pom.xml | 2 +- msa/transport/lwm2m/pom.xml | 2 +- msa/transport/mqtt/pom.xml | 2 +- msa/transport/pom.xml | 2 +- msa/transport/snmp/pom.xml | 2 +- msa/vc-executor-docker/pom.xml | 2 +- msa/vc-executor/pom.xml | 2 +- msa/web-ui/pom.xml | 2 +- netty-mqtt/pom.xml | 4 ++-- pom.xml | 2 +- rest-client/pom.xml | 2 +- rule-engine/pom.xml | 2 +- rule-engine/rule-engine-api/pom.xml | 2 +- rule-engine/rule-engine-components/pom.xml | 2 +- tools/pom.xml | 2 +- transport/coap/pom.xml | 2 +- transport/http/pom.xml | 2 +- transport/lwm2m/pom.xml | 2 +- transport/mqtt/pom.xml | 2 +- transport/pom.xml | 2 +- transport/snmp/pom.xml | 2 +- ui-ngx/pom.xml | 2 +- 55 files changed, 56 insertions(+), 56 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index 8c3976eb31..8e7c3cd524 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard application diff --git a/common/actor/pom.xml b/common/actor/pom.xml index 2de85be932..b113788a11 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/cache/pom.xml b/common/cache/pom.xml index 440860fda6..0a9141846f 100644 --- a/common/cache/pom.xml +++ b/common/cache/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml index c9fa6d0894..d6954a40f9 100644 --- a/common/cluster-api/pom.xml +++ b/common/cluster-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/coap-server/pom.xml b/common/coap-server/pom.xml index 420fc4dae6..116a94791d 100644 --- a/common/coap-server/pom.xml +++ b/common/coap-server/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index 029c660500..cf825ea637 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/data/pom.xml b/common/data/pom.xml index 677c3dfd25..f4e1fb2756 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/edge-api/pom.xml b/common/edge-api/pom.xml index 60562efbf2..c99a475236 100644 --- a/common/edge-api/pom.xml +++ b/common/edge-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/message/pom.xml b/common/message/pom.xml index e64d4676ce..62e176e675 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index 0edd153a3c..51ca9546b1 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index edd4574bdd..a995d9b4a3 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/script/pom.xml b/common/script/pom.xml index 26f60bd358..7a4304b77a 100644 --- a/common/script/pom.xml +++ b/common/script/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/script/remote-js-client/pom.xml b/common/script/remote-js-client/pom.xml index 8fa852d977..53e222ad76 100644 --- a/common/script/remote-js-client/pom.xml +++ b/common/script/remote-js-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT script org.thingsboard.common.script diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml index c4e069f695..ae5f38f42f 100644 --- a/common/script/script-api/pom.xml +++ b/common/script/script-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT script org.thingsboard.common.script diff --git a/common/stats/pom.xml b/common/stats/pom.xml index 0869243e7a..10d4ea3b95 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index 2ac15d3e42..3e1174362c 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index 8cf3e0efe8..09f822959f 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/lwm2m/pom.xml b/common/transport/lwm2m/pom.xml index 4433eae2b9..f5ee1eea52 100644 --- a/common/transport/lwm2m/pom.xml +++ b/common/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index bb4767640c..e11f923a0b 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/pom.xml b/common/transport/pom.xml index 6879a4924d..4fc43aa3ea 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/snmp/pom.xml b/common/transport/snmp/pom.xml index 1865f498fa..0a615cfd4f 100644 --- a/common/transport/snmp/pom.xml +++ b/common/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.common - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 2e2174e0a9..6840a24ab2 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index df09e302ba..ee32f1e1e9 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/common/version-control/pom.xml b/common/version-control/pom.xml index a8acdf2be9..ae12a413c0 100644 --- a/common/version-control/pom.xml +++ b/common/version-control/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index 4d4dd2a30b..45f49790b0 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard dao diff --git a/monitoring/pom.xml b/monitoring/pom.xml index 399e34092d..cc3a78c04d 100644 --- a/monitoring/pom.xml +++ b/monitoring/pom.xml @@ -21,7 +21,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index 12d36272c0..6413973d7c 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 0bd7bf4d60..fe92a77763 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/monitoring/pom.xml b/msa/monitoring/pom.xml index 1fe43219a0..bb0539ac98 100644 --- a/msa/monitoring/pom.xml +++ b/msa/monitoring/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.5.1-SNAPSHOT + 3.5.2-SNAPSHOT msa diff --git a/msa/pom.xml b/msa/pom.xml index bf4e15d9d4..451466f98a 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index 8437cc35c3..3d39ba285b 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index c85ac88274..31380a4578 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 386b91ea76..7c55ef4322 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index 344219a660..2d02b2f124 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/lwm2m/pom.xml b/msa/transport/lwm2m/pom.xml index 8dfef617cd..7a521a6718 100644 --- a/msa/transport/lwm2m/pom.xml +++ b/msa/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index e1d740c877..4ab24589dd 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index e0bd5a9457..f12564c24f 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/snmp/pom.xml b/msa/transport/snmp/pom.xml index b6a4e15b04..c5b5617f69 100644 --- a/msa/transport/snmp/pom.xml +++ b/msa/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard.msa transport - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT org.thingsboard.msa.transport diff --git a/msa/vc-executor-docker/pom.xml b/msa/vc-executor-docker/pom.xml index 9b6fc493cd..162ae1f801 100644 --- a/msa/vc-executor-docker/pom.xml +++ b/msa/vc-executor-docker/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/vc-executor/pom.xml b/msa/vc-executor/pom.xml index 9bd2befa90..c78b3fd129 100644 --- a/msa/vc-executor/pom.xml +++ b/msa/vc-executor/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index e9500cf5e0..58efe59856 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index 0ae03f3980..d81be2fece 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard netty-mqtt - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index 6c6608785d..98b2e1529a 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index 638dc42009..728ffc5040 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard rest-client diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index fe8cb3fab5..3ebb1f6c76 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 47d13e5658..f8c45d388b 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 34c6e315f7..ac493e79ce 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/tools/pom.xml b/tools/pom.xml index c0b74bb0a9..1cdd789ffb 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index 3b1e0a9e62..d7572a1523 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index 3d4b806d03..3a991911ce 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/lwm2m/pom.xml b/transport/lwm2m/pom.xml index efe76111f3..e8f639ba85 100644 --- a/transport/lwm2m/pom.xml +++ b/transport/lwm2m/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index 75daa483a1..85ea0c86f1 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index 203ea6cbbb..ad614a8d2c 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard transport diff --git a/transport/snmp/pom.xml b/transport/snmp/pom.xml index c04e7d1f1f..e5ae7ce756 100644 --- a/transport/snmp/pom.xml +++ b/transport/snmp/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT transport diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index d6dc28490f..5b5949a005 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.6.0-SNAPSHOT + 3.5.2-SNAPSHOT thingsboard org.thingsboard From 6b6e27bd60dd770ba7eeeb2d56cdf2d158e4a1a1 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Mon, 29 May 2023 14:07:02 +0300 Subject: [PATCH 010/397] Maven dependency fix --- common/util/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/util/pom.xml b/common/util/pom.xml index df09e302ba..14ae1748b2 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -92,6 +92,10 @@ com.github.oshi oshi-core + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + From 22aaadff858f603df2feebe9154013914385ae57 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Wed, 31 May 2023 17:26:03 +0200 Subject: [PATCH 011/397] jdk 17 for windows --- packaging/java/scripts/windows/install.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/java/scripts/windows/install.bat b/packaging/java/scripts/windows/install.bat index 5f71149c83..b0f6c9b203 100644 --- a/packaging/java/scripts/windows/install.bat +++ b/packaging/java/scripts/windows/install.bat @@ -7,7 +7,7 @@ setlocal ENABLEEXTENSIONS for /f tokens^=2-5^ delims^=.-_^" %%j in ('java -fullversion 2^>^&1') do set "jver=%%j%%k" @ECHO CurrentVersion %jver% -if %jver% NEQ 110 GOTO JAVA_NOT_INSTALLED +if %jver% NEQ 170 GOTO JAVA_NOT_INSTALLED :JAVA_INSTALLED From c9966ef3ef4ce1f5be77109103de2ff9f8416d27 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Fri, 2 Jun 2023 16:27:06 +0300 Subject: [PATCH 012/397] Extracted proto files to a separate module --- .../device/DeviceActorMessageProcessor.java | 27 +-- .../queue/DefaultTbCoreConsumerService.java | 5 +- .../subscription/TbSubscriptionUtils.java | 65 +------- common/cluster-api/pom.xml | 8 +- common/pom.xml | 1 + common/proto/pom.xml | 109 ++++++++++++ .../transport/adaptor/AdaptorException.java | 0 .../transport/adaptor/JsonConverter.java | 0 .../adaptor/JsonConverterConfig.java | 0 .../transport/adaptor/ProtoConverter.java | 0 .../common/transport/util/KvProtoUtil.java | 156 ++++++++++++++++++ .../src/main/proto/jsinvoke.proto | 0 .../src/main/proto/queue.proto | 0 .../src/main/proto/transport.proto | 0 common/queue/pom.xml | 4 + common/transport/transport-api/pom.xml | 9 - pom.xml | 7 + 17 files changed, 292 insertions(+), 99 deletions(-) create mode 100644 common/proto/pom.xml rename common/{transport/transport-api => proto}/src/main/java/org/thingsboard/server/common/transport/adaptor/AdaptorException.java (100%) rename common/{transport/transport-api => proto}/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java (100%) rename common/{transport/transport-api => proto}/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverterConfig.java (100%) rename common/{transport/transport-api => proto}/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java (100%) create mode 100644 common/proto/src/main/java/org/thingsboard/server/common/transport/util/KvProtoUtil.java rename common/{cluster-api => proto}/src/main/proto/jsinvoke.proto (100%) rename common/{cluster-api => proto}/src/main/proto/queue.proto (100%) rename common/{transport/transport-api => proto}/src/main/proto/transport.proto (100%) diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index 934f309480..1831c6ab9c 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -63,6 +63,7 @@ import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; +import org.thingsboard.server.common.transport.util.KvProtoUtil; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; @@ -455,7 +456,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder() .setRequestId(requestId) .setSharedStateMsg(true) - .addAllSharedAttributeList(toTsKvProtos(result)) + .addAllSharedAttributeList(KvProtoUtil.attrToTsKvProtos(result)) .setIsMultipleAttributesRequest(request.getSharedAttributeNamesCount() > 1) .build(); sendToTransport(responseMsg, sessionInfo); @@ -476,8 +477,8 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso public void onSuccess(@Nullable List> result) { GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder() .setRequestId(requestId) - .addAllClientAttributeList(toTsKvProtos(result.get(0))) - .addAllSharedAttributeList(toTsKvProtos(result.get(1))) + .addAllClientAttributeList(KvProtoUtil.attrToTsKvProtos(result.get(0))) + .addAllSharedAttributeList(KvProtoUtil.attrToTsKvProtos(result.get(1))) .setIsMultipleAttributesRequest( request.getSharedAttributeNamesCount() + request.getClientAttributeNamesCount() > 1) .build(); @@ -547,7 +548,7 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso if (DataConstants.SHARED_SCOPE.equals(msg.getScope())) { List attributes = new ArrayList<>(msg.getValues()); if (attributes.size() > 0) { - List sharedUpdated = msg.getValues().stream().map(this::toTsKvProto) + List sharedUpdated = msg.getValues().stream().map(t -> KvProtoUtil.toTsKvProto(t.getLastUpdateTs(), t)) .collect(Collectors.toList()); if (!sharedUpdated.isEmpty()) { notification.addAllSharedUpdated(sharedUpdated); @@ -834,24 +835,6 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso }, systemContext.getDbCallbackExecutor()); } - private List toTsKvProtos(@Nullable List result) { - List clientAttributes; - if (result == null || result.isEmpty()) { - clientAttributes = Collections.emptyList(); - } else { - clientAttributes = new ArrayList<>(result.size()); - for (AttributeKvEntry attrEntry : result) { - clientAttributes.add(toTsKvProto(attrEntry)); - } - } - return clientAttributes; - } - - private TsKvProto toTsKvProto(AttributeKvEntry attrEntry) { - return TsKvProto.newBuilder().setTs(attrEntry.getLastUpdateTs()) - .setKv(toKeyValueProto(attrEntry)).build(); - } - private KeyValueProto toKeyValueProto(KvEntry kvEntry) { KeyValueProto.Builder builder = KeyValueProto.newBuilder(); builder.setKey(kvEntry.getKey()); diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index 2bd0043046..e11b6cdd5b 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -40,6 +40,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; import org.thingsboard.server.common.stats.StatsFactory; +import org.thingsboard.server.common.transport.util.KvProtoUtil; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto; @@ -522,13 +523,13 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService builder.addData(toKeyValueProto(v.getTs(), v).build())); + ts.forEach(v -> builder.addData(KvProtoUtil.toKeyValueProto(v.getTs(), v).build())); SubscriptionMgrMsgProto.Builder msgBuilder = SubscriptionMgrMsgProto.newBuilder(); msgBuilder.setTsUpdate(builder); return ToCoreMsg.newBuilder().setToSubscriptionMgrMsg(msgBuilder.build()).build(); @@ -269,7 +270,7 @@ public class TbSubscriptionUtils { builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); builder.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); builder.setScope(scope); - attributes.forEach(v -> builder.addData(toKeyValueProto(v.getLastUpdateTs(), v).build())); + attributes.forEach(v -> builder.addData(KvProtoUtil.toKeyValueProto(v.getLastUpdateTs(), v).build())); SubscriptionMgrMsgProto.Builder msgBuilder = SubscriptionMgrMsgProto.newBuilder(); msgBuilder.setAttrUpdate(builder); @@ -292,70 +293,10 @@ public class TbSubscriptionUtils { return ToCoreMsg.newBuilder().setToSubscriptionMgrMsg(msgBuilder.build()).build(); } - - private static TsKvProto.Builder toKeyValueProto(long ts, KvEntry attr) { - KeyValueProto.Builder dataBuilder = KeyValueProto.newBuilder(); - dataBuilder.setKey(attr.getKey()); - dataBuilder.setType(KeyValueType.forNumber(attr.getDataType().ordinal())); - switch (attr.getDataType()) { - case BOOLEAN: - attr.getBooleanValue().ifPresent(dataBuilder::setBoolV); - break; - case LONG: - attr.getLongValue().ifPresent(dataBuilder::setLongV); - break; - case DOUBLE: - attr.getDoubleValue().ifPresent(dataBuilder::setDoubleV); - break; - case JSON: - attr.getJsonValue().ifPresent(dataBuilder::setJsonV); - break; - case STRING: - attr.getStrValue().ifPresent(dataBuilder::setStringV); - break; - } - return TsKvProto.newBuilder().setTs(ts).setKv(dataBuilder); - } - public static EntityId toEntityId(String entityType, long entityIdMSB, long entityIdLSB) { return EntityIdFactory.getByTypeAndUuid(entityType, new UUID(entityIdMSB, entityIdLSB)); } - public static List toTsKvEntityList(List dataList) { - List result = new ArrayList<>(dataList.size()); - dataList.forEach(proto -> result.add(new BasicTsKvEntry(proto.getTs(), getKvEntry(proto.getKv())))); - return result; - } - - public static List toAttributeKvList(List dataList) { - List result = new ArrayList<>(dataList.size()); - dataList.forEach(proto -> result.add(new BaseAttributeKvEntry(getKvEntry(proto.getKv()), proto.getTs()))); - return result; - } - - private static KvEntry getKvEntry(KeyValueProto proto) { - KvEntry entry = null; - DataType type = DataType.values()[proto.getType().getNumber()]; - switch (type) { - case BOOLEAN: - entry = new BooleanDataEntry(proto.getKey(), proto.getBoolV()); - break; - case LONG: - entry = new LongDataEntry(proto.getKey(), proto.getLongV()); - break; - case DOUBLE: - entry = new DoubleDataEntry(proto.getKey(), proto.getDoubleV()); - break; - case STRING: - entry = new StringDataEntry(proto.getKey(), proto.getStringV()); - break; - case JSON: - entry = new JsonDataEntry(proto.getKey(), proto.getJsonV()); - break; - } - return entry; - } - public static ToCoreMsg toAlarmUpdateProto(TenantId tenantId, EntityId entityId, AlarmInfo alarm) { TbAlarmUpdateProto.Builder builder = TbAlarmUpdateProto.newBuilder(); builder.setEntityType(entityId.getEntityType().name()); diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml index c9fa6d0894..93cd7c665a 100644 --- a/common/cluster-api/pom.xml +++ b/common/cluster-api/pom.xml @@ -40,6 +40,10 @@ org.thingsboard.common data + + org.thingsboard.common + proto + org.thingsboard.common message @@ -119,10 +123,6 @@ - - org.xolstice.maven.plugins - protobuf-maven-plugin - org.apache.maven.plugins maven-source-plugin diff --git a/common/pom.xml b/common/pom.xml index 0edd153a3c..0c80189acf 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -35,6 +35,7 @@ data + proto util message actor diff --git a/common/proto/pom.xml b/common/proto/pom.xml new file mode 100644 index 0000000000..ab2cdf91c9 --- /dev/null +++ b/common/proto/pom.xml @@ -0,0 +1,109 @@ + + + 4.0.0 + + org.thingsboard + 3.6.0-SNAPSHOT + common + + org.thingsboard.common + proto + jar + + Thingsboard Server Common Protobuf and gRPC structures + https://thingsboard.io + + + UTF-8 + ${basedir}/../.. + + + + + org.thingsboard.common + data + + + org.thingsboard.common + message + + + com.google.protobuf + protobuf-java + + + com.google.protobuf + protobuf-java-util + + + io.grpc + grpc-netty-shaded + provided + + + io.grpc + grpc-protobuf + provided + + + io.grpc + grpc-stub + provided + + + org.springframework.boot + spring-boot-starter-web + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + test + + + org.awaitility + awaitility + test + + + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + + + + + + + thingsboard-repo-deploy + ThingsBoard Repo Deployment + https://repo.thingsboard.io/artifactory/libs-release-public + + + + diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/AdaptorException.java b/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/AdaptorException.java similarity index 100% rename from common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/AdaptorException.java rename to common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/AdaptorException.java diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java b/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java similarity index 100% rename from common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java rename to common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverterConfig.java b/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverterConfig.java similarity index 100% rename from common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverterConfig.java rename to common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverterConfig.java diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java b/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java similarity index 100% rename from common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java rename to common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java diff --git a/common/proto/src/main/java/org/thingsboard/server/common/transport/util/KvProtoUtil.java b/common/proto/src/main/java/org/thingsboard/server/common/transport/util/KvProtoUtil.java new file mode 100644 index 0000000000..172d014460 --- /dev/null +++ b/common/proto/src/main/java/org/thingsboard/server/common/transport/util/KvProtoUtil.java @@ -0,0 +1,156 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.transport.util; + +import org.thingsboard.server.common.data.kv.AttributeKvEntry; +import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; +import org.thingsboard.server.common.data.kv.BasicTsKvEntry; +import org.thingsboard.server.common.data.kv.BooleanDataEntry; +import org.thingsboard.server.common.data.kv.DataType; +import org.thingsboard.server.common.data.kv.DoubleDataEntry; +import org.thingsboard.server.common.data.kv.JsonDataEntry; +import org.thingsboard.server.common.data.kv.KvEntry; +import org.thingsboard.server.common.data.kv.LongDataEntry; +import org.thingsboard.server.common.data.kv.StringDataEntry; +import org.thingsboard.server.common.data.kv.TsKvEntry; +import org.thingsboard.server.gen.transport.TransportProtos; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class KvProtoUtil { + + public static List attrToTsKvProtos(List result) { + List clientAttributes; + if (result == null || result.isEmpty()) { + clientAttributes = Collections.emptyList(); + } else { + clientAttributes = new ArrayList<>(result.size()); + for (AttributeKvEntry attrEntry : result) { + clientAttributes.add(toTsKvProto(attrEntry.getLastUpdateTs(), attrEntry)); + } + } + return clientAttributes; + } + + + public static List tsToTsKvProtos(List result) { + List ts; + if (result == null || result.isEmpty()) { + ts = Collections.emptyList(); + } else { + ts = new ArrayList<>(result.size()); + for (TsKvEntry attrEntry : result) { + ts.add(toTsKvProto(attrEntry.getTs(), attrEntry)); + } + } + return ts; + } + + public static TransportProtos.TsKvProto toTsKvProto(long ts, KvEntry kvEntry) { + return TransportProtos.TsKvProto.newBuilder().setTs(ts) + .setKv(KvProtoUtil.toKeyValueProto(kvEntry)).build(); + } + + public static TransportProtos.KeyValueProto toKeyValueProto(KvEntry kvEntry) { + TransportProtos.KeyValueProto.Builder builder = TransportProtos.KeyValueProto.newBuilder(); + builder.setKey(kvEntry.getKey()); + switch (kvEntry.getDataType()) { + case BOOLEAN: + builder.setType(TransportProtos.KeyValueType.BOOLEAN_V); + builder.setBoolV(kvEntry.getBooleanValue().get()); + break; + case DOUBLE: + builder.setType(TransportProtos.KeyValueType.DOUBLE_V); + builder.setDoubleV(kvEntry.getDoubleValue().get()); + break; + case LONG: + builder.setType(TransportProtos.KeyValueType.LONG_V); + builder.setLongV(kvEntry.getLongValue().get()); + break; + case STRING: + builder.setType(TransportProtos.KeyValueType.STRING_V); + builder.setStringV(kvEntry.getStrValue().get()); + break; + case JSON: + builder.setType(TransportProtos.KeyValueType.JSON_V); + builder.setJsonV(kvEntry.getJsonValue().get()); + break; + } + return builder.build(); + } + + public static TransportProtos.TsKvProto.Builder toKeyValueProto(long ts, KvEntry attr) { + TransportProtos.KeyValueProto.Builder dataBuilder = TransportProtos.KeyValueProto.newBuilder(); + dataBuilder.setKey(attr.getKey()); + dataBuilder.setType(TransportProtos.KeyValueType.forNumber(attr.getDataType().ordinal())); + switch (attr.getDataType()) { + case BOOLEAN: + attr.getBooleanValue().ifPresent(dataBuilder::setBoolV); + break; + case LONG: + attr.getLongValue().ifPresent(dataBuilder::setLongV); + break; + case DOUBLE: + attr.getDoubleValue().ifPresent(dataBuilder::setDoubleV); + break; + case JSON: + attr.getJsonValue().ifPresent(dataBuilder::setJsonV); + break; + case STRING: + attr.getStrValue().ifPresent(dataBuilder::setStringV); + break; + } + return TransportProtos.TsKvProto.newBuilder().setTs(ts).setKv(dataBuilder); + } + + public static List toTsKvEntityList(List dataList) { + List result = new ArrayList<>(dataList.size()); + dataList.forEach(proto -> result.add(new BasicTsKvEntry(proto.getTs(), getKvEntry(proto.getKv())))); + return result; + } + + public static List toAttributeKvList(List dataList) { + List result = new ArrayList<>(dataList.size()); + dataList.forEach(proto -> result.add(new BaseAttributeKvEntry(getKvEntry(proto.getKv()), proto.getTs()))); + return result; + } + + private static KvEntry getKvEntry(TransportProtos.KeyValueProto proto) { + KvEntry entry = null; + DataType type = DataType.values()[proto.getType().getNumber()]; + switch (type) { + case BOOLEAN: + entry = new BooleanDataEntry(proto.getKey(), proto.getBoolV()); + break; + case LONG: + entry = new LongDataEntry(proto.getKey(), proto.getLongV()); + break; + case DOUBLE: + entry = new DoubleDataEntry(proto.getKey(), proto.getDoubleV()); + break; + case STRING: + entry = new StringDataEntry(proto.getKey(), proto.getStringV()); + break; + case JSON: + entry = new JsonDataEntry(proto.getKey(), proto.getJsonV()); + break; + } + return entry; + } +} diff --git a/common/cluster-api/src/main/proto/jsinvoke.proto b/common/proto/src/main/proto/jsinvoke.proto similarity index 100% rename from common/cluster-api/src/main/proto/jsinvoke.proto rename to common/proto/src/main/proto/jsinvoke.proto diff --git a/common/cluster-api/src/main/proto/queue.proto b/common/proto/src/main/proto/queue.proto similarity index 100% rename from common/cluster-api/src/main/proto/queue.proto rename to common/proto/src/main/proto/queue.proto diff --git a/common/transport/transport-api/src/main/proto/transport.proto b/common/proto/src/main/proto/transport.proto similarity index 100% rename from common/transport/transport-api/src/main/proto/transport.proto rename to common/proto/src/main/proto/transport.proto diff --git a/common/queue/pom.xml b/common/queue/pom.xml index edd4574bdd..59e96d210d 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -36,6 +36,10 @@ + + org.thingsboard.common + proto + org.thingsboard.common data diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 2e2174e0a9..b45cd28e52 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -135,13 +135,4 @@ - - - - org.xolstice.maven.plugins - protobuf-maven-plugin - - - - diff --git a/pom.xml b/pom.xml index 9b11160fab..c778ebcaab 100755 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,8 @@ 2016 + 17 + 17 ${basedir} true none @@ -892,6 +894,11 @@ version-control ${project.version} + + org.thingsboard.common + proto + ${project.version} + org.thingsboard.common cache From 4c470583f3467fc7d4a524e95dfa33cfe99a77a4 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Fri, 2 Jun 2023 16:31:38 +0300 Subject: [PATCH 013/397] Correct package name --- .../actors/device/DeviceActorMessageProcessor.java | 2 +- .../server/controller/TelemetryController.java | 2 +- .../rpc/constructor/EntityDataMsgConstructor.java | 2 +- .../telemetry/BaseTelemetryProcessor.java | 2 +- .../queue/DefaultTbCoreConsumerService.java | 2 +- .../service/subscription/TbSubscriptionUtils.java | 14 +------------- .../importing/csv/AbstractBulkImportService.java | 2 +- .../thingsboard/server/edge/DeviceEdgeTest.java | 2 +- .../{transport => }/adaptor/AdaptorException.java | 2 +- .../{transport => }/adaptor/JsonConverter.java | 2 +- .../adaptor/JsonConverterConfig.java | 2 +- .../{transport => }/adaptor/ProtoConverter.java | 2 +- .../common/{transport => }/util/KvProtoUtil.java | 3 +-- .../transport/coap/CoapTransportResource.java | 4 ++-- .../transport/coap/adaptors/CoapAdaptorUtils.java | 2 +- .../coap/adaptors/CoapTransportAdaptor.java | 2 +- .../transport/coap/adaptors/JsonCoapAdaptor.java | 4 ++-- .../transport/coap/adaptors/ProtoCoapAdaptor.java | 6 +++--- .../callback/GetAttributesSyncSessionCallback.java | 2 +- .../callback/ToServerRpcSyncSessionCallback.java | 2 +- .../transport/coap/client/CoapClientContext.java | 2 +- .../coap/client/DefaultCoapClientContext.java | 2 +- .../coap/efento/CoapEfentoTransportResource.java | 2 +- .../coap/efento/adaptor/EfentoCoapAdaptor.java | 4 ++-- .../server/transport/http/DeviceApiController.java | 2 +- .../lwm2m/server/adaptors/LwM2MJsonAdaptor.java | 4 ++-- .../server/adaptors/LwM2MTransportAdaptor.java | 2 +- .../transport/mqtt/MqttTransportHandler.java | 2 +- .../adaptors/BackwardCompatibilityAdaptor.java | 2 +- .../transport/mqtt/adaptors/JsonMqttAdaptor.java | 4 ++-- .../mqtt/adaptors/MqttTransportAdaptor.java | 2 +- .../transport/mqtt/adaptors/ProtoMqttAdaptor.java | 6 +++--- .../session/AbstractGatewaySessionHandler.java | 6 +++--- .../mqtt/session/GatewaySessionHandler.java | 2 +- .../mqtt/session/SparkplugNodeSessionHandler.java | 6 +++--- .../mqtt/util/sparkplug/MetricDataType.java | 2 +- .../snmp/service/SnmpTransportService.java | 2 +- .../src/test/java/JsonConverterTest.java | 2 +- .../action/TbCopyAttributesToEntityViewNode.java | 2 +- .../rule/engine/profile/AlarmRuleState.java | 2 +- .../rule/engine/profile/DeviceState.java | 2 +- .../rule/engine/telemetry/TbMsgAttributesNode.java | 2 +- .../rule/engine/telemetry/TbMsgTimeseriesNode.java | 2 +- 43 files changed, 56 insertions(+), 69 deletions(-) rename common/proto/src/main/java/org/thingsboard/server/common/{transport => }/adaptor/AdaptorException.java (94%) rename common/proto/src/main/java/org/thingsboard/server/common/{transport => }/adaptor/JsonConverter.java (99%) rename common/proto/src/main/java/org/thingsboard/server/common/{transport => }/adaptor/JsonConverterConfig.java (96%) rename common/proto/src/main/java/org/thingsboard/server/common/{transport => }/adaptor/ProtoConverter.java (99%) rename common/proto/src/main/java/org/thingsboard/server/common/{transport => }/util/KvProtoUtil.java (98%) diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index 1831c6ab9c..fc8eaf9e1c 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -63,7 +63,7 @@ import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; import org.thingsboard.server.common.msg.timeout.DeviceActorServerSideRpcTimeoutMsg; -import org.thingsboard.server.common.transport.util.KvProtoUtil; +import org.thingsboard.server.common.util.KvProtoUtil; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index 05f56e93bd..670a65f862 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -74,7 +74,7 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery; import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.exception.InvalidParametersException; import org.thingsboard.server.exception.UncheckedApiException; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java index 242a15ba56..0cef8f3581 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java @@ -27,7 +27,7 @@ import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg; import org.thingsboard.server.gen.edge.v1.EntityDataProto; import org.thingsboard.server.gen.transport.TransportProtos; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java index fece86b92a..ebdf1b6c57 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java @@ -55,7 +55,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.common.msg.session.SessionMsgType; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.common.transport.util.JsonUtils; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.gen.edge.v1.AttributeDeleteMsg; diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index e11b6cdd5b..36799e7fac 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -40,7 +40,7 @@ import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; import org.thingsboard.server.common.stats.StatsFactory; -import org.thingsboard.server.common.transport.util.KvProtoUtil; +import org.thingsboard.server.common.util.KvProtoUtil; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.DeviceStateServiceMsgProto; diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscriptionUtils.java b/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscriptionUtils.java index 7bba9a429a..2f1dca9333 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscriptionUtils.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscriptionUtils.java @@ -22,20 +22,9 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; -import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; -import org.thingsboard.server.common.data.kv.BasicTsKvEntry; -import org.thingsboard.server.common.data.kv.BooleanDataEntry; -import org.thingsboard.server.common.data.kv.DataType; -import org.thingsboard.server.common.data.kv.DoubleDataEntry; -import org.thingsboard.server.common.data.kv.JsonDataEntry; -import org.thingsboard.server.common.data.kv.KvEntry; -import org.thingsboard.server.common.data.kv.LongDataEntry; -import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; -import org.thingsboard.server.common.transport.util.KvProtoUtil; +import org.thingsboard.server.common.util.KvProtoUtil; import org.thingsboard.server.gen.transport.TransportProtos; -import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto; -import org.thingsboard.server.gen.transport.TransportProtos.KeyValueType; import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionMgrMsgProto; import org.thingsboard.server.gen.transport.TransportProtos.TbAlarmDeleteProto; import org.thingsboard.server.gen.transport.TransportProtos.TbAlarmUpdateProto; @@ -52,7 +41,6 @@ import org.thingsboard.server.gen.transport.TransportProtos.TbTimeSeriesSubscrip import org.thingsboard.server.gen.transport.TransportProtos.TbTimeSeriesUpdateProto; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; import org.thingsboard.server.gen.transport.TransportProtos.ToCoreNotificationMsg; -import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto; import org.thingsboard.server.service.ws.notification.sub.NotificationRequestUpdate; import org.thingsboard.server.service.ws.notification.sub.NotificationUpdate; import org.thingsboard.server.service.ws.notification.sub.NotificationsCountSubscription; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java index 45805c5939..bc71505631 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java @@ -46,7 +46,7 @@ import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportColumn import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportRequest; import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportResult; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.controller.BaseController; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.service.action.EntityActionService; diff --git a/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java index 15d5b5c809..d3a8083b4a 100644 --- a/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java @@ -51,7 +51,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.msg.session.FeatureType; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.gen.edge.v1.AttributesRequestMsg; import org.thingsboard.server.gen.edge.v1.DeviceCredentialsRequestMsg; diff --git a/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/AdaptorException.java b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/AdaptorException.java similarity index 94% rename from common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/AdaptorException.java rename to common/proto/src/main/java/org/thingsboard/server/common/adaptor/AdaptorException.java index 8b2908a4b5..1c22163c1f 100644 --- a/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/AdaptorException.java +++ b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/AdaptorException.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.transport.adaptor; +package org.thingsboard.server.common.adaptor; public class AdaptorException extends Exception { diff --git a/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/JsonConverter.java similarity index 99% rename from common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java rename to common/proto/src/main/java/org/thingsboard/server/common/adaptor/JsonConverter.java index 51e74d5097..c51bc784a6 100644 --- a/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java +++ b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/JsonConverter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.transport.adaptor; +package org.thingsboard.server.common.adaptor; import com.google.gson.Gson; import com.google.gson.JsonArray; diff --git a/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverterConfig.java b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/JsonConverterConfig.java similarity index 96% rename from common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverterConfig.java rename to common/proto/src/main/java/org/thingsboard/server/common/adaptor/JsonConverterConfig.java index 0a9df150e5..e160c051f5 100644 --- a/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverterConfig.java +++ b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/JsonConverterConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.transport.adaptor; +package org.thingsboard.server.common.adaptor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; diff --git a/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/ProtoConverter.java similarity index 99% rename from common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java rename to common/proto/src/main/java/org/thingsboard/server/common/adaptor/ProtoConverter.java index 54358709f0..098108c864 100644 --- a/common/proto/src/main/java/org/thingsboard/server/common/transport/adaptor/ProtoConverter.java +++ b/common/proto/src/main/java/org/thingsboard/server/common/adaptor/ProtoConverter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.transport.adaptor; +package org.thingsboard.server.common.adaptor; import com.google.gson.Gson; import com.google.gson.JsonElement; diff --git a/common/proto/src/main/java/org/thingsboard/server/common/transport/util/KvProtoUtil.java b/common/proto/src/main/java/org/thingsboard/server/common/util/KvProtoUtil.java similarity index 98% rename from common/proto/src/main/java/org/thingsboard/server/common/transport/util/KvProtoUtil.java rename to common/proto/src/main/java/org/thingsboard/server/common/util/KvProtoUtil.java index 172d014460..63ef81d35f 100644 --- a/common/proto/src/main/java/org/thingsboard/server/common/transport/util/KvProtoUtil.java +++ b/common/proto/src/main/java/org/thingsboard/server/common/util/KvProtoUtil.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.transport.util; +package org.thingsboard.server.common.util; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; @@ -28,7 +28,6 @@ import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.gen.transport.TransportProtos; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java index 7dde25bfd0..96f4cfecac 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java @@ -35,8 +35,8 @@ import org.thingsboard.server.common.data.security.DeviceTokenCredentials; import org.thingsboard.server.common.msg.session.FeatureType; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.coap.callback.CoapDeviceAuthCallback; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapAdaptorUtils.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapAdaptorUtils.java index 710f18a8b7..629e0380e0 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapAdaptorUtils.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapAdaptorUtils.java @@ -17,7 +17,7 @@ package org.thingsboard.server.transport.coap.adaptors; import org.eclipse.californium.core.coap.Request; import org.thingsboard.server.common.data.StringUtils; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.gen.transport.TransportProtos; import java.util.Arrays; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapTransportAdaptor.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapTransportAdaptor.java index 05a38e1ad1..e88251c93c 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapTransportAdaptor.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/CoapTransportAdaptor.java @@ -19,7 +19,7 @@ import com.google.protobuf.Descriptors; import com.google.protobuf.DynamicMessage; import org.eclipse.californium.core.coap.Request; import org.eclipse.californium.core.coap.Response; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/JsonCoapAdaptor.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/JsonCoapAdaptor.java index d81ff32edd..fffe1a7e1a 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/JsonCoapAdaptor.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/JsonCoapAdaptor.java @@ -29,8 +29,8 @@ import org.eclipse.californium.core.coap.Response; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.coap.CoapTransportResource; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/ProtoCoapAdaptor.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/ProtoCoapAdaptor.java index 4d3b0015ef..5287645591 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/ProtoCoapAdaptor.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/adaptors/ProtoCoapAdaptor.java @@ -28,9 +28,9 @@ import org.eclipse.californium.core.coap.Response; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; -import org.thingsboard.server.common.transport.adaptor.ProtoConverter; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.ProtoConverter; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.coap.CoapTransportResource; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/GetAttributesSyncSessionCallback.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/GetAttributesSyncSessionCallback.java index 907e49f600..caacd31012 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/GetAttributesSyncSessionCallback.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/GetAttributesSyncSessionCallback.java @@ -20,7 +20,7 @@ import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.Request; import org.eclipse.californium.core.coap.Response; import org.eclipse.californium.core.server.resources.CoapExchange; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.coap.client.TbCoapClientState; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/ToServerRpcSyncSessionCallback.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/ToServerRpcSyncSessionCallback.java index 2209ea6613..fc35da0bd6 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/ToServerRpcSyncSessionCallback.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/ToServerRpcSyncSessionCallback.java @@ -19,7 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.Request; import org.eclipse.californium.core.server.resources.CoapExchange; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.coap.client.TbCoapClientState; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/CoapClientContext.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/CoapClientContext.java index 36ef8472de..0ca21fd8cb 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/CoapClientContext.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/CoapClientContext.java @@ -19,7 +19,7 @@ import org.eclipse.californium.core.observe.ObserveRelation; import org.eclipse.californium.core.server.resources.CoapExchange; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.msg.session.SessionMsgType; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.gen.transport.TransportProtos; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java index 3caaba0ba9..95f1698dc3 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java @@ -53,7 +53,7 @@ import org.thingsboard.server.common.transport.SessionMsgListener; import org.thingsboard.server.common.transport.TransportDeviceProfileCache; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.common.transport.auth.SessionInfoCreator; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.gen.transport.TransportProtos; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/CoapEfentoTransportResource.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/CoapEfentoTransportResource.java index 93061d522a..5a59ab0f51 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/CoapEfentoTransportResource.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/CoapEfentoTransportResource.java @@ -31,7 +31,7 @@ import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.device.profile.EfentoCoapDeviceTypeConfiguration; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.common.transport.auth.SessionInfoCreator; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.coap.MeasurementTypeProtos; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/adaptor/EfentoCoapAdaptor.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/adaptor/EfentoCoapAdaptor.java index a6b588139a..42eebe86f1 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/adaptor/EfentoCoapAdaptor.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/efento/adaptor/EfentoCoapAdaptor.java @@ -18,8 +18,8 @@ package org.thingsboard.server.transport.coap.efento.adaptor; import com.google.gson.Gson; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.coap.efento.CoapEfentoTransportResource; diff --git a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java index 041ae0510d..589e93d803 100644 --- a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java +++ b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java @@ -46,7 +46,7 @@ import org.thingsboard.server.common.transport.SessionMsgListener; import org.thingsboard.server.common.transport.TransportContext; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.common.transport.auth.SessionInfoCreator; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.gen.transport.TransportProtos; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java index feb74b47f9..afe1d160ce 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MJsonAdaptor.java @@ -19,8 +19,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonSyntaxException; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MTransportAdaptor.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MTransportAdaptor.java index 96e6008c63..fe24b21053 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MTransportAdaptor.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/adaptors/LwM2MTransportAdaptor.java @@ -16,7 +16,7 @@ package org.thingsboard.server.transport.lwm2m.server.adaptors; import com.google.gson.JsonElement; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.gen.transport.TransportProtos; import java.util.Collection; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index efa5aee965..8347769bd7 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -63,7 +63,7 @@ import org.thingsboard.server.common.msg.tools.TbRateLimitsException; import org.thingsboard.server.common.transport.SessionMsgListener; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.common.transport.auth.SessionInfoCreator; import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/BackwardCompatibilityAdaptor.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/BackwardCompatibilityAdaptor.java index 40be642a1a..73bba60cff 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/BackwardCompatibilityAdaptor.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/BackwardCompatibilityAdaptor.java @@ -21,7 +21,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.ota.OtaPackageType; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionContext; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java index 513fd97cf6..a30749b17d 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/JsonMqttAdaptor.java @@ -30,8 +30,8 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.device.profile.MqttTopics; import org.thingsboard.server.common.data.ota.OtaPackageType; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.mqtt.session.MqttDeviceAwareSessionContext; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/MqttTransportAdaptor.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/MqttTransportAdaptor.java index 3764c2a9a9..10599d0be7 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/MqttTransportAdaptor.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/MqttTransportAdaptor.java @@ -24,7 +24,7 @@ import io.netty.handler.codec.mqtt.MqttMessageType; import io.netty.handler.codec.mqtt.MqttPublishMessage; import io.netty.handler.codec.mqtt.MqttPublishVariableHeader; import org.thingsboard.server.common.data.ota.OtaPackageType; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg; import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeRequestMsg; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java index 39176fa212..c1fba86776 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/adaptors/ProtoMqttAdaptor.java @@ -28,9 +28,9 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.device.profile.MqttTopics; import org.thingsboard.server.common.data.ota.OtaPackageType; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; -import org.thingsboard.server.common.transport.adaptor.ProtoConverter; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.ProtoConverter; import org.thingsboard.server.gen.transport.TransportApiProtos; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java index 95603e751c..9a7e6c5177 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java @@ -39,9 +39,9 @@ import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; -import org.thingsboard.server.common.transport.adaptor.ProtoConverter; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.ProtoConverter; import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse; import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; import org.thingsboard.server.gen.transport.TransportApiProtos; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java index de0f2a502b..6ff505cb36 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/GatewaySessionHandler.java @@ -17,7 +17,7 @@ package org.thingsboard.server.transport.mqtt.session; import io.netty.buffer.ByteBuf; import io.netty.handler.codec.mqtt.MqttPublishMessage; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse; import java.util.UUID; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java index 48998d58cd..f3aaa2708f 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java @@ -32,9 +32,9 @@ import org.springframework.util.CollectionUtils; import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; -import org.thingsboard.server.common.transport.adaptor.ProtoConverter; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.ProtoConverter; import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse; import org.thingsboard.server.gen.transport.TransportApiProtos; import org.thingsboard.server.gen.transport.TransportProtos; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/sparkplug/MetricDataType.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/sparkplug/MetricDataType.java index d5e781a402..c49286a4b1 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/sparkplug/MetricDataType.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/util/sparkplug/MetricDataType.java @@ -16,7 +16,7 @@ package org.thingsboard.server.transport.mqtt.util.sparkplug; import lombok.extern.slf4j.Slf4j; -import org.thingsboard.server.common.transport.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.gen.transport.mqtt.SparkplugBProto; import java.math.BigInteger; diff --git a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java index 6e68a0bd44..51ed8d0485 100644 --- a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java +++ b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java @@ -46,7 +46,7 @@ import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryin import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.TbSnmpTransportComponent; import org.thingsboard.server.transport.snmp.session.DeviceSessionContext; diff --git a/common/transport/transport-api/src/test/java/JsonConverterTest.java b/common/transport/transport-api/src/test/java/JsonConverterTest.java index 39ed04a29a..1062199caf 100644 --- a/common/transport/transport-api/src/test/java/JsonConverterTest.java +++ b/common/transport/transport-api/src/test/java/JsonConverterTest.java @@ -19,7 +19,7 @@ import org.junit.Assert; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import java.util.ArrayList; 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 6f7bb7cf8d..9196561ed5 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 @@ -37,7 +37,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.util.CollectionsUtil; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import javax.annotation.Nullable; import java.util.ArrayList; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java index f31896a8c9..6bb37438a1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java @@ -41,7 +41,7 @@ import org.thingsboard.server.common.data.query.KeyFilterPredicate; import org.thingsboard.server.common.data.query.NumericFilterPredicate; import org.thingsboard.server.common.data.query.StringFilterPredicate; import org.thingsboard.server.common.msg.tools.SchedulerUtils; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import java.time.Instant; import java.time.ZoneId; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java index 31f661417b..feedfaae60 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/DeviceState.java @@ -41,7 +41,7 @@ import org.thingsboard.server.common.data.query.EntityKeyType; import org.thingsboard.server.common.data.rule.RuleNodeState; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.dao.sql.query.EntityKeyMapping; import java.util.ArrayList; 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 9cf9bfa1bd..5baba50565 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 @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import java.util.ArrayList; import java.util.List; 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 dcc84813cd..b94df4268c 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 @@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; -import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.adaptor.JsonConverter; import java.util.ArrayList; import java.util.List; From db6f3102849a259090789ccce7c60befc033fbd8 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Mon, 5 Jun 2023 15:24:47 +0200 Subject: [PATCH 014/397] migration to spring boot 3.1 --- application/pom.xml | 11 +- .../server/actors/ActorSystemContext.java | 6 +- .../device/DeviceActorMessageProcessor.java | 2 +- .../actors/service/DefaultActorService.java | 4 +- ...tomOAuth2AuthorizationRequestResolver.java | 5 +- .../config/RateLimitProcessingFilter.java | 10 +- .../server/config/SwaggerConfiguration.java | 2 +- .../ThingsboardSecurityConfiguration.java | 82 +++--- .../thingsboard/server/config/WebConfig.java | 4 +- .../controller/AbstractRpcController.java | 2 +- .../server/controller/AuthController.java | 2 +- .../server/controller/BaseController.java | 8 +- .../server/controller/DeviceController.java | 2 +- .../server/controller/EdgeController.java | 2 +- .../controller/NotificationController.java | 2 +- .../NotificationRuleController.java | 2 +- .../NotificationTargetController.java | 2 +- .../NotificationTemplateController.java | 2 +- .../server/controller/OAuth2Controller.java | 2 +- .../server/controller/RpcV2Controller.java | 2 +- .../controller/SystemInfoController.java | 2 +- .../controller/TelemetryController.java | 6 +- .../TwoFactorAuthConfigController.java | 2 +- .../controller/TwoFactorAuthController.java | 2 +- .../server/controller/UserController.java | 2 +- .../controller/plugin/TbWebSocketHandler.java | 8 +- .../ThingsboardErrorResponseHandler.java | 16 +- .../DefaultTbApiUsageStateService.java | 4 +- .../limits/DefaultRateLimitService.java | 2 +- .../AnnotationComponentDiscoveryService.java | 2 +- .../device/ClaimDevicesServiceImpl.java | 2 +- .../edge/DefaultEdgeNotificationService.java | 4 +- .../DefaultEdgeInstallService.java | 2 +- .../edge/instructions/EdgeInstallService.java | 2 +- .../service/edge/rpc/EdgeGrpcService.java | 6 +- .../telemetry/BaseTelemetryProcessor.java | 4 +- .../DefaultTbEntityViewService.java | 2 +- .../entitiy/user/DefaultUserService.java | 2 +- .../service/entitiy/user/TbUserService.java | 2 +- .../SharedEventLoopGroupService.java | 4 +- .../DefaultSystemDataLoaderService.java | 6 +- .../TbRuleEngineQueueConfigService.java | 2 +- .../service/mail/DefaultMailService.java | 5 +- .../DefaultNotificationSchedulerService.java | 2 +- .../DefaultNotificationRuleProcessor.java | 2 +- .../cache/DefaultNotificationRulesCache.java | 2 +- .../ota/DefaultOtaPackageStateService.java | 2 +- .../queue/DefaultTbCoreConsumerService.java | 4 +- .../DefaultTbRuleEngineConsumerService.java | 5 +- .../processing/AbstractConsumerService.java | 2 +- .../rpc/DefaultTbCoreDeviceRpcService.java | 5 +- .../rpc/DefaultTbRuleEngineRpcService.java | 4 +- .../service/security/AccessValidator.java | 6 +- ...wtTokenAuthenticationProcessingFilter.java | 8 +- .../jwt/RefreshTokenProcessingFilter.java | 8 +- .../auth/jwt/SkipPathRequestMatcher.java | 2 +- .../extractor/JwtHeaderTokenExtractor.java | 2 +- .../jwt/extractor/JwtQueryTokenExtractor.java | 2 +- .../auth/jwt/extractor/TokenExtractor.java | 4 +- .../auth/oauth2/AppleOAuth2ClientMapper.java | 2 +- .../auth/oauth2/BasicOAuth2ClientMapper.java | 2 +- .../security/auth/oauth2/CookieUtils.java | 6 +- .../auth/oauth2/CustomOAuth2ClientMapper.java | 2 +- .../auth/oauth2/GithubOAuth2ClientMapper.java | 2 +- ...eOAuth2AuthorizationRequestRepository.java | 7 +- .../auth/oauth2/OAuth2ClientMapper.java | 2 +- .../Oauth2AuthenticationFailureHandler.java | 6 +- .../Oauth2AuthenticationSuccessHandler.java | 6 +- .../auth/rest/RestAuthenticationDetails.java | 2 +- .../rest/RestAuthenticationDetailsSource.java | 2 +- ...RestAwareAuthenticationFailureHandler.java | 6 +- ...RestAwareAuthenticationSuccessHandler.java | 8 +- .../auth/rest/RestLoginProcessingFilter.java | 8 +- .../rest/RestPublicLoginProcessingFilter.java | 8 +- .../system/DefaultSystemSecurityService.java | 4 +- .../system/SystemSecurityService.java | 2 +- .../server/service/sms/DefaultSmsService.java | 5 +- .../state/DefaultDeviceStateService.java | 11 +- .../service/stats/DefaultJsInvokeStats.java | 2 +- .../DefaultRuleEngineStatisticsService.java | 2 +- .../DefaultSubscriptionManagerService.java | 4 +- ...efaultTbEntityDataSubscriptionService.java | 4 +- .../DefaultTbLocalSubscriptionService.java | 4 +- .../csv/AbstractBulkImportService.java | 6 +- .../DefaultEntitiesVersionControlService.java | 4 +- .../system/DefaultSystemInfoService.java | 4 +- .../AbstractSubscriptionService.java | 6 +- .../DefaultTelemetrySubscriptionService.java | 6 +- .../transport/TbCoreTransportApiService.java | 4 +- .../service/update/DefaultUpdateService.java | 2 +- .../service/ws/DefaultWebSocketService.java | 6 +- .../thingsboard/server/utils/MiscUtils.java | 2 +- .../src/main/resources/thingsboard.yml | 2 +- .../controller/AbstractControllerTest.java | 2 +- .../server/edge/DeviceEdgeTest.java | 2 +- .../lwm2m/AbstractLwM2MIntegrationTest.java | 10 +- .../security/sql/PskLwm2mIntegrationTest.java | 2 +- .../security/sql/RpkLwM2MIntegrationTest.java | 2 +- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 2 +- common/cache/pom.xml | 4 +- .../server/cache/CacheSpecsMap.java | 2 +- .../cache/RedisTbTransactionalCache.java | 3 +- common/cluster-api/pom.xml | 4 +- .../coapserver/DefaultCoapServerService.java | 4 +- common/dao-api/pom.xml | 4 +- .../cassandra/AbstractCassandraCluster.java | 2 +- .../dao/cassandra/CassandraCluster.java | 2 +- .../dao/cassandra/CassandraDriverOptions.java | 2 +- .../cassandra/CassandraInstallCluster.java | 2 +- common/data/pom.xml | 4 +- .../server/common/data/DashboardInfo.java | 2 +- .../server/common/data/DeviceProfile.java | 2 +- .../AlarmCreateOrUpdateActiveRequest.java | 4 +- .../common/data/alarm/AlarmUpdateRequest.java | 4 +- .../data/device/profile/AlarmCondition.java | 2 +- .../device/profile/AlarmConditionFilter.java | 2 +- .../common/data/device/profile/AlarmRule.java | 2 +- .../device/profile/DeviceProfileAlarm.java | 2 +- .../device/profile/DeviceProfileData.java | 2 +- .../common/data/kv/BaseAttributeKvEntry.java | 2 +- .../server/common/data/kv/BasicTsKvEntry.java | 2 +- .../notification/NotificationRequest.java | 4 +- .../NotificationRequestConfig.java | 2 +- ...faultNotificationRuleRecipientsConfig.java | 2 +- ...latedNotificationRuleRecipientsConfig.java | 2 +- .../notification/rule/NotificationRule.java | 8 +- .../NotificationRuleRecipientsConfig.java | 2 +- ...signmentNotificationRuleTriggerConfig.java | 2 +- .../AlarmNotificationRuleTriggerConfig.java | 2 +- ...ActivityNotificationRuleTriggerConfig.java | 2 +- ...iesLimitNotificationRuleTriggerConfig.java | 2 +- .../settings/NotificationSettings.java | 4 +- ...SlackNotificationDeliveryMethodConfig.java | 2 +- .../targets/NotificationTarget.java | 6 +- .../targets/platform/CustomerUsersFilter.java | 2 +- ...PlatformUsersNotificationTargetConfig.java | 4 +- .../targets/platform/UserListFilter.java | 2 +- .../targets/slack/SlackConversation.java | 4 +- .../slack/SlackNotificationTargetConfig.java | 4 +- .../DeliveryMethodNotificationTemplate.java | 2 +- ...ailDeliveryMethodNotificationTemplate.java | 2 +- .../template/NotificationTemplate.java | 6 +- .../template/NotificationTemplateConfig.java | 4 +- ...WebDeliveryMethodNotificationTemplate.java | 2 +- .../OAuth2ClientRegistrationTemplate.java | 2 +- .../data/oauth2/OAuth2MapperConfig.java | 2 +- .../data/query/FilterPredicateValue.java | 2 +- .../data/query/StringFilterPredicate.java | 2 +- .../model/mfa/PlatformTwoFaSettings.java | 8 +- .../account/BackupCodeTwoFaAccountConfig.java | 2 +- .../mfa/account/EmailTwoFaAccountConfig.java | 4 +- .../mfa/account/SmsTwoFaAccountConfig.java | 4 +- .../mfa/account/TotpTwoFaAccountConfig.java | 4 +- .../BackupCodeTwoFaProviderConfig.java | 2 +- .../provider/OtpBasedTwoFaProviderConfig.java | 2 +- .../mfa/provider/SmsTwoFaProviderConfig.java | 4 +- .../mfa/provider/TotpTwoFaProviderConfig.java | 2 +- .../server/common/data/validation/Length.java | 4 +- .../server/common/data/validation/NoXss.java | 4 +- .../servicebus/TbServiceBusQueueConfigs.java | 2 +- .../AbstractTbQueueConsumerTemplate.java | 2 +- .../common/DefaultTbQueueRequestTemplate.java | 2 +- .../DefaultTbServiceInfoProvider.java | 2 +- .../queue/discovery/HashPartitionService.java | 4 +- .../queue/discovery/ZkDiscoveryService.java | 4 +- .../environment/EnvironmentLogService.java | 2 +- .../kafka/TbKafkaConsumerStatsService.java | 4 +- .../queue/kafka/TbKafkaTopicConfigs.java | 2 +- .../provider/AwsSqsMonolithQueueFactory.java | 2 +- .../provider/AwsSqsTbCoreQueueFactory.java | 2 +- .../AwsSqsTbRuleEngineQueueFactory.java | 2 +- .../AwsSqsTbVersionControlQueueFactory.java | 2 +- .../provider/AwsSqsTransportQueueFactory.java | 2 +- .../provider/KafkaMonolithQueueFactory.java | 2 +- .../provider/KafkaTbCoreQueueFactory.java | 2 +- .../KafkaTbRuleEngineQueueFactory.java | 2 +- .../KafkaTbTransportQueueFactory.java | 2 +- .../KafkaTbVersionControlQueueFactory.java | 2 +- .../provider/PubSubMonolithQueueFactory.java | 2 +- .../provider/PubSubTbCoreQueueFactory.java | 2 +- .../PubSubTbRuleEngineQueueFactory.java | 2 +- .../PubSubTbVersionControlQueueFactory.java | 2 +- .../provider/PubSubTransportQueueFactory.java | 2 +- .../RabbitMqMonolithQueueFactory.java | 2 +- .../provider/RabbitMqTbCoreQueueFactory.java | 2 +- .../RabbitMqTbRuleEngineQueueFactory.java | 2 +- .../RabbitMqTbVersionControlQueueFactory.java | 2 +- .../RabbitMqTransportQueueFactory.java | 2 +- .../ServiceBusMonolithQueueFactory.java | 2 +- .../ServiceBusTbCoreQueueFactory.java | 2 +- .../ServiceBusTbRuleEngineQueueFactory.java | 2 +- ...erviceBusTbVersionControlQueueFactory.java | 2 +- .../ServiceBusTransportQueueFactory.java | 2 +- .../provider/TbCoreQueueProducerProvider.java | 2 +- .../TbRuleEngineProducerProvider.java | 2 +- .../TbTransportQueueProducerProvider.java | 2 +- .../TbVersionControlProducerProvider.java | 2 +- .../server/queue/pubsub/TbPubSubSettings.java | 2 +- .../pubsub/TbPubSubSubscriptionSettings.java | 2 +- .../rabbitmq/TbRabbitMqQueueArguments.java | 2 +- .../queue/rabbitmq/TbRabbitMqSettings.java | 2 +- .../scheduler/DefaultSchedulerComponent.java | 4 +- .../queue/sqs/TbAwsSqsQueueAttributes.java | 2 +- .../DefaultTbApiUsageReportClient.java | 2 +- .../service/script/RemoteJsInvokeService.java | 4 +- .../script/api/ScriptStatCallback.java | 2 +- .../script/api/js/NashornJsInvokeService.java | 4 +- .../api/tbel/DefaultTbelInvokeService.java | 4 +- .../common/stats/DefaultStatsFactory.java | 2 +- .../transport/coap/CoapTransportService.java | 4 +- .../transport/http/DeviceApiController.java | 2 +- .../LwM2MTransportBootstrapService.java | 4 +- ...LwM2MDtlsBootstrapCertificateVerifier.java | 2 +- .../TbLwM2MDtlsCertificateVerifier.java | 2 +- .../server/DefaultLwM2mTransportService.java | 2 +- .../server/LwM2mTransportServerHelper.java | 4 +- .../DefaultLwM2mDownlinkMsgHandler.java | 4 +- .../model/LwM2MModelConfigServiceImpl.java | 2 +- .../ota/DefaultLwM2MOtaUpdateService.java | 4 +- .../uplink/DefaultLwM2mUplinkMsgHandler.java | 4 +- .../transport/mqtt/MqttTransportContext.java | 2 +- .../transport/mqtt/MqttTransportService.java | 4 +- .../AbstractGatewaySessionHandler.java | 2 +- .../session/SparkplugNodeSessionHandler.java | 2 +- .../snmp/service/SnmpTransportService.java | 4 +- .../common/transport/TransportContext.java | 4 +- .../config/ssl/SslCredentialsConfig.java | 2 +- .../service/DefaultTransportService.java | 4 +- common/util/pom.xml | 4 +- .../util/AbstractListeningExecutor.java | 4 +- common/version-control/pom.xml | 4 +- .../DefaultClusterVersionControlService.java | 4 +- .../sync/vc/DefaultGitRepositoryService.java | 2 +- dao/pom.xml | 8 +- .../server/dao/asset/AssetTypeFilter.java | 2 +- .../attributes/CachedAttributesService.java | 2 +- .../audit/sink/ElasticsearchAuditLogSink.java | 2 +- .../server/dao/edge/EdgeServiceImpl.java | 2 +- .../dao/entityview/EntityViewServiceImpl.java | 2 +- .../server/dao/model/BaseSqlEntity.java | 6 +- .../model/sql/AbstractAlarmCommentEntity.java | 13 +- .../dao/model/sql/AbstractAlarmEntity.java | 17 +- .../dao/model/sql/AbstractAssetEntity.java | 12 +- .../dao/model/sql/AbstractDeviceEntity.java | 22 +- .../dao/model/sql/AbstractEdgeEntity.java | 12 +- .../model/sql/AbstractEntityViewEntity.java | 17 +- .../dao/model/sql/AbstractTenantEntity.java | 12 +- .../dao/model/sql/AbstractTsKvEntity.java | 9 +- .../model/sql/AbstractWidgetTypeEntity.java | 4 +- .../dao/model/sql/AdminSettingsEntity.java | 16 +- .../dao/model/sql/AlarmCommentEntity.java | 11 +- .../server/dao/model/sql/AlarmEntity.java | 8 +- .../server/dao/model/sql/AlarmInfoEntity.java | 6 +- .../dao/model/sql/ApiUsageStateEntity.java | 13 +- .../server/dao/model/sql/AssetEntity.java | 8 +- .../dao/model/sql/AssetProfileEntity.java | 6 +- .../model/sql/AttributeKvCompositeKey.java | 8 +- .../dao/model/sql/AttributeKvEntity.java | 8 +- .../server/dao/model/sql/AuditLogEntity.java | 18 +- .../model/sql/ComponentDescriptorEntity.java | 19 +- .../server/dao/model/sql/CustomerEntity.java | 22 +- .../server/dao/model/sql/DashboardEntity.java | 16 +- .../dao/model/sql/DashboardInfoEntity.java | 9 +- .../model/sql/DeviceCredentialsEntity.java | 10 +- .../server/dao/model/sql/DeviceEntity.java | 13 +- .../dao/model/sql/DeviceInfoEntity.java | 6 +- .../dao/model/sql/DeviceProfileEntity.java | 21 +- .../server/dao/model/sql/EdgeEntity.java | 8 +- .../server/dao/model/sql/EdgeEventEntity.java | 20 +- .../model/sql/EntityAlarmCompositeKey.java | 2 +- .../dao/model/sql/EntityAlarmEntity.java | 10 +- .../dao/model/sql/EntityViewEntity.java | 8 +- .../dao/model/sql/ErrorEventEntity.java | 6 +- .../server/dao/model/sql/EventEntity.java | 6 +- .../dao/model/sql/LifecycleEventEntity.java | 6 +- .../dao/model/sql/NotificationEntity.java | 20 +- .../model/sql/NotificationRequestEntity.java | 24 +- .../dao/model/sql/NotificationRuleEntity.java | 25 +- .../model/sql/NotificationTargetEntity.java | 14 +- .../model/sql/NotificationTemplateEntity.java | 18 +- ...Auth2ClientRegistrationTemplateEntity.java | 20 +- .../dao/model/sql/OAuth2DomainEntity.java | 10 +- .../dao/model/sql/OAuth2MobileEntity.java | 6 +- .../dao/model/sql/OAuth2ParamsEntity.java | 6 +- .../model/sql/OAuth2RegistrationEntity.java | 18 +- .../dao/model/sql/OtaPackageEntity.java | 22 +- .../dao/model/sql/OtaPackageInfoEntity.java | 22 +- .../server/dao/model/sql/QueueEntity.java | 18 +- .../dao/model/sql/RelationCompositeKey.java | 2 +- .../server/dao/model/sql/RelationEntity.java | 20 +- .../server/dao/model/sql/RpcEntity.java | 22 +- .../model/sql/RuleChainDebugEventEntity.java | 6 +- .../server/dao/model/sql/RuleChainEntity.java | 20 +- .../model/sql/RuleNodeDebugEventEntity.java | 6 +- .../server/dao/model/sql/RuleNodeEntity.java | 16 +- .../dao/model/sql/RuleNodeStateEntity.java | 9 +- .../dao/model/sql/StatisticsEventEntity.java | 6 +- .../dao/model/sql/TbResourceEntity.java | 6 +- .../dao/model/sql/TbResourceInfoEntity.java | 6 +- .../server/dao/model/sql/TenantEntity.java | 8 +- .../dao/model/sql/TenantProfileEntity.java | 20 +- .../dao/model/sql/UserAuthSettingsEntity.java | 14 +- .../dao/model/sql/UserCredentialsEntity.java | 12 +- .../server/dao/model/sql/UserEntity.java | 18 +- .../dao/model/sql/UserSettingsEntity.java | 18 +- .../model/sql/WidgetTypeDetailsEntity.java | 15 +- .../dao/model/sql/WidgetTypeEntity.java | 15 +- .../dao/model/sql/WidgetsBundleEntity.java | 6 +- .../sqlts/dictionary/TsKvDictionary.java | 16 +- .../TsKvDictionaryCompositeKey.java | 2 +- .../sqlts/latest/TsKvLatestCompositeKey.java | 2 +- .../model/sqlts/latest/TsKvLatestEntity.java | 18 +- .../ts/TimescaleTsKvCompositeKey.java | 2 +- .../timescale/ts/TimescaleTsKvEntity.java | 19 +- .../dao/model/sqlts/ts/TsKvCompositeKey.java | 2 +- .../server/dao/model/sqlts/ts/TsKvEntity.java | 7 +- .../dao/nosql/CassandraAbstractAsyncDao.java | 6 +- .../CassandraBufferedRateReadExecutor.java | 2 +- .../CassandraBufferedRateWriteExecutor.java | 2 +- .../server/dao/oauth2/OAuth2ServiceImpl.java | 2 +- .../dao/relation/BaseRelationService.java | 4 +- .../dao/service/ConstraintValidator.java | 12 +- .../server/dao/service/NoXssValidator.java | 4 +- .../dao/service/StringLengthValidator.java | 4 +- .../sql/ScheduledLogExecutorComponent.java | 4 +- .../server/dao/sql/TbSqlBlockingQueue.java | 4 +- .../server/dao/sql/alarm/AlarmRepository.java | 88 ++++--- .../dao/sql/attributes/JpaAttributeDao.java | 12 +- .../dao/sql/audit/AuditLogRepository.java | 12 +- ...ctComponentDescriptorInsertRepository.java | 6 +- .../dao/sql/device/DeviceRepository.java | 2 +- .../dao/sql/edge/JpaBaseEdgeEventDao.java | 4 +- .../dao/sql/event/EventInsertRepository.java | 2 +- .../event/EventPartitionConfiguration.java | 2 +- .../server/dao/sql/event/JpaBaseEventDao.java | 4 +- .../server/dao/sql/query/QueryContext.java | 8 +- .../relation/SqlRelationInsertRepository.java | 6 +- ...stractChunkedAggregationTimeseriesDao.java | 4 +- .../dao/sqlts/AbstractSqlTimeseriesDao.java | 2 +- .../sqlts/BaseAbstractSqlTimeseriesDao.java | 10 +- .../dao/sqlts/SqlTimeseriesLatestDao.java | 4 +- .../latest/SearchTsKvLatestRepository.java | 4 +- .../timescale/AggregationRepository.java | 4 +- .../timescale/TimescaleTimeseriesDao.java | 4 +- .../server/dao/sqlts/ts/TsKvRepository.java | 60 ++--- .../AggregatePartitionsFunction.java | 2 +- .../CassandraBaseTimeseriesDao.java | 6 +- .../util/AbstractBufferedRateExecutor.java | 2 +- .../AbstractJsonSqlTypeDescriptor.java | 78 ------ .../mapping/JsonBinarySqlTypeDescriptor.java | 52 ---- .../dao/util/mapping/JsonBinaryType.java | 46 ---- .../dao/util/mapping/JsonConverter.java | 34 +++ .../mapping/JsonStringSqlTypeDescriptor.java | 61 ----- .../dao/util/mapping/JsonStringType.java | 48 ---- .../dao/util/mapping/JsonTypeDescriptor.java | 96 ------- .../impl/SlackNotificationChannel.java | 2 +- .../transport/TransportHealthChecker.java | 4 +- .../transport/TransportMonitoringService.java | 2 +- msa/monitoring/pom.xml | 2 +- netty-mqtt/pom.xml | 4 + .../thingsboard/mqtt/MqttClientConfig.java | 4 +- pom.xml | 114 ++++++--- rule-engine/rule-engine-api/pom.xml | 2 +- rule-engine/rule-engine-components/pom.xml | 10 +- .../TbCopyAttributesToEntityViewNode.java | 2 +- .../TbSaveToCustomCassandraTableNode.java | 2 +- .../engine/filter/TbCheckAlarmStatusNode.java | 3 +- .../TbNotificationNodeConfiguration.java | 4 +- .../TbSlackNodeConfiguration.java | 6 +- .../rule/engine/rest/TbHttpClient.java | 238 +++++++----------- .../rule/engine/rest/TbRestApiCallNode.java | 9 +- .../AttributesDeleteNodeCallback.java | 2 +- .../AttributesUpdateNodeCallback.java | 2 +- .../telemetry/TelemetryNodeCallback.java | 2 +- .../rule/engine/rest/TbHttpClientTest.java | 33 +-- .../engine/rest/TbRestApiCallNodeTest.java | 43 ++-- 376 files changed, 1261 insertions(+), 1739 deletions(-) delete mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/mapping/AbstractJsonSqlTypeDescriptor.java delete mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonBinarySqlTypeDescriptor.java delete mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonBinaryType.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonConverter.java delete mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonStringSqlTypeDescriptor.java delete mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonStringType.java delete mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonTypeDescriptor.java diff --git a/application/pom.xml b/application/pom.xml index 8c3976eb31..1838c97c65 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -49,7 +49,6 @@ io.netty netty-transport-native-epoll - ${netty.version} linux-x86_64 @@ -212,7 +211,15 @@ com.sun.mail - javax.mail + jakarta.mail + + + jakarta.xml.bind + jakarta.xml.bind-api + + + javax.xml.bind + jaxb-api com.twilio.sdk diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index e0190bb388..437a18bbff 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -113,9 +113,9 @@ import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; import org.thingsboard.server.service.transport.TbCoreToTransportService; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import java.io.IOException; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; + import java.io.PrintWriter; import java.io.StringWriter; import java.util.concurrent.ConcurrentHashMap; diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index 934f309480..e9b10287b5 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -93,7 +93,7 @@ import org.thingsboard.server.service.rpc.RemoveRpcActorMsg; import org.thingsboard.server.service.rpc.ToDeviceRpcRequestActorMsg; import org.thingsboard.server.service.transport.msg.TransportToDeviceActorMsgWrapper; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java b/application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java index dd5bd4f1ed..3a78701d0b 100644 --- a/application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java +++ b/application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java @@ -35,8 +35,8 @@ import org.thingsboard.server.queue.discovery.TbApplicationEventListener; import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; import org.thingsboard.server.queue.util.AfterStartUp; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; diff --git a/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java b/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java index 4d227345b1..84789fc851 100644 --- a/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java +++ b/application/src/main/java/org/thingsboard/server/config/CustomOAuth2AuthorizationRequestResolver.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.config; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.keygen.Base64StringKeyGenerator; @@ -42,7 +43,6 @@ import org.thingsboard.server.service.security.auth.oauth2.TbOAuth2ParameterName import org.thingsboard.server.service.security.model.token.OAuth2AppTokenFactory; import org.thingsboard.server.utils.MiscUtils; -import javax.servlet.http.HttpServletRequest; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -113,7 +113,6 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza return request.getParameter("appToken"); } - @SuppressWarnings("deprecation") private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, String redirectUriAction, String appPackage, String appToken) { if (registrationId == null) { return null; @@ -154,8 +153,6 @@ public class CustomOAuth2AuthorizationRequestResolver implements OAuth2Authoriza addPkceParameters(attributes, additionalParameters); } builder.additionalParameters(additionalParameters); - } else if (AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) { - builder = OAuth2AuthorizationRequest.implicit(); } else { throw new IllegalArgumentException("Invalid Authorization Grant Type (" + clientRegistration.getAuthorizationGrantType().getValue() + diff --git a/application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java b/application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java index 0593b9765a..d18e999137 100644 --- a/application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/config/RateLimitProcessingFilter.java @@ -33,11 +33,11 @@ import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; diff --git a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java index 4415f1a0bf..c7616ed865 100644 --- a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java @@ -82,7 +82,7 @@ import static springfox.documentation.builders.PathSelectors.any; import static springfox.documentation.builders.PathSelectors.regex; @Slf4j -@Configuration +//@Configuration @TbCoreComponent @Profile("!test") public class SwaggerConfiguration { diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java index a418dc268b..052e1bb6ba 100644 --- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java @@ -26,10 +26,11 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.DefaultAuthenticationEventPublisher; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; @@ -60,7 +61,7 @@ import java.util.List; @Configuration @EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled=true) +@EnableMethodSecurity @Order(SecurityProperties.BASIC_AUTH_ORDER) @TbCoreComponent public class ThingsboardSecurityConfiguration { @@ -74,11 +75,12 @@ public class ThingsboardSecurityConfiguration { public static final String FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login"; public static final String PUBLIC_LOGIN_ENTRY_POINT = "/api/auth/login/public"; public static final String TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token"; - protected static final String[] NON_TOKEN_BASED_AUTH_ENTRY_POINTS = new String[] {"/index.html", "/assets/**", "/static/**", "/api/noauth/**", "/webjars/**", "/api/license/**"}; + protected static final String[] NON_TOKEN_BASED_AUTH_ENTRY_POINTS = new String[]{"/index.html", "/assets/**", "/static/**", "/api/noauth/**", "/webjars/**", "/api/license/**"}; public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**"; public static final String WS_TOKEN_BASED_AUTH_ENTRY_POINT = "/api/ws/**"; - @Autowired private ThingsboardErrorResponseHandler restAccessDeniedHandler; + @Autowired + private ThingsboardErrorResponseHandler restAccessDeniedHandler; @Autowired(required = false) @Qualifier("oauth2AuthenticationSuccessHandler") @@ -99,11 +101,15 @@ public class ThingsboardSecurityConfiguration { @Qualifier("defaultAuthenticationFailureHandler") private AuthenticationFailureHandler failureHandler; - @Autowired private RestAuthenticationProvider restAuthenticationProvider; - @Autowired private JwtAuthenticationProvider jwtAuthenticationProvider; - @Autowired private RefreshTokenAuthenticationProvider refreshTokenAuthenticationProvider; + @Autowired + private RestAuthenticationProvider restAuthenticationProvider; + @Autowired + private JwtAuthenticationProvider jwtAuthenticationProvider; + @Autowired + private RefreshTokenAuthenticationProvider refreshTokenAuthenticationProvider; - @Autowired(required = false) OAuth2Configuration oauth2Configuration; + @Autowired(required = false) + OAuth2Configuration oauth2Configuration; @Autowired @Qualifier("jwtHeaderTokenExtractor") @@ -113,9 +119,11 @@ public class ThingsboardSecurityConfiguration { @Qualifier("jwtQueryTokenExtractor") private TokenExtractor jwtQueryTokenExtractor; - @Autowired private AuthenticationManager authenticationManager; + @Autowired + private AuthenticationManager authenticationManager; - @Autowired private RateLimitProcessingFilter rateLimitProcessingFilter; + @Autowired + private RateLimitProcessingFilter rateLimitProcessingFilter; @Bean protected RestLoginProcessingFilter buildRestLoginProcessingFilter() throws Exception { @@ -180,35 +188,28 @@ public class ThingsboardSecurityConfiguration { @Bean public WebSecurityCustomizer webSecurityCustomizer() { - return (web) -> web.ignoring().antMatchers("/*.js","/*.css","/*.ico","/assets/**","/static/**"); + return (web) -> web.ignoring().requestMatchers("/*.js", "/*.css", "/*.ico", "/assets/**", "/static/**"); } @Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.headers().cacheControl().and().frameOptions().disable() - .and() - .cors() - .and() - .csrf().disable() - .exceptionHandling() - .and() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .authorizeRequests() - .antMatchers(WEBJARS_ENTRY_POINT).permitAll() // Webjars - .antMatchers(DEVICE_API_ENTRY_POINT).permitAll() // Device HTTP Transport API - .antMatchers(FORM_BASED_LOGIN_ENTRY_POINT).permitAll() // Login end-point - .antMatchers(PUBLIC_LOGIN_ENTRY_POINT).permitAll() // Public login end-point - .antMatchers(TOKEN_REFRESH_ENTRY_POINT).permitAll() // Token refresh end-point - .antMatchers(NON_TOKEN_BASED_AUTH_ENTRY_POINTS).permitAll() // static resources, user activation and password reset end-points - .and() - .authorizeRequests() - .antMatchers(WS_TOKEN_BASED_AUTH_ENTRY_POINT).authenticated() // Protected WebSocket API End-points - .antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated() // Protected API End-points - .and() - .exceptionHandling().accessDeniedHandler(restAccessDeniedHandler) - .and() + http.headers(headers -> headers + .cacheControl(config -> {}) + .frameOptions(config -> {})) + .cors(cors -> {}) + .csrf(AbstractHttpConfigurer::disable) + .exceptionHandling(config -> {}) + .sessionManagement(config -> config.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .authorizeRequests(config -> config + .requestMatchers(WEBJARS_ENTRY_POINT).permitAll() // Webjars + .requestMatchers(DEVICE_API_ENTRY_POINT).permitAll() // Device HTTP Transport API + .requestMatchers(FORM_BASED_LOGIN_ENTRY_POINT).permitAll() // Login end-point + .requestMatchers(PUBLIC_LOGIN_ENTRY_POINT).permitAll() // Public login end-point + .requestMatchers(TOKEN_REFRESH_ENTRY_POINT).permitAll() // Token refresh end-point + .requestMatchers(NON_TOKEN_BASED_AUTH_ENTRY_POINTS).permitAll() // static resources, user activation and password reset end-points + .requestMatchers(WS_TOKEN_BASED_AUTH_ENTRY_POINT).authenticated() // Protected WebSocket API End-points + .requestMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated()) // Protected API End-points + .exceptionHandling(config -> config.accessDeniedHandler(restAccessDeniedHandler)) .addFilterBefore(buildRestLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(buildRestPublicLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(buildJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class) @@ -216,15 +217,14 @@ public class ThingsboardSecurityConfiguration { .addFilterBefore(buildWsJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterAfter(rateLimitProcessingFilter, UsernamePasswordAuthenticationFilter.class); if (oauth2Configuration != null) { - http.oauth2Login() - .authorizationEndpoint() - .authorizationRequestRepository(httpCookieOAuth2AuthorizationRequestRepository) - .authorizationRequestResolver(oAuth2AuthorizationRequestResolver) - .and() + http.oauth2Login(login -> login + .authorizationEndpoint(config -> config + .authorizationRequestRepository(httpCookieOAuth2AuthorizationRequestRepository) + .authorizationRequestResolver(oAuth2AuthorizationRequestResolver)) .loginPage("/oauth2Login") .loginProcessingUrl(oauth2Configuration.getLoginProcessingUrl()) .successHandler(oauth2AuthenticationSuccessHandler) - .failureHandler(oauth2AuthenticationFailureHandler); + .failureHandler(oauth2AuthenticationFailureHandler)); } return http.build(); } diff --git a/application/src/main/java/org/thingsboard/server/config/WebConfig.java b/application/src/main/java/org/thingsboard/server/config/WebConfig.java index 65396576c1..df57cf45f8 100644 --- a/application/src/main/java/org/thingsboard/server/config/WebConfig.java +++ b/application/src/main/java/org/thingsboard/server/config/WebConfig.java @@ -19,8 +19,8 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.thingsboard.server.utils.MiscUtils; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @Controller diff --git a/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java b/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java index 32797801c0..5f33eb951e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java @@ -45,7 +45,7 @@ import org.thingsboard.server.service.security.AccessValidator; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.Optional; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index f3a3a2397c..492296995c 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -62,7 +62,7 @@ import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.system.SystemSecurityService; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.net.URI; import java.net.URISyntaxException; import java.util.concurrent.ConcurrentHashMap; diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 68a987a0bc..da2740a3b7 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -160,9 +160,9 @@ import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService; import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; -import javax.mail.MessagingException; -import javax.servlet.http.HttpServletResponse; -import javax.validation.ConstraintViolation; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.ConstraintViolation; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -390,7 +390,7 @@ public abstract class BaseController { } /** - * Handles validation error for controller method arguments annotated with @{@link javax.validation.Valid} + * Handles validation error for controller method arguments annotated with @{@link jakarta.validation.Valid} * */ @ExceptionHandler(MethodArgumentNotValidException.class) public void handleValidationError(MethodArgumentNotValidException validationError, HttpServletResponse response) { diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index bb34f6d5b2..9de6a66041 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -74,7 +74,7 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 9a021643cc..0213ae5686 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -64,7 +64,7 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.List; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationController.java index 0f4a288e33..5893410b2a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationController.java @@ -66,7 +66,7 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java index ccf2124113..06eabbc215 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java @@ -43,7 +43,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.UUID; import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_END; diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java index a4c829796b..6b13e9de9d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java @@ -53,7 +53,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.Arrays; import java.util.List; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java index ab171efacf..fef919d710 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java @@ -48,7 +48,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.List; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java b/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java index ef5739a481..519629fbc3 100644 --- a/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java +++ b/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java @@ -39,7 +39,7 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.utils.MiscUtils; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.Enumeration; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java b/application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java index 464dc528a5..c611cfda54 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java +++ b/application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java @@ -49,7 +49,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.rpc.RemoveRpcActorMsg; import org.thingsboard.server.service.security.permission.Operation; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.UUID; import static org.thingsboard.server.common.data.DataConstants.RPC_DELETED; diff --git a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java index 3633cbbdeb..724cb59b73 100644 --- a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java +++ b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java @@ -41,7 +41,7 @@ import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService; import springfox.documentation.annotations.ApiIgnore; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index 05f56e93bd..48864829ac 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -85,9 +85,9 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.telemetry.AttributeData; import org.thingsboard.server.service.telemetry.TsData; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; diff --git a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java index b07b1eb70b..a809f5280c 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java @@ -39,7 +39,7 @@ import org.thingsboard.server.service.security.auth.mfa.TwoFactorAuthService; import org.thingsboard.server.service.security.auth.mfa.config.TwoFaConfigManager; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; diff --git a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthController.java b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthController.java index 4a5bcb3d81..ee1db6868a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthController.java @@ -44,7 +44,7 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.system.SystemSecurityService; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.Collections; import java.util.List; import java.util.Optional; diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index f79f5ee782..91434421d2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -75,7 +75,7 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.system.SystemSecurityService; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java index 7a396ff795..805d24e175 100644 --- a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java +++ b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java @@ -47,10 +47,10 @@ import org.thingsboard.server.service.ws.WebSocketService; import org.thingsboard.server.service.ws.WebSocketSessionRef; import org.thingsboard.server.service.ws.WebSocketSessionType; -import javax.websocket.RemoteEndpoint; -import javax.websocket.SendHandler; -import javax.websocket.SendResult; -import javax.websocket.Session; +import jakarta.websocket.RemoteEndpoint; +import jakarta.websocket.SendHandler; +import jakarta.websocket.SendResult; +import jakarta.websocket.Session; import java.io.IOException; import java.net.URI; import java.security.InvalidParameterException; diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java index ed641c2d4f..c037710e8b 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -16,9 +16,9 @@ package org.thingsboard.server.exception; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.lang.Nullable; @@ -43,9 +43,9 @@ import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedE import org.thingsboard.server.service.security.exception.JwtExpiredTokenException; import org.thingsboard.server.service.security.exception.UserPasswordExpiredException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -138,13 +138,13 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand @Override protected ResponseEntity handleExceptionInternal( Exception ex, @Nullable Object body, - HttpHeaders headers, HttpStatus status, + HttpHeaders headers, HttpStatusCode statusCode, WebRequest request) { - if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) { + if (HttpStatus.INTERNAL_SERVER_ERROR.equals(statusCode)) { request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST); } - ThingsboardErrorCode errorCode = statusToErrorCode(status); - return new ResponseEntity<>(ThingsboardErrorResponse.of(ex.getMessage(), errorCode, status), headers, status); + ThingsboardErrorCode errorCode = statusToErrorCode((HttpStatus) statusCode); + return new ResponseEntity<>(ThingsboardErrorResponse.of(ex.getMessage(), errorCode, (HttpStatus) statusCode), headers, statusCode); } private void handleThingsboardException(ThingsboardException thingsboardException, HttpServletResponse response) throws IOException { diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java index 9e17641c69..f0ee13ae69 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java @@ -68,8 +68,8 @@ import org.thingsboard.server.service.mail.MailExecutorService; import org.thingsboard.server.service.partition.AbstractPartitionBasedService; import org.thingsboard.server.service.telemetry.InternalTelemetryService; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/limits/DefaultRateLimitService.java b/application/src/main/java/org/thingsboard/server/service/apiusage/limits/DefaultRateLimitService.java index 9a0282c840..fac569110d 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/limits/DefaultRateLimitService.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/limits/DefaultRateLimitService.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.msg.tools.TbRateLimits; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.concurrent.TimeUnit; @Service diff --git a/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java b/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java index 1f5e41aeed..ab43208b85 100644 --- a/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java +++ b/application/src/main/java/org/thingsboard/server/service/component/AnnotationComponentDiscoveryService.java @@ -37,7 +37,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.rule.RuleChainType; import org.thingsboard.server.dao.component.ComponentDescriptorService; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; diff --git a/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java index ebc0fd0d24..a4ba2c8311 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/device/ClaimDevicesServiceImpl.java @@ -51,7 +51,7 @@ import org.thingsboard.server.dao.device.claim.ReclaimResult; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.Arrays; import java.util.Collections; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java index 110760acbc..7c6267c4df 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java @@ -58,8 +58,8 @@ import org.thingsboard.server.service.edge.rpc.processor.user.UserEdgeProcessor; import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetBundleEdgeProcessor; import org.thingsboard.server.service.edge.rpc.processor.widget.WidgetTypeEdgeProcessor; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallService.java index 2c4a14635d..344a4e6742 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/instructions/DefaultEdgeInstallService.java @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.install.InstallScripts; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallService.java b/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallService.java index 2a030fc4fa..52a9a5d820 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/instructions/EdgeInstallService.java @@ -19,7 +19,7 @@ import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeInstallInstructions; import org.thingsboard.server.common.data.id.TenantId; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; public interface EdgeInstallService { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java index bda510a762..e0f6b3f6fc 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcService.java @@ -52,9 +52,9 @@ import org.thingsboard.server.service.edge.EdgeContextComponent; import org.thingsboard.server.service.state.DefaultDeviceStateService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.io.IOException; import java.io.InputStream; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java index fece86b92a..4ed2e8f055 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java @@ -67,8 +67,8 @@ import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java index 48e6c4b634..e59340b99b 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/entityview/DefaultTbEntityViewService.java @@ -49,7 +49,7 @@ import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.service.entitiy.AbstractTbEntityService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java index c83c48cc8a..181e0b8b80 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java @@ -32,7 +32,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.AbstractTbEntityService; import org.thingsboard.server.service.security.system.SystemSecurityService; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import static org.thingsboard.server.controller.UserController.ACTIVATE_URL_PATTERN; diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java index 3ef79371d4..b5a5b83bfd 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java @@ -20,7 +20,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; public interface TbUserService { User save(TenantId tenantId, CustomerId customerId, User tbUser, boolean sendActivationMail, HttpServletRequest request, User user) throws ThingsboardException; diff --git a/application/src/main/java/org/thingsboard/server/service/executors/SharedEventLoopGroupService.java b/application/src/main/java/org/thingsboard/server/service/executors/SharedEventLoopGroupService.java index 38b563472e..245387b70e 100644 --- a/application/src/main/java/org/thingsboard/server/service/executors/SharedEventLoopGroupService.java +++ b/application/src/main/java/org/thingsboard/server/service/executors/SharedEventLoopGroupService.java @@ -20,8 +20,8 @@ import io.netty.channel.nio.NioEventLoopGroup; import lombok.Getter; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.concurrent.TimeUnit; @Component diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index 497627f629..69cdebd55e 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -102,9 +102,9 @@ import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.widget.WidgetsBundleService; import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.Arrays; import java.util.Collections; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/service/install/TbRuleEngineQueueConfigService.java b/application/src/main/java/org/thingsboard/server/service/install/TbRuleEngineQueueConfigService.java index 455bd56309..36372650c1 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/TbRuleEngineQueueConfigService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/TbRuleEngineQueueConfigService.java @@ -24,7 +24,7 @@ import org.springframework.context.annotation.Profile; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.queue.settings.TbRuleEngineQueueConfiguration; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.List; @Slf4j diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java index f3fd18141a..5fe876bb75 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java @@ -18,6 +18,7 @@ package org.thingsboard.server.service.mail; import com.fasterxml.jackson.databind.JsonNode; import freemarker.template.Configuration; import freemarker.template.Template; +import jakarta.xml.bind.DatatypeConverter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -47,8 +48,8 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.service.apiusage.TbApiUsageStateService; -import javax.annotation.PostConstruct; -import javax.mail.internet.MimeMessage; +import jakarta.annotation.PostConstruct; +import jakarta.mail.internet.MimeMessage; import java.io.ByteArrayInputStream; import java.util.HashMap; import java.util.Locale; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java index 01591003ad..17dcfca40e 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationSchedulerService.java @@ -40,7 +40,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.executors.NotificationExecutorService; import org.thingsboard.server.service.partition.AbstractPartitionBasedService; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.Collections; import java.util.HashSet; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java index 3e7f67e09b..913c9c9be3 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/DefaultNotificationRuleProcessor.java @@ -53,7 +53,7 @@ import org.thingsboard.server.service.notification.rule.cache.NotificationRulesC import org.thingsboard.server.service.notification.rule.trigger.NotificationRuleTriggerProcessor; import org.thingsboard.server.service.notification.rule.trigger.RuleEngineMsgNotificationRuleTriggerProcessor; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.io.Serializable; import java.util.Collection; import java.util.EnumMap; diff --git a/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/DefaultNotificationRulesCache.java b/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/DefaultNotificationRulesCache.java index a02b7bf1e4..bac51d3585 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/DefaultNotificationRulesCache.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/rule/cache/DefaultNotificationRulesCache.java @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.msg.plugin.ComponentLifecycleMsg; import org.thingsboard.server.dao.notification.NotificationRuleService; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.Arrays; import java.util.Collections; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/service/ota/DefaultOtaPackageStateService.java b/application/src/main/java/org/thingsboard/server/service/ota/DefaultOtaPackageStateService.java index 6ab61426a8..a8d84bf63a 100644 --- a/application/src/main/java/org/thingsboard/server/service/ota/DefaultOtaPackageStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/ota/DefaultOtaPackageStateService.java @@ -51,7 +51,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.provider.TbCoreQueueFactory; import org.thingsboard.server.queue.provider.TbRuleEngineQueueFactory; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index 2bd0043046..f9dbf695c3 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -89,8 +89,8 @@ import org.thingsboard.server.service.ws.notification.sub.NotificationRequestUpd import org.thingsboard.server.service.ws.notification.sub.NotificationUpdate; import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscriptionUpdate; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.List; import java.util.Optional; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java index f8f6a7d25f..c47057b8dd 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java @@ -64,8 +64,8 @@ import org.thingsboard.server.service.queue.processing.TbRuleEngineSubmitStrateg import org.thingsboard.server.service.rpc.TbRuleEngineDeviceRpcService; import org.thingsboard.server.service.stats.RuleEngineStatisticsService; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -107,7 +107,6 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< private final TbRuleEngineDeviceRpcService tbDeviceRpcService; private final TbServiceInfoProvider serviceInfoProvider; private final QueueService queueService; - // private final TenantId tenantId; private final ConcurrentMap>> consumers = new ConcurrentHashMap<>(); private final ConcurrentMap consumerConfigurations = new ConcurrentHashMap<>(); private final ConcurrentMap consumerStats = new ConcurrentHashMap<>(); diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java index 2d517a2213..961d080aad 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java @@ -49,7 +49,7 @@ import org.thingsboard.server.service.queue.TbPackCallback; import org.thingsboard.server.service.queue.TbPackProcessingContext; import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.util.List; import java.util.Optional; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbCoreDeviceRpcService.java b/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbCoreDeviceRpcService.java index bca7c7d81a..2665c83884 100644 --- a/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbCoreDeviceRpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbCoreDeviceRpcService.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.service.rpc; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -38,8 +37,8 @@ import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; diff --git a/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java b/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java index 1fef6acbc0..3edd69bf0c 100644 --- a/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java +++ b/application/src/main/java/org/thingsboard/server/service/rpc/DefaultTbRuleEngineRpcService.java @@ -37,8 +37,8 @@ import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.util.TbRuleEngineComponent; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; diff --git a/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java b/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java index 9bb0a40a78..a3bdfc109e 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java +++ b/application/src/main/java/org/thingsboard/server/service/security/AccessValidator.java @@ -81,9 +81,9 @@ import org.thingsboard.server.service.security.permission.AccessControlService; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.BiConsumer; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java index 73cfe193e1..b380363e41 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/JwtTokenAuthenticationProcessingFilter.java @@ -27,10 +27,10 @@ import org.thingsboard.server.service.security.auth.JwtAuthenticationToken; import org.thingsboard.server.service.security.auth.jwt.extractor.TokenExtractor; import org.thingsboard.server.service.security.model.token.RawAccessJwtToken; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; public class JwtTokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter { diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java index 66c206a7ad..c6d22b1478 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/RefreshTokenProcessingFilter.java @@ -30,10 +30,10 @@ import org.thingsboard.server.service.security.auth.RefreshAuthenticationToken; import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; import org.thingsboard.server.service.security.model.token.RawAccessJwtToken; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @Slf4j diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/SkipPathRequestMatcher.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/SkipPathRequestMatcher.java index b4c4843d1b..e3eca7217d 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/SkipPathRequestMatcher.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/SkipPathRequestMatcher.java @@ -20,7 +20,7 @@ import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.List; import java.util.stream.Collectors; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java index 2f01decc73..22cf552ef5 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtHeaderTokenExtractor.java @@ -20,7 +20,7 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.config.ThingsboardSecurityConfiguration; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; @Component(value="jwtHeaderTokenExtractor") public class JwtHeaderTokenExtractor implements TokenExtractor { diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtQueryTokenExtractor.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtQueryTokenExtractor.java index 7a458ef052..f58224fa6c 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtQueryTokenExtractor.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/JwtQueryTokenExtractor.java @@ -20,7 +20,7 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.config.ThingsboardSecurityConfiguration; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; @Component(value="jwtQueryTokenExtractor") public class JwtQueryTokenExtractor implements TokenExtractor { diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/TokenExtractor.java b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/TokenExtractor.java index b1976dce9a..8d53395c57 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/TokenExtractor.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/jwt/extractor/TokenExtractor.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.service.security.auth.jwt.extractor; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; public interface TokenExtractor { - public String extract(HttpServletRequest request); + String extract(HttpServletRequest request); } \ No newline at end of file diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java index 9bbb3643e3..2875ef4c09 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AppleOAuth2ClientMapper.java @@ -29,7 +29,7 @@ import org.thingsboard.server.dao.oauth2.OAuth2User; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java index 91de70e35c..42a0e66171 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/BasicOAuth2ClientMapper.java @@ -24,7 +24,7 @@ import org.thingsboard.server.dao.oauth2.OAuth2User; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.Map; @Service(value = "basicOAuth2ClientMapper") diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CookieUtils.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CookieUtils.java index 429e185b3e..f2692dc296 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CookieUtils.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CookieUtils.java @@ -17,9 +17,9 @@ package org.thingsboard.server.service.security.auth.oauth2; import org.springframework.util.SerializationUtils; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.Base64; import java.util.Optional; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java index 9cac9b87a0..739bbeda79 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/CustomOAuth2ClientMapper.java @@ -30,7 +30,7 @@ import org.thingsboard.server.dao.oauth2.OAuth2User; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; @Service(value = "customOAuth2ClientMapper") @Slf4j diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/GithubOAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/GithubOAuth2ClientMapper.java index 0381e64298..326e77403c 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/GithubOAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/GithubOAuth2ClientMapper.java @@ -30,7 +30,7 @@ import org.thingsboard.server.dao.oauth2.OAuth2User; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Map; import java.util.Optional; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/HttpCookieOAuth2AuthorizationRequestRepository.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/HttpCookieOAuth2AuthorizationRequestRepository.java index d63f759dd3..d52df7aec8 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/HttpCookieOAuth2AuthorizationRequestRepository.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/HttpCookieOAuth2AuthorizationRequestRepository.java @@ -19,8 +19,8 @@ import org.springframework.security.oauth2.client.web.AuthorizationRequestReposi import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; import org.springframework.stereotype.Component; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; @Component public class HttpCookieOAuth2AuthorizationRequestRepository implements AuthorizationRequestRepository { @@ -48,9 +48,8 @@ public class HttpCookieOAuth2AuthorizationRequestRepository implements Authoriza CookieUtils.addCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CookieUtils.serialize(authorizationRequest), cookieExpireSeconds); } - @SuppressWarnings("deprecation") @Override - public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request) { + public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) { return this.loadAuthorizationRequest(request); } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/OAuth2ClientMapper.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/OAuth2ClientMapper.java index 23befd67c8..5de5d216e7 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/OAuth2ClientMapper.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/OAuth2ClientMapper.java @@ -19,7 +19,7 @@ import org.springframework.security.oauth2.client.authentication.OAuth2Authentic import org.thingsboard.server.common.data.oauth2.OAuth2Registration; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; public interface OAuth2ClientMapper { SecurityUser getOrCreateUserByClientPrincipal(HttpServletRequest request, OAuth2AuthenticationToken token, String providerAccessToken, OAuth2Registration registration); diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java index 4251c4bad4..5e416da302 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationFailureHandler.java @@ -27,9 +27,9 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.system.SystemSecurityService; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java index edfc826050..edbd96ec07 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/Oauth2AuthenticationSuccessHandler.java @@ -38,9 +38,9 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.system.SystemSecurityService; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationDetails.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationDetails.java index 1eafe66c8f..774fca5a48 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationDetails.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationDetails.java @@ -19,7 +19,7 @@ import lombok.Data; import ua_parser.Client; import ua_parser.Parser; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.io.Serializable; @Data diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationDetailsSource.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationDetailsSource.java index 36ce529e24..7d96c579ac 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationDetailsSource.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationDetailsSource.java @@ -17,7 +17,7 @@ package org.thingsboard.server.service.security.auth.rest; import org.springframework.security.authentication.AuthenticationDetailsSource; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; public class RestAuthenticationDetailsSource implements AuthenticationDetailsSource { diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationFailureHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationFailureHandler.java index e5d20ac546..81529c62e2 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationFailureHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationFailureHandler.java @@ -21,9 +21,9 @@ import org.springframework.security.web.authentication.AuthenticationFailureHand import org.springframework.stereotype.Component; import org.thingsboard.server.exception.ThingsboardErrorResponseHandler; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @Component(value = "defaultAuthenticationFailureHandler") diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationSuccessHandler.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationSuccessHandler.java index 0229170781..25e1460438 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationSuccessHandler.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAwareAuthenticationSuccessHandler.java @@ -30,10 +30,10 @@ import org.thingsboard.server.service.security.auth.mfa.config.TwoFaConfigManage import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; import java.io.IOException; import java.util.Optional; import java.util.concurrent.TimeUnit; diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java index b3ea3453b2..91ac6db711 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestLoginProcessingFilter.java @@ -31,10 +31,10 @@ import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; import org.thingsboard.server.service.security.model.UserPrincipal; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @Slf4j diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java index 23252c27ef..741055a8a2 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestPublicLoginProcessingFilter.java @@ -30,10 +30,10 @@ import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; import org.thingsboard.server.service.security.model.UserPrincipal; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @Slf4j diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java index 726a5d98f0..222db9d7c4 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java @@ -62,8 +62,8 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.utils.MiscUtils; import ua_parser.Client; -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java index 64550c438e..8c23fa6755 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.security.model.mfa.PlatformTwoFaSettin import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.service.security.model.SecurityUser; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; public interface SystemSecurityService { diff --git a/application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java b/application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java index ff1304208d..e21a8e5a79 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/DefaultSmsService.java @@ -34,10 +34,9 @@ import org.thingsboard.server.common.data.sms.config.TestSmsRequest; import org.thingsboard.server.common.stats.TbApiUsageReportClient; import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.service.apiusage.TbApiUsageStateService; -import org.thingsboard.server.service.transport.DefaultTransportApiService; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; @Service @Slf4j diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java index e33e501fbc..402be010ac 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java @@ -31,7 +31,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardExecutors; @@ -70,20 +69,18 @@ import org.thingsboard.server.common.stats.TbApiUsageReportClient; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.sql.query.EntityQueryRepository; -import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.dao.util.DbTypeInfoComponent; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.discovery.PartitionService; -import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.partition.AbstractPartitionBasedService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/service/stats/DefaultJsInvokeStats.java b/application/src/main/java/org/thingsboard/server/service/stats/DefaultJsInvokeStats.java index bca8df431a..fcd1e5413f 100644 --- a/application/src/main/java/org/thingsboard/server/service/stats/DefaultJsInvokeStats.java +++ b/application/src/main/java/org/thingsboard/server/service/stats/DefaultJsInvokeStats.java @@ -22,7 +22,7 @@ import org.thingsboard.server.common.stats.StatsCounter; import org.thingsboard.server.common.stats.StatsFactory; import org.thingsboard.server.common.stats.StatsType; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; @Service public class DefaultJsInvokeStats implements JsInvokeStats { diff --git a/application/src/main/java/org/thingsboard/server/service/stats/DefaultRuleEngineStatisticsService.java b/application/src/main/java/org/thingsboard/server/service/stats/DefaultRuleEngineStatisticsService.java index 1b5bfd56d1..50e35b8b28 100644 --- a/application/src/main/java/org/thingsboard/server/service/stats/DefaultRuleEngineStatisticsService.java +++ b/application/src/main/java/org/thingsboard/server/service/stats/DefaultRuleEngineStatisticsService.java @@ -32,7 +32,7 @@ import org.thingsboard.server.queue.util.TbRuleEngineComponent; import org.thingsboard.server.service.queue.TbRuleEngineConsumerStats; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.Collections; import java.util.List; import java.util.concurrent.ConcurrentHashMap; diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultSubscriptionManagerService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultSubscriptionManagerService.java index 60fce13560..c3c050f73b 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultSubscriptionManagerService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultSubscriptionManagerService.java @@ -66,8 +66,8 @@ import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscript import org.thingsboard.server.service.ws.telemetry.sub.AlarmSubscriptionUpdate; import org.thingsboard.server.service.ws.telemetry.sub.TelemetrySubscriptionUpdate; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.HashSet; import java.util.List; diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java index 4b37ba26b5..a70f0cba57 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java @@ -66,8 +66,8 @@ import org.thingsboard.server.service.ws.telemetry.cmd.v2.LatestValueCmd; import org.thingsboard.server.service.ws.telemetry.cmd.v2.TimeSeriesCmd; import org.thingsboard.server.service.ws.telemetry.cmd.v2.UnsubscribeCmd; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java index 64f1de8662..f8173d75e3 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java @@ -35,8 +35,8 @@ import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscript import org.thingsboard.server.service.ws.telemetry.sub.AlarmSubscriptionUpdate; import org.thingsboard.server.service.ws.telemetry.sub.TelemetrySubscriptionUpdate; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.Collections; import java.util.HashSet; import java.util.Map; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java index 45805c5939..87532fd587 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java @@ -59,9 +59,9 @@ import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; import org.thingsboard.server.utils.CsvUtils; import org.thingsboard.server.utils.TypeCastUtil; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java index a63600619a..075632774a 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java @@ -87,8 +87,8 @@ import org.thingsboard.server.service.sync.vc.data.ReimportTask; import org.thingsboard.server.service.sync.vc.data.SimpleEntitiesExportCtx; import org.thingsboard.server.service.sync.vc.repository.TbRepositorySettingsService; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.time.Instant; import java.util.ArrayList; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/service/system/DefaultSystemInfoService.java b/application/src/main/java/org/thingsboard/server/service/system/DefaultSystemInfoService.java index 80d4cede03..4b4a164856 100644 --- a/application/src/main/java/org/thingsboard/server/service/system/DefaultSystemInfoService.java +++ b/application/src/main/java/org/thingsboard/server/service/system/DefaultSystemInfoService.java @@ -48,8 +48,8 @@ import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; -import javax.annotation.Nullable; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/AbstractSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/AbstractSubscriptionService.java index 145f43fa3f..0e791c50c2 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/AbstractSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/AbstractSubscriptionService.java @@ -32,9 +32,9 @@ import org.thingsboard.server.queue.discovery.TbApplicationEventListener; import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; import org.thingsboard.server.service.subscription.SubscriptionManagerService; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java index 3f5e52796a..c2888f7487 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java @@ -48,9 +48,9 @@ import org.thingsboard.server.service.apiusage.TbApiUsageStateService; import org.thingsboard.server.service.entitiy.entityview.TbEntityViewService; import org.thingsboard.server.service.subscription.TbSubscriptionUtils; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/service/transport/TbCoreTransportApiService.java b/application/src/main/java/org/thingsboard/server/service/transport/TbCoreTransportApiService.java index a2afe6b433..4276d7b465 100644 --- a/application/src/main/java/org/thingsboard/server/service/transport/TbCoreTransportApiService.java +++ b/application/src/main/java/org/thingsboard/server/service/transport/TbCoreTransportApiService.java @@ -34,8 +34,8 @@ import org.thingsboard.server.queue.provider.TbCoreQueueFactory; import org.thingsboard.server.queue.util.AfterStartUp; import org.thingsboard.server.queue.util.TbCoreComponent; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.concurrent.ExecutorService; /** diff --git a/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java b/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java index ef066a73f6..b7cf161853 100644 --- a/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java +++ b/application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java @@ -33,7 +33,7 @@ import org.thingsboard.server.queue.notification.NotificationRuleProcessor; import org.thingsboard.server.queue.util.AfterStartUp; import org.thingsboard.server.queue.util.TbCoreComponent; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; diff --git a/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java b/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java index 21d69d6b42..711a218f0e 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java @@ -81,9 +81,9 @@ import org.thingsboard.server.service.ws.telemetry.cmd.v2.EntityDataUpdate; import org.thingsboard.server.service.ws.telemetry.cmd.v2.UnsubscribeCmd; import org.thingsboard.server.service.ws.telemetry.sub.TelemetrySubscriptionUpdate; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; diff --git a/application/src/main/java/org/thingsboard/server/utils/MiscUtils.java b/application/src/main/java/org/thingsboard/server/utils/MiscUtils.java index 2fc0fa134c..efa642e8b1 100644 --- a/application/src/main/java/org/thingsboard/server/utils/MiscUtils.java +++ b/application/src/main/java/org/thingsboard/server/utils/MiscUtils.java @@ -18,7 +18,7 @@ package org.thingsboard.server.utils; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.nio.charset.Charset; diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index f776887287..98635273b8 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -597,7 +597,7 @@ spring: enabled: "true" jpa: properties: - javax.persistence.query.timeout: "${JAVAX_PERSISTENCE_QUERY_TIMEOUT:30000}" + jakarta.persistence.query.timeout: "${JAVAX_PERSISTENCE_QUERY_TIMEOUT:30000}" open-in-view: "false" hibernate: ddl-auto: "none" diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java index 5809ab5e42..dbf7184bf6 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java @@ -21,7 +21,7 @@ import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootContextLoader; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.test.annotation.DirtiesContext; diff --git a/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java index 15d5b5c809..b42e6f9733 100644 --- a/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/DeviceEdgeTest.java @@ -270,7 +270,7 @@ public class DeviceEdgeTest extends AbstractEdgeTest { (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration(); profileConfiguration.setMaxDevices(1); tenantProfile.getProfileData().setConfiguration(profileConfiguration); - doPost("/api/tenantProfile/", tenantProfile, TenantProfile.class); + doPost("/api/tenantProfile", tenantProfile, TenantProfile.class); loginTenantAdmin(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 64382d5d51..7d2bc51ce6 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -30,7 +30,6 @@ import org.junit.Before; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.TestPropertySource; -import org.springframework.util.SocketUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.common.data.Device; @@ -304,9 +303,12 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte public void createNewClient(Security security, Configuration coapConfig, boolean isRpc, String endpoint, boolean isBootstrap, Security securityBs) throws Exception { this.clientDestroy(); lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); - int clientPort = SocketUtils.findAvailableUdpPort(); - lwM2MTestClient.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, - securityBs, this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest); + + try (ServerSocket socket = new ServerSocket(0)) { + int clientPort = socket.getLocalPort(); + lwM2MTestClient.init(security, coapConfig, clientPort, isRpc, isBootstrap, this.shortServerId, this.shortServerIdBs, + securityBs, this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest); + } } private void clientDestroy() { diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index 79b53bf15e..f041f0be55 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCred import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import java.nio.charset.StandardCharsets; import static org.eclipse.leshan.client.object.Security.psk; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java index c22a25a504..c75ecbd820 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java @@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.device.credentials.lwm2m.RPKClientCred import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import java.security.PrivateKey; import java.security.cert.X509Certificate; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index e448a41f4b..1a908bffb8 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCre import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; import java.security.PrivateKey; import java.security.cert.X509Certificate; diff --git a/common/cache/pom.xml b/common/cache/pom.xml index 440860fda6..a14c84d3f4 100644 --- a/common/cache/pom.xml +++ b/common/cache/pom.xml @@ -57,8 +57,8 @@ caffeine - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api org.apache.commons diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/CacheSpecsMap.java b/common/cache/src/main/java/org/thingsboard/server/cache/CacheSpecsMap.java index bf3cc25a52..451d0e7c5d 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/CacheSpecsMap.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/CacheSpecsMap.java @@ -22,7 +22,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.thingsboard.server.common.data.CacheConstants; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.Map; @Configuration diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java index c5af954392..0332a25452 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java @@ -27,6 +27,7 @@ import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.types.Expiration; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; +import redis.clients.jedis.Connection; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.util.JedisClusterCRC16; @@ -149,7 +150,7 @@ public abstract class RedisTbTransactionalCacheguava - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api com.github.fge diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java index 35e77ff584..afbd148c58 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/DefaultCoapServerService.java @@ -27,8 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.thingsboard.common.util.ThingsBoardThreadFactory; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index 029c660500..6cfb7706a8 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -53,8 +53,8 @@ guava - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api com.github.fge diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/AbstractCassandraCluster.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/AbstractCassandraCluster.java index 293039a1d8..e20b4af7af 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/AbstractCassandraCluster.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/AbstractCassandraCluster.java @@ -29,7 +29,7 @@ import org.thingsboard.server.dao.cassandra.guava.GuavaSession; import org.thingsboard.server.dao.cassandra.guava.GuavaSessionBuilder; import org.thingsboard.server.dao.cassandra.guava.GuavaSessionUtils; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.file.Paths; @Slf4j diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraCluster.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraCluster.java index c2438f258a..eab9108790 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraCluster.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraCluster.java @@ -19,7 +19,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.thingsboard.server.dao.util.NoSqlAnyDao; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; @Component("CassandraCluster") @NoSqlAnyDao diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraDriverOptions.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraDriverOptions.java index 1b6524f8a9..9474fb574e 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraDriverOptions.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraDriverOptions.java @@ -29,7 +29,7 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.dao.util.NoSqlAnyDao; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraInstallCluster.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraInstallCluster.java index 13916ea48a..efa9fb7799 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraInstallCluster.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/cassandra/CassandraInstallCluster.java @@ -19,7 +19,7 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import org.thingsboard.server.dao.util.NoSqlAnyDao; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; @Component("CassandraInstallCluster") @NoSqlAnyDao diff --git a/common/data/pom.xml b/common/data/pom.xml index 3257d4cf32..68f7eb2393 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -37,8 +37,8 @@ - javax.validation - validation-api + jakarta.validation + jakarta.validation-api org.owasp.antisamy diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java index 3c791171d5..43927acd02 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DashboardInfo.java @@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.HashSet; import java.util.Objects; import java.util.Set; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java index 7ff7d72023..7de86b86d3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java @@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.io.ByteArrayInputStream; import java.io.IOException; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java index 0f3dd5b636..1c71e66b87 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java @@ -27,8 +27,8 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; @Data @Builder diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java index 23edafd6d2..e97b40e1f1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java @@ -24,8 +24,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; @Data @Builder diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java index b771d591b1..a8b83a1cf6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java @@ -20,7 +20,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.io.Serializable; import java.util.List; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java index 00562ef677..7a44d707f9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.query.EntityKeyValueType; import org.thingsboard.server.common.data.query.KeyFilterPredicate; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.io.Serializable; @ApiModel diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java index 5302d42cad..0f23ae5624 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java @@ -21,7 +21,7 @@ import lombok.Data; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.io.Serializable; @ApiModel diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java index 24fff47fc2..96f365a152 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.io.Serializable; import java.util.List; import java.util.TreeMap; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java index 389b87f813..f6b2de915b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java @@ -19,7 +19,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.io.Serializable; import java.util.List; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseAttributeKvEntry.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseAttributeKvEntry.java index eef43dd8b7..6e192ea473 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseAttributeKvEntry.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BaseAttributeKvEntry.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data.kv; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.Optional; /** diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BasicTsKvEntry.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BasicTsKvEntry.java index 3c612d3b78..a2e6bc0128 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/BasicTsKvEntry.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/BasicTsKvEntry.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data.kv; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.Objects; import java.util.Optional; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java index 61d6982264..201fef7e0a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequest.java @@ -33,8 +33,8 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.template.NotificationTemplate; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; import java.util.List; import java.util.UUID; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestConfig.java index 8bd9214f6b..b10d772c0b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestConfig.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.notification; import lombok.Data; -import javax.validation.constraints.Max; +import jakarta.validation.constraints.Max; @Data public class NotificationRequestConfig { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/DefaultNotificationRuleRecipientsConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/DefaultNotificationRuleRecipientsConfig.java index 8c94ebf416..a37291f3ec 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/DefaultNotificationRuleRecipientsConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/DefaultNotificationRuleRecipientsConfig.java @@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.notification.rule; import lombok.Data; import lombok.EqualsAndHashCode; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; import java.util.List; import java.util.Map; import java.util.UUID; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/EscalatedNotificationRuleRecipientsConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/EscalatedNotificationRuleRecipientsConfig.java index c8858321de..c4899418ec 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/EscalatedNotificationRuleRecipientsConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/EscalatedNotificationRuleRecipientsConfig.java @@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.notification.rule; import lombok.Data; import lombok.EqualsAndHashCode; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; import java.util.List; import java.util.Map; import java.util.UUID; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRule.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRule.java index 607ca7f639..a54a07f3ab 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRule.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRule.java @@ -30,10 +30,10 @@ import org.thingsboard.server.common.data.notification.rule.trigger.Notification import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import java.io.Serializable; @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRuleRecipientsConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRuleRecipientsConfig.java index d31ec098ca..ed3a8c2cd6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRuleRecipientsConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRuleRecipientsConfig.java @@ -23,7 +23,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; import lombok.Data; import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import java.io.Serializable; import java.util.List; import java.util.Map; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java index 59ad9e5316..02a3bb8e23 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java @@ -22,7 +22,7 @@ import lombok.NoArgsConstructor; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.alarm.AlarmSeverity; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; import java.util.Set; @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmNotificationRuleTriggerConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmNotificationRuleTriggerConfig.java index 6118e9da00..3a2eeaadc7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmNotificationRuleTriggerConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmNotificationRuleTriggerConfig.java @@ -22,7 +22,7 @@ import lombok.NoArgsConstructor; import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; import org.thingsboard.server.common.data.alarm.AlarmSeverity; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; import java.io.Serializable; import java.util.Set; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/DeviceActivityNotificationRuleTriggerConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/DeviceActivityNotificationRuleTriggerConfig.java index 8deeada7c0..c0ce99e76d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/DeviceActivityNotificationRuleTriggerConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/DeviceActivityNotificationRuleTriggerConfig.java @@ -20,7 +20,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; import java.util.Set; import java.util.UUID; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/EntitiesLimitNotificationRuleTriggerConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/EntitiesLimitNotificationRuleTriggerConfig.java index a40ddfb081..8aeb715a11 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/EntitiesLimitNotificationRuleTriggerConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/EntitiesLimitNotificationRuleTriggerConfig.java @@ -21,7 +21,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.thingsboard.server.common.data.EntityType; -import javax.validation.constraints.Max; +import jakarta.validation.constraints.Max; import java.util.Set; @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationSettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationSettings.java index 4ed6cfc30d..86f5dee26a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationSettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationSettings.java @@ -18,8 +18,8 @@ package org.thingsboard.server.common.data.notification.settings; import lombok.Data; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import java.io.Serializable; import java.util.Map; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/SlackNotificationDeliveryMethodConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/SlackNotificationDeliveryMethodConfig.java index 22a14c500c..98630482e4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/SlackNotificationDeliveryMethodConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/SlackNotificationDeliveryMethodConfig.java @@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.notification.settings; import lombok.Data; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; @Data public class SlackNotificationDeliveryMethodConfig implements NotificationDeliveryMethodConfig { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java index 9a2f9a5306..d49c2e893e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java @@ -25,9 +25,9 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; @Data @EqualsAndHashCode(callSuper = true) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/CustomerUsersFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/CustomerUsersFilter.java index dd4c38b2a0..16d760c686 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/CustomerUsersFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/CustomerUsersFilter.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.notification.targets.platform; import lombok.Data; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import java.util.UUID; @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/PlatformUsersNotificationTargetConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/PlatformUsersNotificationTargetConfig.java index d04411a194..7adb1aaebf 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/PlatformUsersNotificationTargetConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/PlatformUsersNotificationTargetConfig.java @@ -20,8 +20,8 @@ import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.notification.targets.NotificationTargetConfig; import org.thingsboard.server.common.data.notification.targets.NotificationTargetType; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; @Data @EqualsAndHashCode(callSuper = true) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UserListFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UserListFilter.java index d190000576..283dd78a97 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UserListFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/platform/UserListFilter.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.notification.targets.platform; import lombok.Data; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; import java.util.List; import java.util.UUID; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/slack/SlackConversation.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/slack/SlackConversation.java index ed9dee71b6..7e9d62e067 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/slack/SlackConversation.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/slack/SlackConversation.java @@ -24,8 +24,8 @@ import lombok.NoArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.thingsboard.server.common.data.notification.targets.NotificationRecipient; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import static org.apache.commons.lang3.StringUtils.isEmpty; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/slack/SlackNotificationTargetConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/slack/SlackNotificationTargetConfig.java index 5eb2b9a44f..6c55611904 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/slack/SlackNotificationTargetConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/slack/SlackNotificationTargetConfig.java @@ -20,8 +20,8 @@ import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.notification.targets.NotificationTargetConfig; import org.thingsboard.server.common.data.notification.targets.NotificationTargetType; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; @Data @EqualsAndHashCode(callSuper = true) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java index ecb7f2d2b6..25f3bed1b9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/DeliveryMethodNotificationTemplate.java @@ -25,7 +25,7 @@ import lombok.NoArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "method") diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/EmailDeliveryMethodNotificationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/EmailDeliveryMethodNotificationTemplate.java index fe909a104e..ee9c1432e2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/EmailDeliveryMethodNotificationTemplate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/EmailDeliveryMethodNotificationTemplate.java @@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.notification.NotificationDeliveryMetho import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; @Data @NoArgsConstructor diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplate.java index 71da2f862b..b0937b397a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplate.java @@ -26,9 +26,9 @@ import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; @Data @EqualsAndHashCode(callSuper = true) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplateConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplateConfig.java index 1dcb4aec0c..0797ecf164 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplateConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/NotificationTemplateConfig.java @@ -18,8 +18,8 @@ package org.thingsboard.server.common.data.notification.template; import lombok.Data; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; import java.util.Map; @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/WebDeliveryMethodNotificationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/WebDeliveryMethodNotificationTemplate.java index f26ed00568..cba325c064 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/WebDeliveryMethodNotificationTemplate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/WebDeliveryMethodNotificationTemplate.java @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.notification.NotificationDeliveryMetho import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; import java.util.Optional; @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationTemplate.java index 988af25d92..568664c01b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationTemplate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationTemplate.java @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId; import org.thingsboard.server.common.data.validation.Length; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.util.List; @EqualsAndHashCode(callSuper = true) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java index 0a149d90e2..89c8bcaa07 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java @@ -21,7 +21,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import javax.validation.Valid; +import jakarta.validation.Valid; @Builder(toBuilder = true) @EqualsAndHashCode diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateValue.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateValue.java index 28f401e22e..8f976459e3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateValue.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateValue.java @@ -22,7 +22,7 @@ import lombok.Data; import lombok.Getter; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.Valid; +import jakarta.validation.Valid; import java.io.Serializable; @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java index 125ca4665a..e233e8291b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.query; import lombok.Data; -import javax.validation.Valid; +import jakarta.validation.Valid; @Data public class StringFilterPredicate implements SimpleKeyFilterPredicate { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/PlatformTwoFaSettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/PlatformTwoFaSettings.java index 4f7cf4f545..7918813fa3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/PlatformTwoFaSettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/PlatformTwoFaSettings.java @@ -20,10 +20,10 @@ import lombok.Data; import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderConfig; import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType; -import javax.validation.Valid; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Pattern; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import java.util.List; import java.util.Optional; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/BackupCodeTwoFaAccountConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/BackupCodeTwoFaAccountConfig.java index 59ba4770b9..504bb12964 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/BackupCodeTwoFaAccountConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/BackupCodeTwoFaAccountConfig.java @@ -20,7 +20,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType; -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; import java.util.Set; @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/EmailTwoFaAccountConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/EmailTwoFaAccountConfig.java index 270f5f7298..590f314ecf 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/EmailTwoFaAccountConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/EmailTwoFaAccountConfig.java @@ -19,8 +19,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; @Data @EqualsAndHashCode(callSuper = true) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/SmsTwoFaAccountConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/SmsTwoFaAccountConfig.java index d1b739c378..dfbaa586af 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/SmsTwoFaAccountConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/SmsTwoFaAccountConfig.java @@ -19,8 +19,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; @EqualsAndHashCode(callSuper = true) @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/TotpTwoFaAccountConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/TotpTwoFaAccountConfig.java index 35c60bd540..60cd096ccb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/TotpTwoFaAccountConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/account/TotpTwoFaAccountConfig.java @@ -19,8 +19,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; @Data @EqualsAndHashCode(callSuper = true) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/BackupCodeTwoFaProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/BackupCodeTwoFaProviderConfig.java index 36ac3150b5..a547a00f8d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/BackupCodeTwoFaProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/BackupCodeTwoFaProviderConfig.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.security.model.mfa.provider; import lombok.Data; -import javax.validation.constraints.Min; +import jakarta.validation.constraints.Min; @Data public class BackupCodeTwoFaProviderConfig implements TwoFaProviderConfig { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/OtpBasedTwoFaProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/OtpBasedTwoFaProviderConfig.java index f304b5858e..41d767b86f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/OtpBasedTwoFaProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/OtpBasedTwoFaProviderConfig.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.security.model.mfa.provider; import lombok.Data; -import javax.validation.constraints.Min; +import jakarta.validation.constraints.Min; @Data public abstract class OtpBasedTwoFaProviderConfig implements TwoFaProviderConfig { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/SmsTwoFaProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/SmsTwoFaProviderConfig.java index e5a9fb0f67..d7adfe7020 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/SmsTwoFaProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/SmsTwoFaProviderConfig.java @@ -18,8 +18,8 @@ package org.thingsboard.server.common.data.security.model.mfa.provider; import lombok.Data; import lombok.EqualsAndHashCode; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; @EqualsAndHashCode(callSuper = true) @Data diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/TotpTwoFaProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/TotpTwoFaProviderConfig.java index 70e4abc8a9..83fdc97d23 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/TotpTwoFaProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/mfa/provider/TotpTwoFaProviderConfig.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.security.model.mfa.provider; import lombok.Data; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; @Data public class TotpTwoFaProviderConfig implements TwoFaProviderConfig { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/validation/Length.java b/common/data/src/main/java/org/thingsboard/server/common/data/validation/Length.java index cb7b9b1693..a236f20037 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/validation/Length.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/validation/Length.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.common.data.validation; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/validation/NoXss.java b/common/data/src/main/java/org/thingsboard/server/common/data/validation/NoXss.java index fb7b048f7e..6b972ba112 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/validation/NoXss.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/validation/NoXss.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.common.data.validation; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/azure/servicebus/TbServiceBusQueueConfigs.java b/common/queue/src/main/java/org/thingsboard/server/queue/azure/servicebus/TbServiceBusQueueConfigs.java index 5e404bc928..2fea26625d 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/azure/servicebus/TbServiceBusQueueConfigs.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/azure/servicebus/TbServiceBusQueueConfigs.java @@ -21,7 +21,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; import org.thingsboard.server.queue.util.PropertyUtils; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.Map; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/common/AbstractTbQueueConsumerTemplate.java b/common/queue/src/main/java/org/thingsboard/server/queue/common/AbstractTbQueueConsumerTemplate.java index 86146dabd1..003306c83a 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/common/AbstractTbQueueConsumerTemplate.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/common/AbstractTbQueueConsumerTemplate.java @@ -21,7 +21,7 @@ import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.queue.TbQueueConsumer; import org.thingsboard.server.queue.TbQueueMsg; -import javax.annotation.Nonnull; +import jakarta.annotation.Nonnull; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/common/DefaultTbQueueRequestTemplate.java b/common/queue/src/main/java/org/thingsboard/server/queue/common/DefaultTbQueueRequestTemplate.java index 453183fc58..0b1988935b 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/common/DefaultTbQueueRequestTemplate.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/common/DefaultTbQueueRequestTemplate.java @@ -33,7 +33,7 @@ import org.thingsboard.server.queue.TbQueueMsgMetadata; import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.TbQueueRequestTemplate; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java index 3c85aef350..2f69f79c4b 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java @@ -28,7 +28,7 @@ import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.ServiceInfo; import org.thingsboard.server.queue.util.AfterContextReady; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java index 08f2e849f8..d0b732ba71 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java @@ -33,7 +33,7 @@ import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; import org.thingsboard.server.queue.discovery.event.ServiceListChangedEvent; import org.thingsboard.server.queue.util.AfterStartUp; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; @@ -379,7 +379,7 @@ public class HashPartitionService implements PartitionService { } } - private TenantId getIsolatedOrSystemTenantId(ServiceType serviceType, TenantId tenantId) { + protected TenantId getIsolatedOrSystemTenantId(ServiceType serviceType, TenantId tenantId) { return isIsolated(serviceType, tenantId) ? tenantId : TenantId.SYS_TENANT_ID; } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java index fcf80bcf3d..3a8189aef8 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/ZkDiscoveryService.java @@ -40,8 +40,8 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.AfterStartUp; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.Executors; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/environment/EnvironmentLogService.java b/common/queue/src/main/java/org/thingsboard/server/queue/environment/EnvironmentLogService.java index 0a9e3a1ac0..77e52cedf6 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/environment/EnvironmentLogService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/environment/EnvironmentLogService.java @@ -20,7 +20,7 @@ import org.apache.zookeeper.Environment; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; /** * Created by igor on 11/24/16. diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaConsumerStatsService.java b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaConsumerStatsService.java index 00f76ed50b..d15b29799a 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaConsumerStatsService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaConsumerStatsService.java @@ -35,8 +35,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.queue.discovery.PartitionService; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.time.Duration; import java.util.ArrayList; import java.util.List; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java index 9888066ee7..b688dfb045 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/kafka/TbKafkaTopicConfigs.java @@ -21,7 +21,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; import org.thingsboard.server.queue.util.PropertyUtils; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.Map; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java index 08609b13d0..d1000c7580 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsMonolithQueueFactory.java @@ -54,7 +54,7 @@ import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java index 257ac37408..244ca4a985 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbCoreQueueFactory.java @@ -52,7 +52,7 @@ import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbRuleEngineQueueFactory.java index 9b1f9dba0d..0b66e93299 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbRuleEngineQueueFactory.java @@ -45,7 +45,7 @@ import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbVersionControlQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbVersionControlQueueFactory.java index 24453d3c5c..89fe2b0c6e 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbVersionControlQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTbVersionControlQueueFactory.java @@ -30,7 +30,7 @@ import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && '${service.type:null}'=='tb-vc-executor'") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTransportQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTransportQueueFactory.java index c1ae9fe855..aee2ff39dc 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTransportQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/AwsSqsTransportQueueFactory.java @@ -41,7 +41,7 @@ import org.thingsboard.server.queue.sqs.TbAwsSqsProducerTemplate; import org.thingsboard.server.queue.sqs.TbAwsSqsQueueAttributes; import org.thingsboard.server.queue.sqs.TbAwsSqsSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='aws-sqs' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java index 364abcff4c..86b7da5d31 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java @@ -54,7 +54,7 @@ import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.AtomicLong; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java index 9c25a5d420..edd092f3f0 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java @@ -53,7 +53,7 @@ import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java index b8e07a45f7..a99e874310 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java @@ -49,7 +49,7 @@ import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.AtomicLong; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbTransportQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbTransportQueueFactory.java index 51e3dc99c7..67e12568f9 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbTransportQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbTransportQueueFactory.java @@ -42,7 +42,7 @@ import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='kafka' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbVersionControlQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbVersionControlQueueFactory.java index d851956420..ace91f0e74 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbVersionControlQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbVersionControlQueueFactory.java @@ -34,7 +34,7 @@ import org.thingsboard.server.queue.kafka.TbKafkaTopicConfigs; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='kafka' && '${service.type:null}'=='tb-vc-executor'") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java index 857641098c..79d252c4e5 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubMonolithQueueFactory.java @@ -54,7 +54,7 @@ import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java index f197082829..16c0cba977 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbCoreQueueFactory.java @@ -51,7 +51,7 @@ import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbRuleEngineQueueFactory.java index 9766bf9915..5416a78699 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbRuleEngineQueueFactory.java @@ -48,7 +48,7 @@ import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbVersionControlQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbVersionControlQueueFactory.java index 57db7b884c..e0431a28aa 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbVersionControlQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTbVersionControlQueueFactory.java @@ -30,7 +30,7 @@ import org.thingsboard.server.queue.pubsub.TbPubSubSubscriptionSettings; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='pubsub' && '${service.type:null}'=='tb-vc-executor'") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTransportQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTransportQueueFactory.java index d5665e2fbe..9581e3833e 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTransportQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/PubSubTransportQueueFactory.java @@ -41,7 +41,7 @@ import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='pubsub' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java index 0318b5d06f..d4a3824f1d 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqMonolithQueueFactory.java @@ -54,7 +54,7 @@ import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java index 45f5a92980..362a118190 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbCoreQueueFactory.java @@ -51,7 +51,7 @@ import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbRuleEngineQueueFactory.java index 37633ced95..66ef4dfc36 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbRuleEngineQueueFactory.java @@ -48,7 +48,7 @@ import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbVersionControlQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbVersionControlQueueFactory.java index ed1da6a302..1d2ff91bb0 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbVersionControlQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTbVersionControlQueueFactory.java @@ -30,7 +30,7 @@ import org.thingsboard.server.queue.rabbitmq.TbRabbitMqSettings; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && '${service.type:null}'=='tb-vc-executor'") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTransportQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTransportQueueFactory.java index f11a877fc5..9bd84e63a2 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTransportQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/RabbitMqTransportQueueFactory.java @@ -41,7 +41,7 @@ import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='rabbitmq' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java index 950e49dc93..eacf4f4aa8 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusMonolithQueueFactory.java @@ -53,7 +53,7 @@ import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java index b92629633d..fc31678eb5 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbCoreQueueFactory.java @@ -51,7 +51,7 @@ import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbRuleEngineQueueFactory.java index a1571becc7..71051e0df0 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbRuleEngineQueueFactory.java @@ -48,7 +48,7 @@ import org.thingsboard.server.queue.settings.TbQueueRemoteJsInvokeSettings; import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.nio.charset.StandardCharsets; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbVersionControlQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbVersionControlQueueFactory.java index 24cb4fe8bc..b327d81f6f 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbVersionControlQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTbVersionControlQueueFactory.java @@ -30,7 +30,7 @@ import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.settings.TbQueueCoreSettings; import org.thingsboard.server.queue.settings.TbQueueVersionControlSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='service-bus' && '${service.type:null}'=='tb-vc-executor'") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTransportQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTransportQueueFactory.java index 15e661f5b0..2443bce7a3 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTransportQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/ServiceBusTransportQueueFactory.java @@ -41,7 +41,7 @@ import org.thingsboard.server.queue.settings.TbQueueRuleEngineSettings; import org.thingsboard.server.queue.settings.TbQueueTransportApiSettings; import org.thingsboard.server.queue.settings.TbQueueTransportNotificationSettings; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; @Component @ConditionalOnExpression("'${queue.type:null}'=='service-bus' && (('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true') || '${service.type:null}'=='tb-transport')") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java index 71f79627cc..3890a5b8e7 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbCoreQueueProducerProvider.java @@ -27,7 +27,7 @@ import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.util.TbCoreComponent; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; @Service @TbCoreComponent diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineProducerProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineProducerProvider.java index 137b84a208..2769fbf4d2 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineProducerProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbRuleEngineProducerProvider.java @@ -27,7 +27,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceM import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.common.TbProtoQueueMsg; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; @Service @ConditionalOnExpression("'${service.type:null}'=='tb-rule-engine'") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbTransportQueueProducerProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbTransportQueueProducerProvider.java index e9177d8b1c..3c5c63d740 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbTransportQueueProducerProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbTransportQueueProducerProvider.java @@ -27,7 +27,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceM import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.common.TbProtoQueueMsg; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; @Service @ConditionalOnExpression("'${service.type:null}'=='tb-transport'") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbVersionControlProducerProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbVersionControlProducerProvider.java index 77a27dedd8..bb5289350c 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbVersionControlProducerProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/TbVersionControlProducerProvider.java @@ -27,7 +27,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToUsageStatsServiceM import org.thingsboard.server.queue.TbQueueProducer; import org.thingsboard.server.queue.common.TbProtoQueueMsg; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; @Service @ConditionalOnExpression("'${service.type:null}'=='tb-vc-executor'") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSettings.java b/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSettings.java index fe9d85c306..7594cde20d 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSettings.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSettings.java @@ -24,7 +24,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.io.ByteArrayInputStream; import java.io.IOException; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSubscriptionSettings.java b/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSubscriptionSettings.java index 3d7ab85ecc..0288aa021c 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSubscriptionSettings.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/pubsub/TbPubSubSubscriptionSettings.java @@ -21,7 +21,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; import org.thingsboard.server.queue.util.PropertyUtils; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.Map; @Component diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqQueueArguments.java b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqQueueArguments.java index cb96abdf3c..ac03ca7da9 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqQueueArguments.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqQueueArguments.java @@ -21,7 +21,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java index 0273374ddc..f8e8d59877 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java @@ -22,7 +22,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; @Slf4j @ConditionalOnExpression("'${queue.type:null}'=='rabbitmq'") diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java b/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java index 808e7c2c83..eaf90ead0f 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java @@ -18,8 +18,8 @@ package org.thingsboard.server.queue.scheduler; import org.springframework.stereotype.Component; import org.thingsboard.common.util.ThingsBoardThreadFactory; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/sqs/TbAwsSqsQueueAttributes.java b/common/queue/src/main/java/org/thingsboard/server/queue/sqs/TbAwsSqsQueueAttributes.java index 66110ade74..b1c033ed29 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/sqs/TbAwsSqsQueueAttributes.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/sqs/TbAwsSqsQueueAttributes.java @@ -22,7 +22,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.StringUtils; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.HashMap; import java.util.Map; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageReportClient.java b/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageReportClient.java index 8a5857e6a7..e56c9e25c5 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageReportClient.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/usagestats/DefaultTbApiUsageReportClient.java @@ -37,7 +37,7 @@ import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.provider.TbQueueProducerProvider; import org.thingsboard.server.queue.scheduler.SchedulerComponent; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.EnumMap; import java.util.Random; import java.util.UUID; diff --git a/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java b/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java index dc4068edcc..63977d6fab 100644 --- a/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java +++ b/common/script/remote-js-client/src/main/java/org/thingsboard/server/service/script/RemoteJsInvokeService.java @@ -37,8 +37,8 @@ import org.thingsboard.server.queue.TbQueueRequestTemplate; import org.thingsboard.server.queue.common.TbProtoJsQueueMsg; import org.thingsboard.server.queue.common.TbProtoQueueMsg; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.Map; import java.util.Optional; import java.util.UUID; diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/ScriptStatCallback.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/ScriptStatCallback.java index 42131c9dc3..9b449f63e3 100644 --- a/common/script/script-api/src/main/java/org/thingsboard/script/api/ScriptStatCallback.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/ScriptStatCallback.java @@ -19,7 +19,7 @@ import com.google.common.util.concurrent.FutureCallback; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/js/NashornJsInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/js/NashornJsInvokeService.java index 9e3ae3c032..18f9a63e76 100644 --- a/common/script/script-api/src/main/java/org/thingsboard/script/api/js/NashornJsInvokeService.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/js/NashornJsInvokeService.java @@ -31,8 +31,8 @@ import org.thingsboard.script.api.TbScriptException; import org.thingsboard.server.common.stats.TbApiUsageReportClient; import org.thingsboard.server.common.stats.TbApiUsageStateClient; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java index f98e33b615..8b0274c81d 100644 --- a/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java +++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DefaultTbelInvokeService.java @@ -43,8 +43,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.stats.TbApiUsageReportClient; import org.thingsboard.server.common.stats.TbApiUsageStateClient; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.util.Calendar; diff --git a/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java b/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java index 6f5c7eb752..97e5d38f1e 100644 --- a/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java +++ b/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java @@ -24,7 +24,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.StringUtils; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.concurrent.atomic.AtomicInteger; @Service diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java index 8ad2d01e47..ff20d95d5e 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java @@ -27,8 +27,8 @@ import org.thingsboard.server.common.data.TbTransportService; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.transport.coap.efento.CoapEfentoTransportResource; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.net.UnknownHostException; @Service("CoapTransportService") diff --git a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java index 041ae0510d..4cc876a122 100644 --- a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java +++ b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java @@ -64,7 +64,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcRequestMs import org.thingsboard.server.gen.transport.TransportProtos.ToServerRpcResponseMsg; import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import java.util.Arrays; import java.util.List; import java.util.UUID; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java index 209478f4ff..75a2f936ca 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java @@ -33,8 +33,8 @@ import org.thingsboard.server.transport.lwm2m.bootstrap.store.LwM2MInMemoryBoots import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.security.cert.X509Certificate; import static java.util.concurrent.TimeUnit.MILLISECONDS; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/TbLwM2MDtlsBootstrapCertificateVerifier.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/TbLwM2MDtlsBootstrapCertificateVerifier.java index 5f215e51a0..cd5f62eb28 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/TbLwM2MDtlsBootstrapCertificateVerifier.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/TbLwM2MDtlsBootstrapCertificateVerifier.java @@ -41,7 +41,7 @@ import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo; import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import javax.security.auth.x500.X500Principal; import java.net.InetSocketAddress; import java.security.PublicKey; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java index a412d1c918..aa3942f508 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/secure/TbLwM2MDtlsCertificateVerifier.java @@ -47,7 +47,7 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2MAuthException; import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MDtlsSessionStore; import org.thingsboard.server.transport.lwm2m.server.store.TbMainSecurityStore; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import javax.security.auth.x500.X500Principal; import java.net.InetSocketAddress; import java.security.PublicKey; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index 3eb096cd38..5fb36f6f55 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -39,7 +39,7 @@ import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore; import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.security.cert.X509Certificate; import static java.util.concurrent.TimeUnit.MILLISECONDS; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java index 8c65c04939..2f0876157d 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/LwM2mTransportServerHelper.java @@ -33,8 +33,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java index de960ea436..09ecf500b6 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java @@ -75,8 +75,8 @@ import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogServic import org.thingsboard.server.transport.lwm2m.server.rpc.composite.RpcWriteCompositeRequest; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.Arrays; import java.util.Collection; import java.util.Date; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigServiceImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigServiceImpl.java index 302bd20c8b..39938d9e53 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigServiceImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/model/LwM2MModelConfigServiceImpl.java @@ -38,7 +38,7 @@ import org.thingsboard.server.transport.lwm2m.server.log.LwM2MTelemetryLogServic import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MModelConfigStore; import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; import java.util.List; import java.util.Map; import java.util.Set; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java index f59643cbeb..4e43d7b653 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/ota/DefaultLwM2MOtaUpdateService.java @@ -57,8 +57,8 @@ import org.thingsboard.server.transport.lwm2m.server.ota.software.SoftwareUpdate import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2MClientOtaInfoStore; import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index f8ff5c70a0..4369f5f532 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java @@ -100,8 +100,8 @@ import org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mSecurityStore; import org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil; import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java index 51dc2bc55b..13d9115941 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java @@ -27,7 +27,7 @@ import org.thingsboard.server.common.transport.TransportContext; import org.thingsboard.server.transport.mqtt.adaptors.JsonMqttAdaptor; import org.thingsboard.server.transport.mqtt.adaptors.ProtoMqttAdaptor; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.net.InetSocketAddress; import java.util.concurrent.atomic.AtomicInteger; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportService.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportService.java index e953f64b87..c658052467 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportService.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportService.java @@ -31,8 +31,8 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.TbTransportService; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.net.InetSocketAddress; /** diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java index 95603e751c..03ee4fcdc9 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/AbstractGatewaySessionHandler.java @@ -56,7 +56,7 @@ import org.thingsboard.server.transport.mqtt.adaptors.ProtoMqttAdaptor; import org.thingsboard.server.transport.mqtt.util.ReturnCode; import org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugConnectionState; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.Date; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java index 48998d58cd..626a658556 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/SparkplugNodeSessionHandler.java @@ -43,7 +43,7 @@ import org.thingsboard.server.transport.mqtt.MqttTransportHandler; import org.thingsboard.server.transport.mqtt.util.sparkplug.MetricDataType; import org.thingsboard.server.transport.mqtt.util.sparkplug.SparkplugTopic; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java index 6e68a0bd44..577f089f2e 100644 --- a/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java +++ b/common/transport/snmp/src/main/java/org/thingsboard/server/transport/snmp/service/SnmpTransportService.java @@ -51,8 +51,8 @@ import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.util.TbSnmpTransportComponent; import org.thingsboard.server.transport.snmp.session.DeviceSessionContext; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.io.IOException; import java.util.Arrays; import java.util.Collections; diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java index b0e7a527aa..e428b03e0c 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/TransportContext.java @@ -26,8 +26,8 @@ import org.thingsboard.server.common.transport.limits.TransportRateLimitService; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; import org.thingsboard.server.queue.scheduler.SchedulerComponent; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.concurrent.ExecutorService; /** diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentialsConfig.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentialsConfig.java index 7304d6a5c6..a3dd52c62d 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentialsConfig.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/config/ssl/SslCredentialsConfig.java @@ -18,7 +18,7 @@ package org.thingsboard.server.common.transport.config.ssl; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; @Slf4j @Data diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java index b495448d90..8c397bd2d4 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/DefaultTransportService.java @@ -99,8 +99,8 @@ import org.thingsboard.server.queue.util.AfterStartUp; import org.thingsboard.server.queue.util.DataDecodingEncodingService; import org.thingsboard.server.queue.util.TbTransportComponent; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; diff --git a/common/util/pom.xml b/common/util/pom.xml index 14ae1748b2..59669b11fd 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -46,8 +46,8 @@ provided - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api com.fasterxml.jackson.core diff --git a/common/util/src/main/java/org/thingsboard/common/util/AbstractListeningExecutor.java b/common/util/src/main/java/org/thingsboard/common/util/AbstractListeningExecutor.java index a0b88df49e..d9814336e4 100644 --- a/common/util/src/main/java/org/thingsboard/common/util/AbstractListeningExecutor.java +++ b/common/util/src/main/java/org/thingsboard/common/util/AbstractListeningExecutor.java @@ -19,8 +19,8 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.concurrent.Callable; /** diff --git a/common/version-control/pom.xml b/common/version-control/pom.xml index a8acdf2be9..370ecc24a9 100644 --- a/common/version-control/pom.xml +++ b/common/version-control/pom.xml @@ -62,8 +62,8 @@ provided - javax.annotation - javax.annotation-api + jakarta.annotation + jakarta.annotation-api com.google.guava diff --git a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultClusterVersionControlService.java b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultClusterVersionControlService.java index 618eb11d98..2c8a902a8a 100644 --- a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultClusterVersionControlService.java +++ b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultClusterVersionControlService.java @@ -76,8 +76,8 @@ import org.thingsboard.server.queue.provider.TbVersionControlQueueFactory; import org.thingsboard.server.queue.util.DataDecodingEncodingService; import org.thingsboard.server.queue.util.TbVersionControlComponent; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; diff --git a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java index 1905c50ba4..d6722fd5ed 100644 --- a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java +++ b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java @@ -36,7 +36,7 @@ import org.thingsboard.server.common.data.sync.vc.VersionCreationResult; import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo; import org.thingsboard.server.service.sync.vc.GitRepository.Diff; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/dao/pom.xml b/dao/pom.xml index 4d4dd2a30b..36526567de 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -122,7 +122,7 @@ org.glassfish - javax.el + jakarta.el org.springframework @@ -149,6 +149,12 @@ com.datastax.oss java-driver-query-builder + + io.netty + netty-transport-native-epoll + linux-x86_64 + test + io.dropwizard.metrics metrics-jmx diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetTypeFilter.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetTypeFilter.java index ce07d27f7d..2525387357 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetTypeFilter.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetTypeFilter.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.asset; import lombok.Data; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.List; /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java b/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java index b95ce39d9a..555975434a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java @@ -37,7 +37,7 @@ import org.thingsboard.server.common.stats.StatsFactory; import org.thingsboard.server.dao.cache.CacheExecutorService; import org.thingsboard.server.dao.service.Validator; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java b/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java index 6ba72a377a..ea0213240d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/sink/ElasticsearchAuditLogSink.java @@ -38,7 +38,7 @@ import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.id.TenantId; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Collections; diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 31b446fbd5..36ae061a1d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -61,7 +61,7 @@ import org.thingsboard.server.dao.service.PaginatedRemover; import org.thingsboard.server.dao.service.Validator; import org.thingsboard.server.dao.user.UserService; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java index 6433db5ae8..59caf26638 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java @@ -48,7 +48,7 @@ import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; import org.thingsboard.server.dao.sql.JpaExecutorService; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java index 916c459a6b..435b10779f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java @@ -23,9 +23,9 @@ import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UUIDBased; -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; import java.util.Arrays; import java.util.Collections; import java.util.List; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java index 773156adb1..7c19e40141 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmCommentEntity.java @@ -16,10 +16,11 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.MappedSuperclass; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.id.AlarmCommentId; @@ -28,10 +29,8 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.MappedSuperclass; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_ALARM_ID; @@ -40,7 +39,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_TYPE @Data @EqualsAndHashCode(callSuper = true) -@TypeDef(name = "json", typeClass = JsonStringType.class) @MappedSuperclass public abstract class AbstractAlarmCommentEntity extends BaseSqlEntity implements BaseEntity { @@ -53,7 +51,7 @@ public abstract class AbstractAlarmCommentEntity extends @Column(name = ALARM_COMMENT_TYPE) private AlarmCommentType type; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ALARM_COMMENT_COMMENT) private JsonNode comment; @@ -84,6 +82,7 @@ public abstract class AbstractAlarmCommentEntity extends this.type = alarmCommentEntity.getType(); this.comment = alarmCommentEntity.getComment(); } + protected AlarmComment toAlarmComment() { AlarmComment alarmComment = new AlarmComment(new AlarmCommentId(id)); alarmComment.setCreatedTime(createdTime); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java index 164e1518a1..f11faa6210 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAlarmEntity.java @@ -16,10 +16,13 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.MappedSuperclass; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.springframework.util.CollectionUtils; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.StringUtils; @@ -33,12 +36,8 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.MappedSuperclass; import java.util.Arrays; import java.util.Collections; import java.util.UUID; @@ -64,7 +63,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.ALARM_TYPE_PROPERT @Data @EqualsAndHashCode(callSuper = true) -@TypeDef(name = "json", typeClass = JsonStringType.class) @MappedSuperclass public abstract class AbstractAlarmEntity extends BaseSqlEntity implements BaseEntity { @@ -87,7 +85,6 @@ public abstract class AbstractAlarmEntity extends BaseSqlEntity @Column(name = ALARM_SEVERITY_PROPERTY) private AlarmSeverity severity; - @Type(type="pg-uuid") @Column(name = ALARM_ASSIGNEE_ID_PROPERTY) private UUID assigneeId; @@ -112,7 +109,7 @@ public abstract class AbstractAlarmEntity extends BaseSqlEntity @Column(name = ALARM_ASSIGN_TS_PROPERTY) private Long assignTs; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.ALARM_DETAILS_PROPERTY) private JsonNode details; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAssetEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAssetEntity.java index 3b7abed70d..aa11045759 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAssetEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractAssetEntity.java @@ -16,10 +16,11 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.MappedSuperclass; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.AssetProfileId; @@ -28,10 +29,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.MappedSuperclass; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.ASSET_CUSTOMER_ID_PROPERTY; @@ -44,7 +43,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPER @Data @EqualsAndHashCode(callSuper = true) -@TypeDef(name = "json", typeClass = JsonStringType.class) @MappedSuperclass public abstract class AbstractAssetEntity extends BaseSqlEntity implements SearchTextEntity { @@ -66,7 +64,7 @@ public abstract class AbstractAssetEntity extends BaseSqlEntity @Column(name = SEARCH_TEXT_PROPERTY) private String searchText; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.ASSET_ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java index 403cb04aef..237fae77b3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java @@ -17,11 +17,13 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.MappedSuperclass; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; -import org.hibernate.annotations.TypeDefs; +import org.hibernate.annotations.JdbcType; +import org.hibernate.dialect.PostgreSQLJsonPGObjectJsonbType; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.device.data.DeviceData; @@ -33,19 +35,12 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonBinaryType; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.MappedSuperclass; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) -@TypeDefs({ - @TypeDef(name = "json", typeClass = JsonStringType.class), - @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) -}) @MappedSuperclass public abstract class AbstractDeviceEntity extends BaseSqlEntity implements SearchTextEntity { @@ -67,7 +62,7 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) private String searchText; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.DEVICE_ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; @@ -80,7 +75,8 @@ public abstract class AbstractDeviceEntity extends BaseSqlEnti @Column(name = ModelConstants.DEVICE_SOFTWARE_ID_PROPERTY, columnDefinition = "uuid") private UUID softwareId; - @Type(type = "jsonb") + @Convert(converter = JsonConverter.class) + @JdbcType(PostgreSQLJsonPGObjectJsonbType.class) @Column(name = ModelConstants.DEVICE_DEVICE_DATA_PROPERTY, columnDefinition = "jsonb") private JsonNode deviceData; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEdgeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEdgeEntity.java index f5a7423df9..0e5da92ecc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEdgeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEdgeEntity.java @@ -16,10 +16,11 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.MappedSuperclass; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EdgeId; @@ -28,10 +29,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.MappedSuperclass; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY; @@ -46,7 +45,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPER @Data @EqualsAndHashCode(callSuper = true) -@TypeDef(name = "json", typeClass = JsonStringType.class) @MappedSuperclass public abstract class AbstractEdgeEntity extends BaseSqlEntity implements SearchTextEntity { @@ -77,7 +75,7 @@ public abstract class AbstractEdgeEntity extends BaseSqlEntity extends BaseSqlEntity implements SearchTextEntity { @@ -85,7 +82,7 @@ public abstract class AbstractEntityViewEntity extends Bas @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) private String searchText; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.ENTITY_VIEW_ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractTenantEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractTenantEntity.java index 39dca43d29..d122de2b15 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractTenantEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractTenantEntity.java @@ -16,25 +16,23 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.MappedSuperclass; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.MappedSuperclass; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) -@TypeDef(name = "json", typeClass = JsonStringType.class) @MappedSuperclass public abstract class AbstractTenantEntity extends BaseSqlEntity implements SearchTextEntity { @@ -71,7 +69,7 @@ public abstract class AbstractTenantEntity extends BaseSqlEnti @Column(name = ModelConstants.EMAIL_PROPERTY) private String email; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractTsKvEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractTsKvEntity.java index 6d3378c0c7..0b9a3aaebe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractTsKvEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractTsKvEntity.java @@ -15,6 +15,10 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.Transient; import lombok.Data; import org.thingsboard.server.common.data.kv.AggTsKvEntry; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; @@ -27,10 +31,6 @@ import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.dao.model.ToData; -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; -import javax.persistence.Transient; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.BOOLEAN_VALUE_COLUMN; @@ -59,7 +59,6 @@ public abstract class AbstractTsKvEntity implements ToData { @Column(name = KEY_COLUMN) protected int key; - @Id @Column(name = TS_COLUMN) protected Long ts; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractWidgetTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractWidgetTypeEntity.java index 127e8509b7..626f158829 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractWidgetTypeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractWidgetTypeEntity.java @@ -24,8 +24,8 @@ import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import javax.persistence.Column; -import javax.persistence.MappedSuperclass; +import jakarta.persistence.Column; +import jakarta.persistence.MappedSuperclass; import java.util.UUID; @Data diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java index 7f61fb0fe6..52a505a035 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java @@ -16,31 +16,29 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.id.AdminSettingsId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; import java.util.UUID; -import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_TABLE_NAME; import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_JSON_VALUE_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_KEY_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.ADMIN_SETTINGS_TABLE_NAME; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ADMIN_SETTINGS_TABLE_NAME) public final class AdminSettingsEntity extends BaseSqlEntity implements BaseEntity { @@ -50,7 +48,7 @@ public final class AdminSettingsEntity extends BaseSqlEntity impl @Column(name = ADMIN_SETTINGS_KEY_PROPERTY) private String key; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ADMIN_SETTINGS_JSON_VALUE_PROPERTY) private JsonNode jsonValue; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java index 7baa81755f..444229672d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmCommentEntity.java @@ -15,25 +15,20 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.AlarmCommentInfo; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Entity; -import javax.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COMMENT_TABLE_NAME; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ALARM_COMMENT_TABLE_NAME) - -public class AlarmCommentEntity extends AbstractAlarmCommentEntity { +public class AlarmCommentEntity extends AbstractAlarmCommentEntity { public AlarmCommentEntity() { super(); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmEntity.java index 19d1040656..beb2849a92 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmEntity.java @@ -15,22 +15,18 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmInfo; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Entity; -import javax.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.ALARM_TABLE_NAME; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ALARM_TABLE_NAME) public final class AlarmEntity extends AbstractAlarmEntity { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmInfoEntity.java index db55756060..e87e4d8257 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AlarmInfoEntity.java @@ -21,9 +21,9 @@ import org.thingsboard.server.common.data.alarm.AlarmAssignee; import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.id.UserId; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ASSIGNEE_EMAIL_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ASSIGNEE_FIRST_NAME_PROPERTY; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java index b18f414c63..298ddcac81 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ApiUsageStateEntity.java @@ -15,9 +15,13 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.ApiUsageState; import org.thingsboard.server.common.data.ApiUsageStateValue; import org.thingsboard.server.common.data.id.ApiUsageStateId; @@ -26,13 +30,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; /** @@ -41,7 +39,6 @@ import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.API_USAGE_STATE_TABLE_NAME) public class ApiUsageStateEntity extends BaseSqlEntity implements BaseEntity { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetEntity.java index c30a572068..bb551ffbda 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetEntity.java @@ -15,21 +15,17 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.asset.Asset; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Entity; -import javax.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.ASSET_TABLE_NAME; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ASSET_TABLE_NAME) public final class AssetEntity extends AbstractAssetEntity { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetProfileEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetProfileEntity.java index 1deb1e5c7b..a276047796 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetProfileEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AssetProfileEntity.java @@ -26,9 +26,9 @@ import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import java.util.UUID; @Data diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java index 745e5893f2..936a18eeeb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java @@ -15,15 +15,15 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.thingsboard.server.common.data.EntityType; -import javax.persistence.Column; -import javax.persistence.Embeddable; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; import java.io.Serializable; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvEntity.java index b39384eb5a..bc97c0394f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvEntity.java @@ -26,10 +26,10 @@ import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.dao.model.ToData; -import javax.persistence.Column; -import javax.persistence.EmbeddedId; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import java.io.Serializable; import static org.thingsboard.server.dao.model.ModelConstants.BOOLEAN_VALUE_COLUMN; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java index 86df16872c..21ef4e09a0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AuditLogEntity.java @@ -16,10 +16,14 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.audit.ActionStatus; import org.thingsboard.server.common.data.audit.ActionType; @@ -32,13 +36,8 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_ACTION_DATA_PROPERTY; @@ -56,7 +55,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.AUDIT_LOG_USER_NAM @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.AUDIT_LOG_TABLE_NAME) public class AuditLogEntity extends BaseSqlEntity implements BaseEntity { @@ -86,7 +84,7 @@ public class AuditLogEntity extends BaseSqlEntity implements BaseEntit @Column(name = AUDIT_LOG_ACTION_TYPE_PROPERTY) private ActionType actionType; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = AUDIT_LOG_ACTION_DATA_PROPERTY) private JsonNode actionData; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java index 09cabb72f1..ca12c0a112 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java @@ -16,10 +16,14 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.ComponentDescriptorId; import org.thingsboard.server.common.data.plugin.ComponentClusteringMode; import org.thingsboard.server.common.data.plugin.ComponentDescriptor; @@ -28,18 +32,11 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; +import org.thingsboard.server.dao.util.mapping.JsonConverter; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.COMPONENT_DESCRIPTOR_TABLE_NAME) public class ComponentDescriptorEntity extends BaseSqlEntity implements SearchTextEntity { @@ -61,7 +58,7 @@ public class ComponentDescriptorEntity extends BaseSqlEntity implements SearchTextEntity { @Column(name = ModelConstants.CUSTOMER_TENANT_ID_PROPERTY) private UUID tenantId; - + @Column(name = ModelConstants.CUSTOMER_TITLE_PROPERTY) private String title; - + @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) private String searchText; - + @Column(name = ModelConstants.COUNTRY_PROPERTY) private String country; - + @Column(name = ModelConstants.STATE_PROPERTY) private String state; @@ -73,7 +71,7 @@ public final class CustomerEntity extends BaseSqlEntity implements Sea @Column(name = ModelConstants.EMAIL_PROPERTY) private String email; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.CUSTOMER_ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java index 1e99a59773..c794e1b963 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java @@ -15,14 +15,15 @@ */ package org.thingsboard.server.dao.model.sql; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.ShortCustomerInfo; @@ -32,12 +33,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; -import java.io.IOException; import java.util.HashSet; import java.util.UUID; @@ -45,7 +42,6 @@ import java.util.UUID; @Slf4j @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.DASHBOARD_TABLE_NAME) public final class DashboardEntity extends BaseSqlEntity implements SearchTextEntity { @@ -73,7 +69,7 @@ public final class DashboardEntity extends BaseSqlEntity implements S @Column(name = ModelConstants.DASHBOARD_MOBILE_ORDER_PROPERTY) private Integer mobileOrder; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.DASHBOARD_CONFIGURATION_PROPERTY) private JsonNode configuration; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java index d3c8bbeb34..5dfaaa8de1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardInfoEntity.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.dao.model.sql; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import lombok.Data; import lombok.EqualsAndHashCode; @@ -30,10 +29,10 @@ import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; -import java.io.IOException; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; + import java.util.HashSet; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java index 9af4ec64e7..4ab2452168 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java @@ -25,11 +25,11 @@ import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import java.util.UUID; @Data diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java index d476596dc1..5d2f34ee16 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java @@ -15,25 +15,16 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.TypeDef; -import org.hibernate.annotations.TypeDefs; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonBinaryType; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Entity; -import javax.persistence.Table; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDefs({ - @TypeDef(name = "json", typeClass = JsonStringType.class), - @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) -}) @Table(name = ModelConstants.DEVICE_TABLE_NAME) public final class DeviceEntity extends AbstractDeviceEntity { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceInfoEntity.java index d8be0eb4b8..f448a79c2b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceInfoEntity.java @@ -21,9 +21,9 @@ import org.hibernate.annotations.Immutable; import org.thingsboard.server.common.data.DeviceInfo; import org.thingsboard.server.dao.model.ModelConstants; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; @Data @EqualsAndHashCode(callSuper = true) diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java index 1b084c4817..cedfe5c748 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java @@ -17,10 +17,16 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.JdbcType; +import org.hibernate.dialect.PostgreSQLJsonPGObjectJsonbType; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileProvisionType; @@ -35,19 +41,13 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonBinaryType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.DEVICE_PROFILE_TABLE_NAME) public final class DeviceProfileEntity extends BaseSqlEntity implements SearchTextEntity { @@ -90,7 +90,8 @@ public final class DeviceProfileEntity extends BaseSqlEntity impl @Column(name = ModelConstants.DEVICE_PROFILE_DEFAULT_QUEUE_NAME_PROPERTY) private String defaultQueueName; - @Type(type = "jsonb") + @Convert(converter = JsonConverter.class) + @JdbcType(PostgreSQLJsonPGObjectJsonbType.class) @Column(name = ModelConstants.DEVICE_PROFILE_PROFILE_DATA_PROPERTY, columnDefinition = "jsonb") private JsonNode profileData; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java index 3c857b3246..a6467da03d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEntity.java @@ -15,21 +15,17 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.edge.Edge; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Entity; -import javax.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TABLE_NAME; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = EDGE_TABLE_NAME) public class EdgeEntity extends AbstractEdgeEntity { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java index 1edc47f197..6ba856df1d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EdgeEventEntity.java @@ -16,11 +16,15 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.edge.EdgeEventType; @@ -29,20 +33,15 @@ import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ACTION_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_BODY_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TABLE_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_EDGE_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_ENTITY_ID_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TABLE_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TENANT_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_TYPE_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.EDGE_EVENT_UID_PROPERTY; @@ -52,7 +51,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.TS_COLUMN; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = EDGE_EVENT_TABLE_NAME) @NoArgsConstructor public class EdgeEventEntity extends BaseSqlEntity implements BaseEntity { @@ -74,7 +72,7 @@ public class EdgeEventEntity extends BaseSqlEntity implements BaseEnt @Column(name = EDGE_EVENT_ACTION_PROPERTY) private EdgeEventActionType edgeEventAction; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = EDGE_EVENT_BODY_PROPERTY) private JsonNode entityBody; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityAlarmCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityAlarmCompositeKey.java index ad0c3af521..83e9584385 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityAlarmCompositeKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityAlarmCompositeKey.java @@ -20,7 +20,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.thingsboard.server.common.data.alarm.EntityAlarm; -import javax.persistence.Transient; +import jakarta.persistence.Transient; import java.io.Serializable; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityAlarmEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityAlarmEntity.java index 6304a5324d..a203195f65 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityAlarmEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityAlarmEntity.java @@ -23,11 +23,11 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.ToData; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import jakarta.persistence.Table; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.CREATED_TIME_PROPERTY; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityViewEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityViewEntity.java index 4bec68240d..dbd442c3d9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityViewEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EntityViewEntity.java @@ -15,20 +15,16 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Entity; -import javax.persistence.Table; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.ENTITY_VIEW_TABLE_NAME) public class EntityViewEntity extends AbstractEntityViewEntity { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ErrorEventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ErrorEventEntity.java index 2eb356ac8b..a9d460df01 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ErrorEventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ErrorEventEntity.java @@ -22,9 +22,9 @@ import org.thingsboard.server.common.data.event.ErrorEvent; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.ERROR_EVENT_TABLE_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ERROR_COLUMN_NAME; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java index f0ac6af704..db1ec2b208 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java @@ -21,9 +21,9 @@ import org.thingsboard.server.common.data.event.Event; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.ModelConstants; -import javax.persistence.Column; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; +import jakarta.persistence.Column; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; import java.util.HashMap; import java.util.Map; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/LifecycleEventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/LifecycleEventEntity.java index e20555147f..b247542228 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/LifecycleEventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/LifecycleEventEntity.java @@ -22,9 +22,9 @@ import org.thingsboard.server.common.data.event.LifecycleEvent; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ERROR_COLUMN_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EVENT_SUCCESS_COLUMN_NAME; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationEntity.java index 560bea2b91..eb154221d8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationEntity.java @@ -16,11 +16,15 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.Formula; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.UserId; @@ -30,19 +34,13 @@ import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.NOTIFICATION_TABLE_NAME) public class NotificationEntity extends BaseSqlEntity { @@ -62,11 +60,11 @@ public class NotificationEntity extends BaseSqlEntity { @Column(name = ModelConstants.NOTIFICATION_TEXT_PROPERTY, nullable = false) private String text; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.NOTIFICATION_ADDITIONAL_CONFIG_PROPERTY) private JsonNode additionalConfig; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Formula("(SELECT r.info FROM notification_request r WHERE r.id = request_id)") private JsonNode info; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java index 713aac62e2..12814e92a2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java @@ -16,10 +16,14 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.NotificationRequestId; @@ -33,19 +37,13 @@ import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.NOTIFICATION_REQUEST_TABLE_NAME) public class NotificationRequestEntity extends BaseSqlEntity { @@ -58,15 +56,15 @@ public class NotificationRequestEntity extends BaseSqlEntity { @@ -60,15 +59,15 @@ public class NotificationRuleEntity extends BaseSqlEntity { @Column(name = ModelConstants.NOTIFICATION_RULE_TRIGGER_TYPE_PROPERTY, nullable = false) private NotificationRuleTriggerType triggerType; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.NOTIFICATION_RULE_TRIGGER_CONFIG_PROPERTY, nullable = false) private JsonNode triggerConfig; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.NOTIFICATION_RULE_RECIPIENTS_CONFIG_PROPERTY, nullable = false) private JsonNode recipientsConfig; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.NOTIFICATION_RULE_ADDITIONAL_CONFIG_PROPERTY) private JsonNode additionalConfig; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTargetEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTargetEntity.java index a4748ae0c2..4da12fa404 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTargetEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTargetEntity.java @@ -16,26 +16,24 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.NotificationTargetId; import org.thingsboard.server.common.data.notification.targets.NotificationTarget; import org.thingsboard.server.common.data.notification.targets.NotificationTargetConfig; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.NOTIFICATION_TARGET_TABLE_NAME) public class NotificationTargetEntity extends BaseSqlEntity { @@ -45,7 +43,7 @@ public class NotificationTargetEntity extends BaseSqlEntity @Column(name = ModelConstants.NAME_PROPERTY, nullable = false) private String name; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.NOTIFICATION_TARGET_CONFIGURATION_PROPERTY, nullable = false) private JsonNode configuration; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTemplateEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTemplateEntity.java index 09b0ee7ee9..ef758918e4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTemplateEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationTemplateEntity.java @@ -16,29 +16,27 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.NotificationTemplateId; import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.NOTIFICATION_TEMPLATE_TABLE_NAME) public class NotificationTemplateEntity extends BaseSqlEntity { @@ -52,7 +50,7 @@ public class NotificationTemplateEntity extends BaseSqlEntity { @@ -89,7 +87,7 @@ public class OAuth2ClientRegistrationTemplateEntity extends BaseSqlEntity { @@ -110,7 +108,7 @@ public class OAuth2RegistrationEntity extends BaseSqlEntity @Column(name = ModelConstants.OAUTH2_MAPPER_SEND_TOKEN_PROPERTY) private Boolean sendToken; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.OAUTH2_ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageEntity.java index dcb3bce546..10af250d29 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageEntity.java @@ -16,10 +16,15 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Lob; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.OtaPackage; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.OtaPackageId; @@ -29,14 +34,8 @@ import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Lob; -import javax.persistence.Table; +import org.thingsboard.server.dao.util.mapping.JsonConverter; + import java.nio.ByteBuffer; import java.util.UUID; @@ -59,7 +58,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPER @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = OTA_PACKAGE_TABLE_NAME) public class OtaPackageEntity extends BaseSqlEntity implements SearchTextEntity { @@ -105,7 +103,7 @@ public class OtaPackageEntity extends BaseSqlEntity implements Searc @Column(name = OTA_PACKAGE_DATA_SIZE_COLUMN) private Long dataSize; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.OTA_PACKAGE_ADDITIONAL_INFO_COLUMN) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageInfoEntity.java index 5a2eb6008b..8e14cc198e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OtaPackageInfoEntity.java @@ -16,10 +16,15 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.OtaPackageInfo; import org.thingsboard.server.common.data.id.DeviceProfileId; @@ -30,14 +35,8 @@ import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; -import javax.persistence.Transient; +import org.thingsboard.server.dao.util.mapping.JsonConverter; + import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.OTA_PACKAGE_CHECKSUM_ALGORITHM_COLUMN; @@ -58,7 +57,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPER @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = OTA_PACKAGE_TABLE_NAME) public class OtaPackageInfoEntity extends BaseSqlEntity implements SearchTextEntity { @@ -100,7 +98,7 @@ public class OtaPackageInfoEntity extends BaseSqlEntity implemen @Column(name = OTA_PACKAGE_DATA_SIZE_COLUMN) private Long dataSize; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.OTA_PACKAGE_ADDITIONAL_INFO_COLUMN) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/QueueEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/QueueEntity.java index 75f3332fbe..b81ddb04e1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/QueueEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/QueueEntity.java @@ -16,10 +16,12 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.id.QueueId; import org.thingsboard.server.common.data.id.TenantId; @@ -29,17 +31,13 @@ import org.thingsboard.server.common.data.queue.SubmitStrategy; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.QUEUE_TABLE_NAME) public class QueueEntity extends BaseSqlEntity { @@ -63,15 +61,15 @@ public class QueueEntity extends BaseSqlEntity { @Column(name = ModelConstants.QUEUE_PACK_PROCESSING_TIMEOUT_PROPERTY) private long packProcessingTimeout; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.QUEUE_SUBMIT_STRATEGY_PROPERTY) private JsonNode submitStrategy; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.QUEUE_PROCESSING_STRATEGY_PROPERTY) private JsonNode processingStrategy; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.QUEUE_ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RelationCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RelationCompositeKey.java index aeae9e5b86..76e953fdbf 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RelationCompositeKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RelationCompositeKey.java @@ -20,7 +20,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.thingsboard.server.common.data.relation.EntityRelation; -import javax.persistence.Transient; +import jakarta.persistence.Transient; import java.io.Serializable; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RelationEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RelationEntity.java index 1e502adde1..a87123a8c0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RelationEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RelationEntity.java @@ -16,26 +16,25 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import jakarta.persistence.Table; import lombok.Data; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.model.ToData; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.Table; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.ADDITIONAL_INFO_PROPERTY; -import static org.thingsboard.server.dao.model.ModelConstants.RELATION_TABLE_NAME; import static org.thingsboard.server.dao.model.ModelConstants.RELATION_FROM_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.RELATION_FROM_TYPE_PROPERTY; +import static org.thingsboard.server.dao.model.ModelConstants.RELATION_TABLE_NAME; import static org.thingsboard.server.dao.model.ModelConstants.RELATION_TO_ID_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.RELATION_TO_TYPE_PROPERTY; import static org.thingsboard.server.dao.model.ModelConstants.RELATION_TYPE_GROUP_PROPERTY; @@ -43,7 +42,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.RELATION_TYPE_PROP @Data @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = RELATION_TABLE_NAME) @IdClass(RelationCompositeKey.class) public final class RelationEntity implements ToData { @@ -72,7 +70,7 @@ public final class RelationEntity implements ToData { @Column(name = RELATION_TYPE_PROPERTY) private String relationType; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RpcEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RpcEntity.java index 8906619d5b..abf32bd444 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RpcEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RpcEntity.java @@ -16,10 +16,14 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.RpcId; import org.thingsboard.server.common.data.id.TenantId; @@ -27,13 +31,8 @@ import org.thingsboard.server.common.data.rpc.Rpc; import org.thingsboard.server.common.data.rpc.RpcStatus; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.RPC_ADDITIONAL_INFO; @@ -48,7 +47,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.RPC_TENANT_ID_COLU @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = RPC_TABLE_NAME) public class RpcEntity extends BaseSqlEntity implements BaseEntity { @@ -61,11 +59,11 @@ public class RpcEntity extends BaseSqlEntity implements BaseEntity { @Column(name = RPC_EXPIRATION_TIME) private long expirationTime; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = RPC_REQUEST) private JsonNode request; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = RPC_RESPONSE) private JsonNode response; @@ -73,7 +71,7 @@ public class RpcEntity extends BaseSqlEntity implements BaseEntity { @Column(name = RPC_STATUS) private RpcStatus status; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = RPC_ADDITIONAL_INFO) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainDebugEventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainDebugEventEntity.java index 7e0921d381..08a2fa6b72 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainDebugEventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainDebugEventEntity.java @@ -22,9 +22,9 @@ import org.thingsboard.server.common.data.event.RuleChainDebugEvent; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ERROR_COLUMN_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EVENT_MESSAGE_COLUMN_NAME; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java index 82362e0259..f55e331d4f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleChainEntity.java @@ -16,10 +16,14 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.TenantId; @@ -29,19 +33,13 @@ import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.RULE_CHAIN_TABLE_NAME) public class RuleChainEntity extends BaseSqlEntity implements SearchTextEntity { @@ -67,11 +65,11 @@ public class RuleChainEntity extends BaseSqlEntity implements SearchT @Column(name = ModelConstants.DEBUG_MODE) private boolean debugMode; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.RULE_CHAIN_CONFIGURATION_PROPERTY) private JsonNode configuration; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeDebugEventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeDebugEventEntity.java index ee4d6c3bd1..ce28037a89 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeDebugEventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeDebugEventEntity.java @@ -23,9 +23,9 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.EVENT_DATA_COLUMN_NAME; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java index c03920d954..26bfdd3c3d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeEntity.java @@ -16,10 +16,12 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.rule.RuleNode; @@ -27,17 +29,13 @@ import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.RULE_NODE_TABLE_NAME) public class RuleNodeEntity extends BaseSqlEntity implements SearchTextEntity { @@ -53,11 +51,11 @@ public class RuleNodeEntity extends BaseSqlEntity implements SearchTex @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) private String searchText; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.RULE_NODE_CONFIGURATION_PROPERTY) private JsonNode configuration; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeStateEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeStateEntity.java index 9a9efe432a..a71e57ce8b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeStateEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleNodeStateEntity.java @@ -15,9 +15,11 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.RuleNodeStateId; @@ -25,17 +27,12 @@ import org.thingsboard.server.common.data.rule.RuleNodeState; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.RULE_NODE_STATE_TABLE_NAME) public class RuleNodeStateEntity extends BaseSqlEntity { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/StatisticsEventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/StatisticsEventEntity.java index 0ac017d48d..43395f2f87 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/StatisticsEventEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/StatisticsEventEntity.java @@ -22,9 +22,9 @@ import org.thingsboard.server.common.data.event.StatisticsEvent; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.EVENT_ERRORS_OCCURRED_COLUMN_NAME; import static org.thingsboard.server.dao.model.ModelConstants.EVENT_MESSAGES_PROCESSED_COLUMN_NAME; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceEntity.java index 1b30123b2e..741e21532e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceEntity.java @@ -24,9 +24,9 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.SearchTextEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_DATA_COLUMN; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceInfoEntity.java index 5ebc0297af..9314c42bcc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TbResourceInfoEntity.java @@ -24,9 +24,9 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.SearchTextEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.RESOURCE_KEY_COLUMN; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java index 46d3f34c9e..592326c20f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java @@ -15,20 +15,16 @@ */ package org.thingsboard.server.dao.model.sql; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Entity; -import javax.persistence.Table; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.TENANT_TABLE_NAME) public final class TenantEntity extends AbstractTenantEntity { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantProfileEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantProfileEntity.java index 9672ed2bab..302a51b4c4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantProfileEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantProfileEntity.java @@ -17,10 +17,14 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; +import org.hibernate.annotations.JdbcType; +import org.hibernate.dialect.PostgreSQLJsonPGObjectJsonbType; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.TenantProfileId; @@ -28,16 +32,11 @@ import org.thingsboard.server.common.data.tenant.profile.TenantProfileData; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonBinaryType; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import org.thingsboard.server.dao.util.mapping.JsonConverter; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.TENANT_PROFILE_TABLE_NAME) public final class TenantProfileEntity extends BaseSqlEntity implements SearchTextEntity { @@ -56,8 +55,9 @@ public final class TenantProfileEntity extends BaseSqlEntity impl @Column(name = ModelConstants.TENANT_PROFILE_ISOLATED_TB_RULE_ENGINE) private boolean isolatedTbRuleEngine; - @Type(type = "jsonb") - @Column(name = ModelConstants.TENANT_PROFILE_PROFILE_DATA_PROPERTY, columnDefinition = "jsonb") + @Convert(converter = JsonConverter.class) + @JdbcType(PostgreSQLJsonPGObjectJsonbType.class) + @Column(name = ModelConstants.TENANT_PROFILE_PROFILE_DATA_PROPERTY) private JsonNode profileData; public TenantProfileEntity() { diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserAuthSettingsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserAuthSettingsEntity.java index 9d63b4d586..1ea283a18b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserAuthSettingsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserAuthSettingsEntity.java @@ -16,11 +16,13 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.id.UserAuthSettingsId; import org.thingsboard.server.common.data.id.UserId; @@ -29,24 +31,20 @@ import org.thingsboard.server.common.data.security.model.mfa.account.AccountTwoF import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; import java.util.UUID; @EqualsAndHashCode(callSuper = true) @Data @NoArgsConstructor -@TypeDef(name = "json", typeClass = JsonStringType.class) @Entity @Table(name = ModelConstants.USER_AUTH_SETTINGS_TABLE_NAME) public class UserAuthSettingsEntity extends BaseSqlEntity implements BaseEntity { @Column(name = ModelConstants.USER_AUTH_SETTINGS_USER_ID_PROPERTY, nullable = false, unique = true) private UUID userId; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.USER_AUTH_SETTINGS_TWO_FA_SETTINGS) private JsonNode twoFaSettings; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java index 7c93fd0be2..f02080bf58 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java @@ -16,9 +16,9 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Convert; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; import org.thingsboard.server.common.data.id.UserCredentialsId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.security.UserCredentials; @@ -26,9 +26,11 @@ import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import org.thingsboard.server.dao.util.mapping.JsonConverter; + import java.util.UUID; @Data @@ -52,7 +54,7 @@ public final class UserCredentialsEntity extends BaseSqlEntity @Column(name = ModelConstants.USER_CREDENTIALS_RESET_TOKEN_PROPERTY, unique = true) private String resetToken; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.USER_CREDENTIALS_ADDITIONAL_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java index 33b19d765e..145b8508d3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java @@ -16,10 +16,14 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -28,13 +32,8 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.Table; import java.util.UUID; /** @@ -43,7 +42,6 @@ import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.USER_PG_HIBERNATE_TABLE_NAME) public class UserEntity extends BaseSqlEntity implements SearchTextEntity { @@ -72,7 +70,7 @@ public class UserEntity extends BaseSqlEntity implements SearchTextEntity< @Column(name = ModelConstants.PHONE_PROPERTY) private String phone; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.USER_ADDITIONAL_INFO_PROPERTY) private JsonNode additionalInfo; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserSettingsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserSettingsEntity.java index a494b8096c..9e383f0359 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserSettingsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserSettingsEntity.java @@ -16,28 +16,26 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import jakarta.persistence.Table; import lombok.Data; import lombok.NoArgsConstructor; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.settings.UserSettings; import org.thingsboard.server.common.data.settings.UserSettingsCompositeKey; import org.thingsboard.server.common.data.settings.UserSettingsType; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.ToData; -import org.thingsboard.server.dao.util.mapping.JsonStringType; +import org.thingsboard.server.dao.util.mapping.JsonConverter; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.Table; import java.util.UUID; @Data @NoArgsConstructor -@TypeDef(name = "json", typeClass = JsonStringType.class) @Entity @Table(name = ModelConstants.USER_SETTINGS_TABLE_NAME) @IdClass(UserSettingsCompositeKey.class) @@ -49,7 +47,7 @@ public class UserSettingsEntity implements ToData { @Id @Column(name = ModelConstants.USER_SETTINGS_TYPE_PROPERTY) private String type; - @Type(type = "json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.USER_SETTINGS_SETTINGS) private JsonNode settings; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java index c936952b40..a304318fee 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeDetailsEntity.java @@ -16,23 +16,20 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; -import org.hibernate.annotations.Type; -import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.widget.BaseWidgetType; import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.util.mapping.JsonStringType; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import org.thingsboard.server.dao.util.mapping.JsonConverter; @Data @EqualsAndHashCode(callSuper = true) @Entity -@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.WIDGET_TYPE_TABLE_NAME) public class WidgetTypeDetailsEntity extends AbstractWidgetTypeEntity { @@ -42,7 +39,7 @@ public class WidgetTypeDetailsEntity extends AbstractWidgetTypeEntity { - @Type(type="json") + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY) private JsonNode descriptor; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java index 0bc2f0ba36..272863134a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java @@ -25,9 +25,9 @@ import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import java.util.UUID; @Data diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/dictionary/TsKvDictionary.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/dictionary/TsKvDictionary.java index 36f34d4239..5f1ff6a9c1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/dictionary/TsKvDictionary.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/dictionary/TsKvDictionary.java @@ -15,15 +15,13 @@ */ package org.thingsboard.server.dao.model.sqlts.dictionary; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; +import jakarta.persistence.Table; import lombok.Data; import org.hibernate.annotations.Generated; -import org.hibernate.annotations.GenerationTime; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.IdClass; -import javax.persistence.Table; import static org.thingsboard.server.dao.model.ModelConstants.KEY_COLUMN; import static org.thingsboard.server.dao.model.ModelConstants.KEY_ID_COLUMN; @@ -38,8 +36,8 @@ public final class TsKvDictionary { @Column(name = KEY_COLUMN) private String key; - @Column(name = KEY_ID_COLUMN, unique = true, columnDefinition="int") - @Generated(GenerationTime.INSERT) + @Column(name = KEY_ID_COLUMN, unique = true, columnDefinition = "int") + @Generated private int keyId; } \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/dictionary/TsKvDictionaryCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/dictionary/TsKvDictionaryCompositeKey.java index 5a83260bac..49ab8b6822 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/dictionary/TsKvDictionaryCompositeKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/dictionary/TsKvDictionaryCompositeKey.java @@ -19,7 +19,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import javax.persistence.Transient; +import jakarta.persistence.Transient; import java.io.Serializable; @Data diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestCompositeKey.java index ae1c34310c..c46d6f3d5d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestCompositeKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestCompositeKey.java @@ -19,7 +19,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import javax.persistence.Transient; +import jakarta.persistence.Transient; import java.io.Serializable; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java index 58a76ddf31..7c57babdb1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/latest/TsKvLatestEntity.java @@ -15,19 +15,19 @@ */ package org.thingsboard.server.dao.model.sqlts.latest; +import jakarta.persistence.ColumnResult; +import jakarta.persistence.ConstructorResult; +import jakarta.persistence.Entity; +import jakarta.persistence.IdClass; +import jakarta.persistence.NamedNativeQueries; +import jakarta.persistence.NamedNativeQuery; +import jakarta.persistence.SqlResultSetMapping; +import jakarta.persistence.SqlResultSetMappings; +import jakarta.persistence.Table; import lombok.Data; import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity; import org.thingsboard.server.dao.sqlts.latest.SearchTsKvLatestRepository; -import javax.persistence.ColumnResult; -import javax.persistence.ConstructorResult; -import javax.persistence.Entity; -import javax.persistence.IdClass; -import javax.persistence.NamedNativeQueries; -import javax.persistence.NamedNativeQuery; -import javax.persistence.SqlResultSetMapping; -import javax.persistence.SqlResultSetMappings; -import javax.persistence.Table; import java.util.UUID; @Data diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvCompositeKey.java index a7f2ed4210..23006f63e7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvCompositeKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvCompositeKey.java @@ -15,11 +15,11 @@ */ package org.thingsboard.server.dao.model.sqlts.timescale.ts; +import jakarta.persistence.Transient; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import javax.persistence.Transient; import java.io.Serializable; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java index f50af42073..2d09caf150 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/timescale/ts/TimescaleTsKvEntity.java @@ -15,21 +15,20 @@ */ package org.thingsboard.server.dao.model.sqlts.timescale.ts; +import jakarta.persistence.ColumnResult; +import jakarta.persistence.ConstructorResult; +import jakarta.persistence.Entity; +import jakarta.persistence.IdClass; +import jakarta.persistence.NamedNativeQueries; +import jakarta.persistence.NamedNativeQuery; +import jakarta.persistence.SqlResultSetMapping; +import jakarta.persistence.SqlResultSetMappings; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity; -import javax.persistence.ColumnResult; -import javax.persistence.ConstructorResult; -import javax.persistence.Entity; -import javax.persistence.IdClass; -import javax.persistence.NamedNativeQueries; -import javax.persistence.NamedNativeQuery; -import javax.persistence.SqlResultSetMapping; -import javax.persistence.SqlResultSetMappings; -import javax.persistence.Table; - import static org.thingsboard.server.dao.sqlts.timescale.AggregationRepository.FIND_AVG; import static org.thingsboard.server.dao.sqlts.timescale.AggregationRepository.FIND_AVG_QUERY; import static org.thingsboard.server.dao.sqlts.timescale.AggregationRepository.FIND_COUNT; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvCompositeKey.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvCompositeKey.java index 14fe2b6eb7..7da73e5012 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvCompositeKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvCompositeKey.java @@ -19,7 +19,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import javax.persistence.Transient; +import jakarta.persistence.Transient; import java.io.Serializable; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvEntity.java index 9f5b8d87ef..d0577b6288 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sqlts/ts/TsKvEntity.java @@ -15,14 +15,13 @@ */ package org.thingsboard.server.dao.model.sqlts.ts; +import jakarta.persistence.Entity; +import jakarta.persistence.IdClass; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity; -import javax.persistence.Entity; -import javax.persistence.IdClass; -import javax.persistence.Table; - @EqualsAndHashCode(callSuper = true) @Data @Entity diff --git a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractAsyncDao.java b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractAsyncDao.java index 425724bf2c..87bb2f0e5c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractAsyncDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraAbstractAsyncDao.java @@ -21,9 +21,9 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.common.util.ThingsBoardThreadFactory; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; diff --git a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateReadExecutor.java b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateReadExecutor.java index adeee5f174..3ed763b43b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateReadExecutor.java +++ b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateReadExecutor.java @@ -29,7 +29,7 @@ import org.thingsboard.server.dao.util.AbstractBufferedRateExecutor; import org.thingsboard.server.dao.util.AsyncTaskContext; import org.thingsboard.server.dao.util.NoSqlAnyDao; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; /** * Created by ashvayka on 24.10.18. diff --git a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateWriteExecutor.java b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateWriteExecutor.java index 55b1b5410d..e09dab1034 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateWriteExecutor.java +++ b/dao/src/main/java/org/thingsboard/server/dao/nosql/CassandraBufferedRateWriteExecutor.java @@ -29,7 +29,7 @@ import org.thingsboard.server.dao.util.AbstractBufferedRateExecutor; import org.thingsboard.server.dao.util.AsyncTaskContext; import org.thingsboard.server.dao.util.NoSqlAnyDao; -import javax.annotation.PreDestroy; +import jakarta.annotation.PreDestroy; /** * Created by ashvayka on 24.10.18. diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java index 9818f4a2f0..0ba74f5811 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java @@ -43,7 +43,7 @@ import org.thingsboard.server.dao.entity.AbstractEntityService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; -import javax.transaction.Transactional; +import jakarta.transaction.Transactional; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; diff --git a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java index fb86e09ab3..6b631bf041 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java @@ -50,8 +50,8 @@ import org.thingsboard.server.dao.service.ConstraintValidator; import org.thingsboard.server.dao.sql.JpaExecutorService; import org.thingsboard.server.dao.sql.relation.JpaRelationQueryExecutorService; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/ConstraintValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/ConstraintValidator.java index b884de0094..b0ced3dcc3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/ConstraintValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/ConstraintValidator.java @@ -30,11 +30,11 @@ import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; import org.thingsboard.server.dao.exception.DataValidationException; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.constraints.AssertTrue; -import javax.validation.metadata.ConstraintDescriptor; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.metadata.ConstraintDescriptor; import java.util.Collection; import java.util.Set; import java.util.stream.Collectors; @@ -100,7 +100,7 @@ public class ConstraintValidator { } private static ConstraintMapping getCustomConstraintMapping() { - ConstraintMapping constraintMapping = new DefaultConstraintMapping(); + ConstraintMapping constraintMapping = new DefaultConstraintMapping(null); constraintMapping.constraintDefinition(NoXss.class).validatedBy(NoXssValidator.class); constraintMapping.constraintDefinition(Length.class).validatedBy(StringLengthValidator.class); return constraintMapping; diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/NoXssValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/NoXssValidator.java index 632caf10c4..8e7b2c6af0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/NoXssValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/NoXssValidator.java @@ -23,8 +23,8 @@ import org.owasp.validator.html.PolicyException; import org.owasp.validator.html.ScanException; import org.thingsboard.server.common.data.validation.NoXss; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; import java.util.Optional; @Slf4j diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/StringLengthValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/StringLengthValidator.java index d4299dcc0b..935eebf19a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/StringLengthValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/StringLengthValidator.java @@ -20,8 +20,8 @@ import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.validation.Length; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; @Slf4j public class StringLengthValidator implements ConstraintValidator { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/ScheduledLogExecutorComponent.java b/dao/src/main/java/org/thingsboard/server/dao/sql/ScheduledLogExecutorComponent.java index 83e1bf4afe..fa39130049 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/ScheduledLogExecutorComponent.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/ScheduledLogExecutorComponent.java @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.sql; import org.springframework.stereotype.Component; import org.thingsboard.common.util.ThingsBoardThreadFactory; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/TbSqlBlockingQueue.java b/dao/src/main/java/org/thingsboard/server/dao/sql/TbSqlBlockingQueue.java index fd3822bb5f..88145a9cf1 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/TbSqlBlockingQueue.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/TbSqlBlockingQueue.java @@ -41,6 +41,7 @@ public class TbSqlBlockingQueue implements TbSqlQueue { private ExecutorService executor; private final MessagesStats stats; + private volatile boolean stopped = false; public TbSqlBlockingQueue(TbSqlBlockingQueueParams params, MessagesStats stats) { this.params = params; @@ -55,7 +56,7 @@ public class TbSqlBlockingQueue implements TbSqlQueue { int batchSize = params.getBatchSize(); long maxDelay = params.getMaxDelay(); List> entities = new ArrayList<>(batchSize); - while (!Thread.interrupted()) { + while (!stopped) { try { long currentTs = System.currentTimeMillis(); TbSqlQueueElement attr = queue.poll(maxDelay, TimeUnit.MILLISECONDS); @@ -109,6 +110,7 @@ public class TbSqlBlockingQueue implements TbSqlQueue { @Override public void destroy() { + stopped = true; if (executor != null) { executor.shutdownNow(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java index 92537dc850..7fb6b31a3c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java @@ -52,8 +52,8 @@ public interface AlarmRepository extends JpaRepository { "AND ea.entityType = :affectedEntityType " + "AND (:startTime IS NULL OR (a.createdTime >= :startTime AND ea.createdTime >= :startTime)) " + "AND (:endTime IS NULL OR (a.createdTime <= :endTime AND ea.createdTime <= :endTime)) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -69,8 +69,8 @@ public interface AlarmRepository extends JpaRepository { "AND ea.entityType = :affectedEntityType " + "AND (:startTime IS NULL OR (a.createdTime >= :startTime AND ea.createdTime >= :startTime)) " + "AND (:endTime IS NULL OR (a.createdTime <= :endTime AND ea.createdTime <= :endTime)) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -97,10 +97,12 @@ public interface AlarmRepository extends JpaRepository { "AND ea.entityType = :affectedEntityType " + "AND (:startTime IS NULL OR (a.createdTime >= :startTime AND ea.createdTime >= :startTime)) " + "AND (:endTime IS NULL OR (a.createdTime <= :endTime AND ea.createdTime <= :endTime)) " + - "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + - "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:#{#alarmTypes == null} = true) OR a.type IN (:alarmTypes)) " + //HHH-15968 + "AND ((:#{#alarmSeverities == null} = true) OR a.severity IN (:alarmSeverities)) " + //HHH-15968 +// "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + +// "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -116,10 +118,12 @@ public interface AlarmRepository extends JpaRepository { "AND ea.entityType = :affectedEntityType " + "AND (:startTime IS NULL OR (a.createdTime >= :startTime AND ea.createdTime >= :startTime)) " + "AND (:endTime IS NULL OR (a.createdTime <= :endTime AND ea.createdTime <= :endTime)) " + - "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + - "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:#{#alarmTypes == null} = true) OR a.type IN (:alarmTypes)) " + //HHH-15968 + "AND ((:#{#alarmSeverities == null} = true) OR a.severity IN (:alarmSeverities)) " + //HHH-15968 +// "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + +// "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -144,8 +148,8 @@ public interface AlarmRepository extends JpaRepository { "WHERE a.tenantId = :tenantId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -156,8 +160,8 @@ public interface AlarmRepository extends JpaRepository { "WHERE a.tenantId = :tenantId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -178,10 +182,12 @@ public interface AlarmRepository extends JpaRepository { "WHERE a.tenantId = :tenantId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + - "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:#{#alarmTypes == null} = true) OR a.type IN (:alarmTypes)) " + //HHH-15968 + "AND ((:#{#alarmSeverities == null} = true) OR a.severity IN (:alarmSeverities)) " + //HHH-15968 +// "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + +// "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -192,10 +198,12 @@ public interface AlarmRepository extends JpaRepository { "WHERE a.tenantId = :tenantId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + - "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:#{#alarmTypes == null} = true) OR a.type IN (:alarmTypes)) " + //HHH-15968 + "AND ((:#{#alarmSeverities == null} = true) OR a.severity IN (:alarmSeverities)) " + //HHH-15968 +// "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + +// "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -218,8 +226,8 @@ public interface AlarmRepository extends JpaRepository { "WHERE a.tenantId = :tenantId AND a.customerId = :customerId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -231,8 +239,8 @@ public interface AlarmRepository extends JpaRepository { "WHERE a.tenantId = :tenantId AND a.customerId = :customerId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -254,10 +262,12 @@ public interface AlarmRepository extends JpaRepository { "WHERE a.tenantId = :tenantId AND a.customerId = :customerId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + - "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:#{#alarmTypes == null} = true) OR a.type IN (:alarmTypes)) " + //HHH-15968 + "AND ((:#{#alarmSeverities == null} = true) OR a.severity IN (:alarmSeverities)) " + //HHH-15968 +// "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + +// "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -269,10 +279,12 @@ public interface AlarmRepository extends JpaRepository { "WHERE a.tenantId = :tenantId AND a.customerId = :customerId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + - "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:#{#alarmTypes == null} = true) OR a.type IN (:alarmTypes)) " + //HHH-15968 + "AND ((:#{#alarmSeverities == null} = true) OR a.severity IN (:alarmSeverities)) " + //HHH-15968 +// "AND ((:alarmTypes) IS NULL OR a.type IN (:alarmTypes)) " + +// "AND ((:alarmSeverities) IS NULL OR a.severity IN (:alarmSeverities)) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId)) " + "AND (LOWER(a.type) LIKE LOWER(CONCAT('%', :searchText, '%')) " + " OR LOWER(a.severity) LIKE LOWER(CONCAT('%', :searchText, '%')) " + @@ -297,8 +309,8 @@ public interface AlarmRepository extends JpaRepository { "AND ea.tenantId = :tenantId " + "AND ea.entityId = :affectedEntityId " + "AND ea.entityType = :affectedEntityType " + - "AND ((:clearFilterEnabled) IS FALSE OR a.cleared = :clearFilter) " + - "AND ((:ackFilterEnabled) IS FALSE OR a.acknowledged = :ackFilter) " + + "AND ((:clearFilterEnabled) = FALSE OR a.cleared = :clearFilter) " + + "AND ((:ackFilterEnabled) = FALSE OR a.acknowledged = :ackFilter) " + "AND (:assigneeId IS NULL OR a.assigneeId = uuid(:assigneeId))") Set findAlarmSeverities(@Param("tenantId") UUID tenantId, @Param("affectedEntityId") UUID affectedEntityId, diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java index 4474378f32..6d195d1cc4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java @@ -19,6 +19,8 @@ import com.google.common.collect.Lists; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -39,8 +41,6 @@ import org.thingsboard.server.dao.sql.TbSqlBlockingQueueParams; import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; import org.thingsboard.server.dao.util.SqlDao; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; @@ -132,10 +132,10 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl @Override public List findAll(TenantId tenantId, EntityId entityId, String attributeType) { return DaoUtil.convertDataList(Lists.newArrayList( - attributeKvRepository.findAllByEntityTypeAndEntityIdAndAttributeType( - entityId.getEntityType(), - entityId.getId(), - attributeType))); + attributeKvRepository.findAllByEntityTypeAndEntityIdAndAttributeType( + entityId.getEntityType(), + entityId.getId(), + attributeType))); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/AuditLogRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/AuditLogRepository.java index 3d35383eb0..68aa2a0ee9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/audit/AuditLogRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/audit/AuditLogRepository.java @@ -33,7 +33,8 @@ public interface AuditLogRepository extends JpaRepository "a.tenantId = :tenantId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:actionTypes) IS NULL OR a.actionType in (:actionTypes)) " + + "AND ((:#{#actionTypes == null} = true) OR a.actionType IN (:actionTypes)) " + //HHH-15968 +// "AND ((:actionTypes) IS NULL OR a.actionType in (:actionTypes)) " + "AND (LOWER(a.entityType) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + "OR LOWER(a.entityName) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + "OR LOWER(a.userName) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + @@ -53,7 +54,8 @@ public interface AuditLogRepository extends JpaRepository "AND a.entityType = :entityType AND a.entityId = :entityId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:actionTypes) IS NULL OR a.actionType in (:actionTypes)) " + + "AND ((:#{#actionTypes == null} = true) OR a.actionType IN (:actionTypes)) " + //HHH-15968 +// "AND ((:actionTypes) IS NULL OR a.actionType in (:actionTypes)) " + "AND (LOWER(a.entityName) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + "OR LOWER(a.userName) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + "OR LOWER(a.actionType) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + @@ -73,7 +75,8 @@ public interface AuditLogRepository extends JpaRepository "AND a.customerId = :customerId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:actionTypes) IS NULL OR a.actionType in (:actionTypes)) " + + "AND ((:#{#actionTypes == null} = true) OR a.actionType IN (:actionTypes)) " + //HHH-15968 +// "AND ((:actionTypes) IS NULL OR a.actionType in (:actionTypes)) " + "AND (LOWER(a.entityType) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + "OR LOWER(a.entityName) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + "OR LOWER(a.userName) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + @@ -93,7 +96,8 @@ public interface AuditLogRepository extends JpaRepository "AND a.userId = :userId " + "AND (:startTime IS NULL OR a.createdTime >= :startTime) " + "AND (:endTime IS NULL OR a.createdTime <= :endTime) " + - "AND ((:actionTypes) IS NULL OR a.actionType in (:actionTypes)) " + + "AND ((:#{#actionTypes == null} = true) OR a.actionType IN (:actionTypes)) " + //HHH-15968 +// "AND ((:actionTypes) IS NULL OR a.actionType in (:actionTypes)) " + "AND (LOWER(a.entityType) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + "OR LOWER(a.entityName) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + "OR LOWER(a.actionType) LIKE LOWER(CONCAT('%', :textSearch, '%'))" + diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/AbstractComponentDescriptorInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/AbstractComponentDescriptorInsertRepository.java index 943697149c..83c841459f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/AbstractComponentDescriptorInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/AbstractComponentDescriptorInsertRepository.java @@ -25,9 +25,9 @@ import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.thingsboard.server.dao.model.sql.ComponentDescriptorEntity; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.Query; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Query; @Slf4j public abstract class AbstractComponentDescriptorInsertRepository implements ComponentDescriptorInsertRepository { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java index 89ed713975..f1f07381d3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java @@ -122,7 +122,7 @@ public interface DeviceRepository extends JpaRepository, Exp "AND (:edgeId IS NULL OR d.id IN (SELECT re.toId FROM RelationEntity re WHERE re.toType = 'DEVICE' AND re.relationTypeGroup = 'EDGE' AND re.relationType = 'Contains' AND re.fromType = 'EDGE' AND re.fromId = uuid(:edgeId))) " + "AND ((:deviceType) IS NULL OR d.type = :deviceType) " + "AND (:deviceProfileId IS NULL OR d.deviceProfileId = uuid(:deviceProfileId)) " + - "AND ((:filterByActive) IS FALSE OR d.active = :deviceActive) " + + "AND ((:filterByActive) = FALSE OR d.active = :deviceActive) " + "AND (LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + "OR LOWER(d.label) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + "OR LOWER(d.type) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java index 239fe1f098..6527f022f6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/edge/JpaBaseEdgeEventDao.java @@ -17,6 +17,8 @@ package org.thingsboard.server.dao.sql.edge; import com.datastax.oss.driver.api.core.uuid.Uuids; import com.google.common.util.concurrent.ListenableFuture; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -41,8 +43,6 @@ import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; import org.thingsboard.server.dao.util.SqlDao; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; import java.util.Comparator; import java.util.Objects; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java index 8d0df9e48d..1f08da69fa 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventInsertRepository.java @@ -33,7 +33,7 @@ import org.thingsboard.server.common.data.event.RuleNodeDebugEvent; import org.thingsboard.server.common.data.event.StatisticsEvent; import org.thingsboard.server.dao.util.SqlDao; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Types; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventPartitionConfiguration.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventPartitionConfiguration.java index 452e9b744f..546f813382 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventPartitionConfiguration.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventPartitionConfiguration.java @@ -20,7 +20,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.event.EventType; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.concurrent.TimeUnit; @Component diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java index f35e7e608f..3ba6d21aa0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java @@ -17,6 +17,8 @@ package org.thingsboard.server.dao.sql.event; import com.datastax.oss.driver.api.core.uuid.Uuids; import com.google.common.util.concurrent.ListenableFuture; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -43,8 +45,6 @@ import org.thingsboard.server.dao.sql.TbSqlBlockingQueueWrapper; import org.thingsboard.server.dao.sqlts.insert.sql.SqlPartitioningRepository; import org.thingsboard.server.dao.util.SqlDao; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; import java.util.Comparator; import java.util.List; import java.util.Map; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/QueryContext.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/QueryContext.java index 8ced23cdb4..a37432d66a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/QueryContext.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/QueryContext.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.sql.query; import lombok.extern.slf4j.Slf4j; -import org.hibernate.type.PostgresUUIDType; +import org.hibernate.type.descriptor.jdbc.UUIDJdbcType; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.CustomerId; @@ -30,7 +30,7 @@ import java.util.UUID; @Slf4j public class QueryContext implements SqlParameterSource { - private static final PostgresUUIDType UUID_TYPE = new PostgresUUIDType(); + private static final UUIDJdbcType UUID_TYPE = UUIDJdbcType.INSTANCE; private final QuerySecurityContext securityCtx; private final StringBuilder query; @@ -91,7 +91,7 @@ public class QueryContext implements SqlParameterSource { } public void addUuidParameter(String name, UUID value) { - addParameter(name, value, UUID_TYPE.sqlType(), UUID_TYPE.getName()); + addParameter(name, value, UUID_TYPE.getJdbcTypeCode(), UUID_TYPE.getFriendlyName()); } public void addStringParameter(String name, String value) { @@ -115,7 +115,7 @@ public class QueryContext implements SqlParameterSource { } public void addUuidListParameter(String name, List value) { - addParameter(name, value, UUID_TYPE.sqlType(), UUID_TYPE.getName()); + addParameter(name, value, UUID_TYPE.getJdbcTypeCode(), UUID_TYPE.getFriendlyName()); } public String getQuery() { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/SqlRelationInsertRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/SqlRelationInsertRepository.java index 835a23f6b5..fded581981 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/SqlRelationInsertRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/SqlRelationInsertRepository.java @@ -23,9 +23,9 @@ import org.springframework.transaction.annotation.Transactional; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.dao.model.sql.RelationEntity; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.Query; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.persistence.Query; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java index 71f9af99e5..991043db88 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractChunkedAggregationTimeseriesDao.java @@ -17,6 +17,8 @@ package org.thingsboard.server.dao.sqlts; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; @@ -38,8 +40,6 @@ import org.thingsboard.server.dao.sqlts.insert.InsertTsRepository; import org.thingsboard.server.dao.sqlts.ts.TsKvRepository; import org.thingsboard.server.dao.timeseries.TimeseriesDao; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; import java.util.ArrayList; import java.util.Comparator; import java.util.List; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractSqlTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractSqlTimeseriesDao.java index ee0dbab8c2..8c82981633 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractSqlTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/AbstractSqlTimeseriesDao.java @@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.sql.ScheduledLogExecutorComponent; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/BaseAbstractSqlTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/BaseAbstractSqlTimeseriesDao.java index c4c3e021c8..52c4216c69 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/BaseAbstractSqlTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/BaseAbstractSqlTimeseriesDao.java @@ -31,7 +31,7 @@ import org.thingsboard.server.dao.model.sqlts.dictionary.TsKvDictionaryComposite import org.thingsboard.server.dao.sql.JpaAbstractDaoListeningExecutorService; import org.thingsboard.server.dao.sqlts.dictionary.TsKvDictionaryRepository; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -53,11 +53,15 @@ public abstract class BaseAbstractSqlTimeseriesDao extends JpaAbstractDaoListeni if (keyId == null) { Optional tsKvDictionaryOptional; tsKvDictionaryOptional = dictionaryRepository.findById(new TsKvDictionaryCompositeKey(strKey)); - if (!tsKvDictionaryOptional.isPresent()) { + if (tsKvDictionaryOptional.isEmpty()) { tsCreationLock.lock(); try { + keyId = tsKvDictionaryMap.get(strKey); + if (keyId != null) { + return keyId; + } tsKvDictionaryOptional = dictionaryRepository.findById(new TsKvDictionaryCompositeKey(strKey)); - if (!tsKvDictionaryOptional.isPresent()) { + if (tsKvDictionaryOptional.isEmpty()) { TsKvDictionary tsKvDictionary = new TsKvDictionary(); tsKvDictionary.setKey(strKey); try { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/SqlTimeseriesLatestDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/SqlTimeseriesLatestDao.java index b58f0dc7c7..2312fa3cb2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/SqlTimeseriesLatestDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/SqlTimeseriesLatestDao.java @@ -49,8 +49,8 @@ import org.thingsboard.server.dao.sqlts.latest.TsKvLatestRepository; import org.thingsboard.server.dao.timeseries.TimeseriesLatestDao; import org.thingsboard.server.dao.util.SqlTsLatestAnyDao; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/latest/SearchTsKvLatestRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/latest/SearchTsKvLatestRepository.java index 7969e9c3c8..beaa4a5f0d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/latest/SearchTsKvLatestRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/latest/SearchTsKvLatestRepository.java @@ -19,8 +19,8 @@ import org.springframework.stereotype.Repository; import org.thingsboard.server.dao.model.sqlts.latest.TsKvLatestEntity; import org.thingsboard.server.dao.util.SqlTsLatestAnyDao; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; import java.util.List; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/AggregationRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/AggregationRepository.java index 43ad0a18fc..23a1f4e397 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/AggregationRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/AggregationRepository.java @@ -19,8 +19,8 @@ import org.springframework.stereotype.Repository; import org.thingsboard.server.dao.model.sqlts.timescale.ts.TimescaleTsKvEntity; import org.thingsboard.server.dao.util.TimescaleDBTsOrTsLatestDao; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; import java.util.List; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java index 42577c2d45..128073323c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/timescale/TimescaleTimeseriesDao.java @@ -42,8 +42,8 @@ import org.thingsboard.server.dao.sqlts.insert.InsertTsRepository; import org.thingsboard.server.dao.timeseries.TimeseriesDao; import org.thingsboard.server.dao.util.TimescaleDBTsDao; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/ts/TsKvRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/ts/TsKvRepository.java index 76b7af20a5..3a907f12bd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/ts/TsKvRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/ts/TsKvRepository.java @@ -30,12 +30,12 @@ import java.util.UUID; public interface TsKvRepository extends JpaRepository { /* - * Using native query to avoid adding 'nulls first' or 'nulls last' (ignoring spring.jpa.properties.hibernate.order_by.default_null_ordering) - * to the order so that index scan is done instead of full scan. - * - * Note: even when setting custom NullHandling for the Sort.Order for non-native queries, - * it will be ignored and default_null_ordering will be used - * */ + * Using native query to avoid adding 'nulls first' or 'nulls last' (ignoring spring.jpa.properties.hibernate.order_by.default_null_ordering) + * to the order so that index scan is done instead of full scan. + * + * Note: even when setting custom NullHandling for the Sort.Order for non-native queries, + * it will be ignored and default_null_ordering will be used + * */ @Query(value = "SELECT * FROM ts_kv WHERE entity_id = :entityId " + "AND key = :entityKey AND ts >= :startTs AND ts < :endTs ", nativeQuery = true) List findAllWithLimit(@Param("entityId") UUID entityId, @@ -57,41 +57,41 @@ public interface TsKvRepository extends JpaRepository= :startTs AND tskv.ts < :endTs") TsKvEntity findStringMax(@Param("entityId") UUID entityId, - @Param("entityKey") int entityKey, - @Param("startTs") long startTs, - @Param("endTs") long endTs); + @Param("entityKey") int entityKey, + @Param("startTs") long startTs, + @Param("endTs") long endTs); @Query("SELECT new TsKvEntity(MAX(COALESCE(tskv.longValue, -9223372036854775807)), " + - "MAX(COALESCE(tskv.doubleValue, -1.79769E+308)), " + + "MAX(COALESCE(tskv.doubleValue, java.lang.Double.MIN_VALUE)), " + "SUM(CASE WHEN tskv.longValue IS NULL THEN 0 ELSE 1 END), " + "SUM(CASE WHEN tskv.doubleValue IS NULL THEN 0 ELSE 1 END), " + "'MAX', MAX(tskv.ts)) FROM TsKvEntity tskv " + "WHERE tskv.entityId = :entityId AND tskv.key = :entityKey AND tskv.ts >= :startTs AND tskv.ts < :endTs") TsKvEntity findNumericMax(@Param("entityId") UUID entityId, - @Param("entityKey") int entityKey, - @Param("startTs") long startTs, - @Param("endTs") long endTs); + @Param("entityKey") int entityKey, + @Param("startTs") long startTs, + @Param("endTs") long endTs); @Query("SELECT new TsKvEntity(MIN(tskv.strValue), MAX(tskv.ts)) FROM TsKvEntity tskv " + "WHERE tskv.strValue IS NOT NULL " + "AND tskv.entityId = :entityId AND tskv.key = :entityKey AND tskv.ts >= :startTs AND tskv.ts < :endTs") TsKvEntity findStringMin(@Param("entityId") UUID entityId, - @Param("entityKey") int entityKey, - @Param("startTs") long startTs, - @Param("endTs") long endTs); + @Param("entityKey") int entityKey, + @Param("startTs") long startTs, + @Param("endTs") long endTs); @Query("SELECT new TsKvEntity(MIN(COALESCE(tskv.longValue, 9223372036854775807)), " + - "MIN(COALESCE(tskv.doubleValue, 1.79769E+308)), " + + "MIN(COALESCE(tskv.doubleValue, java.lang.Double.MAX_VALUE)), " + "SUM(CASE WHEN tskv.longValue IS NULL THEN 0 ELSE 1 END), " + "SUM(CASE WHEN tskv.doubleValue IS NULL THEN 0 ELSE 1 END), " + "'MIN', MAX(tskv.ts)) FROM TsKvEntity tskv " + "WHERE tskv.entityId = :entityId AND tskv.key = :entityKey AND tskv.ts >= :startTs AND tskv.ts < :endTs") TsKvEntity findNumericMin( - @Param("entityId") UUID entityId, - @Param("entityKey") int entityKey, - @Param("startTs") long startTs, - @Param("endTs") long endTs); + @Param("entityId") UUID entityId, + @Param("entityKey") int entityKey, + @Param("startTs") long startTs, + @Param("endTs") long endTs); @Query("SELECT new TsKvEntity(SUM(CASE WHEN tskv.booleanValue IS NULL THEN 0 ELSE 1 END), " + "SUM(CASE WHEN tskv.strValue IS NULL THEN 0 ELSE 1 END), " + @@ -100,9 +100,9 @@ public interface TsKvRepository extends JpaRepository= :startTs AND tskv.ts < :endTs") TsKvEntity findCount(@Param("entityId") UUID entityId, - @Param("entityKey") int entityKey, - @Param("startTs") long startTs, - @Param("endTs") long endTs); + @Param("entityKey") int entityKey, + @Param("startTs") long startTs, + @Param("endTs") long endTs); @Query("SELECT new TsKvEntity(SUM(COALESCE(tskv.longValue, 0)), " + "SUM(COALESCE(tskv.doubleValue, 0.0)), " + @@ -111,9 +111,9 @@ public interface TsKvRepository extends JpaRepository= :startTs AND tskv.ts < :endTs") TsKvEntity findAvg(@Param("entityId") UUID entityId, - @Param("entityKey") int entityKey, - @Param("startTs") long startTs, - @Param("endTs") long endTs); + @Param("entityKey") int entityKey, + @Param("startTs") long startTs, + @Param("endTs") long endTs); @Query("SELECT new TsKvEntity(SUM(COALESCE(tskv.longValue, 0)), " + "SUM(COALESCE(tskv.doubleValue, 0.0)), " + @@ -122,8 +122,8 @@ public interface TsKvRepository extends JpaRepository= :startTs AND tskv.ts < :endTs") TsKvEntity findSum(@Param("entityId") UUID entityId, - @Param("entityKey") int entityKey, - @Param("startTs") long startTs, - @Param("endTs") long endTs); + @Param("entityKey") int entityKey, + @Param("startTs") long startTs, + @Param("endTs") long endTs); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java index e4aca8ecd1..16655514b3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/AggregatePartitionsFunction.java @@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.kv.TsKvEntryAggWrapper; import org.thingsboard.server.dao.nosql.TbResultSet; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.List; import java.util.Optional; import java.util.concurrent.Executor; diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java index 6f14b526a5..4be65b3a93 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/CassandraBaseTimeseriesDao.java @@ -52,9 +52,9 @@ import org.thingsboard.server.dao.nosql.TbResultSetFuture; import org.thingsboard.server.dao.sqlts.AggregationTimeseriesDao; import org.thingsboard.server.dao.util.NoSqlTsDao; -import javax.annotation.Nullable; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java b/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java index 9fbf796eb0..e70a6ba4ac 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java +++ b/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java @@ -41,7 +41,7 @@ import org.thingsboard.server.dao.entity.EntityService; import org.thingsboard.server.dao.nosql.CassandraStatementTask; import org.thingsboard.server.dao.tenant.TbTenantProfileCache; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.HashMap; import java.util.Map; import java.util.UUID; diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/AbstractJsonSqlTypeDescriptor.java b/dao/src/main/java/org/thingsboard/server/dao/util/mapping/AbstractJsonSqlTypeDescriptor.java deleted file mode 100644 index 9f69d65fc6..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/AbstractJsonSqlTypeDescriptor.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright © 2016-2023 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.dao.util.mapping; - -import org.hibernate.type.descriptor.ValueExtractor; -import org.hibernate.type.descriptor.WrapperOptions; -import org.hibernate.type.descriptor.java.JavaTypeDescriptor; -import org.hibernate.type.descriptor.sql.BasicExtractor; -import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; - -import java.sql.CallableStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; - -public abstract class AbstractJsonSqlTypeDescriptor - implements SqlTypeDescriptor { - - @Override - public int getSqlType() { - return Types.VARCHAR; - } - - @Override - public boolean canBeRemapped() { - return true; - } - - @Override - public ValueExtractor getExtractor( - final JavaTypeDescriptor javaTypeDescriptor) { - return new BasicExtractor(javaTypeDescriptor, this) { - @Override - protected X doExtract( - ResultSet rs, - String name, - WrapperOptions options) throws SQLException { - return javaTypeDescriptor.wrap( - rs.getObject(name), options - ); - } - - @Override - protected X doExtract( - CallableStatement statement, - int index, - WrapperOptions options) throws SQLException { - return javaTypeDescriptor.wrap( - statement.getObject(index), options - ); - } - - @Override - protected X doExtract( - CallableStatement statement, - String name, - WrapperOptions options) throws SQLException { - return javaTypeDescriptor.wrap( - statement.getObject(name), options - ); - } - }; - } - -} \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonBinarySqlTypeDescriptor.java b/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonBinarySqlTypeDescriptor.java deleted file mode 100644 index e41b998148..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonBinarySqlTypeDescriptor.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright © 2016-2023 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.dao.util.mapping; - -import com.fasterxml.jackson.databind.JsonNode; -import org.hibernate.type.descriptor.ValueBinder; -import org.hibernate.type.descriptor.WrapperOptions; -import org.hibernate.type.descriptor.java.JavaTypeDescriptor; -import org.hibernate.type.descriptor.sql.BasicBinder; - -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Types; - -public class JsonBinarySqlTypeDescriptor extends AbstractJsonSqlTypeDescriptor { - - public static final JsonBinarySqlTypeDescriptor INSTANCE = new JsonBinarySqlTypeDescriptor(); - - @Override - public int getSqlType() { - return Types.OTHER; - } - - @Override - public ValueBinder getBinder(final JavaTypeDescriptor javaTypeDescriptor) { - return new BasicBinder(javaTypeDescriptor, this) { - @Override - protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException { - st.setObject(index, javaTypeDescriptor.unwrap(value, JsonNode.class, options), getSqlType()); - } - - @Override - protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) throws SQLException { - st.setObject(name, javaTypeDescriptor.unwrap(value, JsonNode.class, options), getSqlType()); - } - }; - } -} diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonBinaryType.java b/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonBinaryType.java deleted file mode 100644 index 7b4760a38f..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonBinaryType.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright © 2016-2023 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.dao.util.mapping; - -import org.hibernate.type.AbstractSingleColumnStandardBasicType; -import org.hibernate.usertype.DynamicParameterizedType; - -import java.util.Properties; - -public class JsonBinaryType extends AbstractSingleColumnStandardBasicType implements DynamicParameterizedType { - - public JsonBinaryType() { - super( - JsonBinarySqlTypeDescriptor.INSTANCE, - new JsonTypeDescriptor() - ); - } - - public String getName() { - return "jsonb"; - } - - @Override - protected boolean registerUnderJavaType() { - return true; - } - - @Override - public void setParameterValues(Properties parameters) { - ((JsonTypeDescriptor) getJavaTypeDescriptor()) - .setParameterValues(parameters); - } -} diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonConverter.java b/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonConverter.java new file mode 100644 index 0000000000..78c2b8852c --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonConverter.java @@ -0,0 +1,34 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.util.mapping; + +import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; +import org.thingsboard.common.util.JacksonUtil; + +@Converter +public class JsonConverter implements AttributeConverter { + @Override + public String convertToDatabaseColumn(JsonNode jsonNode) { + return JacksonUtil.toString(jsonNode); + } + + @Override + public JsonNode convertToEntityAttribute(String s) { + return JacksonUtil.toJsonNode(s); + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonStringSqlTypeDescriptor.java b/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonStringSqlTypeDescriptor.java deleted file mode 100644 index 314eb2751f..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonStringSqlTypeDescriptor.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright © 2016-2023 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.dao.util.mapping; - -import org.hibernate.type.descriptor.ValueBinder; -import org.hibernate.type.descriptor.WrapperOptions; -import org.hibernate.type.descriptor.java.JavaTypeDescriptor; -import org.hibernate.type.descriptor.sql.BasicBinder; - -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.SQLException; - -public class JsonStringSqlTypeDescriptor - extends AbstractJsonSqlTypeDescriptor { - - public static final JsonStringSqlTypeDescriptor INSTANCE = - new JsonStringSqlTypeDescriptor(); - - @Override - public ValueBinder getBinder( - final JavaTypeDescriptor javaTypeDescriptor) { - return new BasicBinder(javaTypeDescriptor, this) { - @Override - protected void doBind( - PreparedStatement st, - X value, - int index, - WrapperOptions options) throws SQLException { - st.setString(index, - javaTypeDescriptor.unwrap(value, String.class, options) - ); - } - - @Override - protected void doBind( - CallableStatement st, - X value, - String name, - WrapperOptions options) - throws SQLException { - st.setString(name, - javaTypeDescriptor.unwrap(value, String.class, options - )); - } - }; - } -} \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonStringType.java b/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonStringType.java deleted file mode 100644 index 42627ef27f..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonStringType.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright © 2016-2023 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.dao.util.mapping; - -import org.hibernate.type.AbstractSingleColumnStandardBasicType; -import org.hibernate.usertype.DynamicParameterizedType; - -import java.util.Properties; - -public class JsonStringType - extends AbstractSingleColumnStandardBasicType - implements DynamicParameterizedType { - - public JsonStringType() { - super( - JsonStringSqlTypeDescriptor.INSTANCE, - new JsonTypeDescriptor() - ); - } - - public String getName() { - return "json"; - } - - @Override - protected boolean registerUnderJavaType() { - return true; - } - - @Override - public void setParameterValues(Properties parameters) { - ((JsonTypeDescriptor) getJavaTypeDescriptor()) - .setParameterValues(parameters); - } -} \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonTypeDescriptor.java b/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonTypeDescriptor.java deleted file mode 100644 index 0654cab84f..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/util/mapping/JsonTypeDescriptor.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright © 2016-2023 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.dao.util.mapping; - -import org.hibernate.type.descriptor.WrapperOptions; -import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; -import org.hibernate.type.descriptor.java.MutableMutabilityPlan; -import org.hibernate.usertype.DynamicParameterizedType; -import org.thingsboard.common.util.JacksonUtil; - -import java.util.Properties; - -/** - * Created by Valerii Sosliuk on 5/12/2017. - */ -public class JsonTypeDescriptor - extends AbstractTypeDescriptor - implements DynamicParameterizedType { - - private Class jsonObjectClass; - - @Override - public void setParameterValues(Properties parameters) { - jsonObjectClass = ( (ParameterType) parameters.get( PARAMETER_TYPE ) ) - .getReturnedClass(); - - } - - public JsonTypeDescriptor() { - super( Object.class, new MutableMutabilityPlan() { - @Override - protected Object deepCopyNotNull(Object value) { - return JacksonUtil.clone(value); - } - }); - } - - @Override - public boolean areEqual(Object one, Object another) { - if ( one == another ) { - return true; - } - if ( one == null || another == null ) { - return false; - } - return JacksonUtil.toJsonNode(JacksonUtil.toString(one)).equals( - JacksonUtil.toJsonNode(JacksonUtil.toString(another))); - } - - @Override - public String toString(Object value) { - return JacksonUtil.toString(value); - } - - @Override - public Object fromString(String string) { - return JacksonUtil.fromString(string, jsonObjectClass); - } - - @SuppressWarnings({ "unchecked" }) - @Override - public X unwrap(Object value, Class type, WrapperOptions options) { - if ( value == null ) { - return null; - } - if ( String.class.isAssignableFrom( type ) ) { - return (X) toString(value); - } - if ( Object.class.isAssignableFrom( type ) ) { - return (X) JacksonUtil.toJsonNode(toString(value)); - } - throw unknownUnwrap( type ); - } - - @Override - public Object wrap(X value, WrapperOptions options) { - if ( value == null ) { - return null; - } - return fromString(value.toString()); - } - -} \ No newline at end of file diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/notification/channels/impl/SlackNotificationChannel.java b/monitoring/src/main/java/org/thingsboard/monitoring/notification/channels/impl/SlackNotificationChannel.java index 092ea0b8c6..28b5133402 100644 --- a/monitoring/src/main/java/org/thingsboard/monitoring/notification/channels/impl/SlackNotificationChannel.java +++ b/monitoring/src/main/java/org/thingsboard/monitoring/notification/channels/impl/SlackNotificationChannel.java @@ -24,7 +24,7 @@ import org.springframework.web.client.RestTemplate; import org.thingsboard.monitoring.data.notification.Notification; import org.thingsboard.monitoring.notification.channels.NotificationChannel; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.time.Duration; import java.util.Map; diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportHealthChecker.java b/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportHealthChecker.java index 0c742e7709..bc6bfb2680 100644 --- a/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportHealthChecker.java +++ b/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportHealthChecker.java @@ -31,8 +31,8 @@ import org.thingsboard.monitoring.data.TransportInfo; import org.thingsboard.monitoring.service.MonitoringReporter; import org.thingsboard.monitoring.util.TbStopWatch; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.util.UUID; @Slf4j diff --git a/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportMonitoringService.java b/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportMonitoringService.java index d94cbc9624..18a8013e2b 100644 --- a/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportMonitoringService.java +++ b/monitoring/src/main/java/org/thingsboard/monitoring/transport/TransportMonitoringService.java @@ -54,7 +54,7 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import java.util.LinkedList; import java.util.List; import java.util.UUID; diff --git a/msa/monitoring/pom.xml b/msa/monitoring/pom.xml index 1fe43219a0..ba96ada39c 100644 --- a/msa/monitoring/pom.xml +++ b/msa/monitoring/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.5.1-SNAPSHOT + 3.6.0-SNAPSHOT msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index 0ae03f3980..3e09ac6b98 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -69,6 +69,10 @@ ch.qos.logback logback-classic + + jakarta.annotation + jakarta.annotation-api + org.springframework.boot spring-boot-starter-test diff --git a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttClientConfig.java b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttClientConfig.java index 1e20a842c3..f697f86e8e 100644 --- a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttClientConfig.java +++ b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttClientConfig.java @@ -20,8 +20,8 @@ import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.mqtt.MqttVersion; import io.netty.handler.ssl.SslContext; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; import java.util.Random; @SuppressWarnings({"WeakerAccess", "unused"}) diff --git a/pom.xml b/pom.xml index 4d456b8f4e..fb667a9526 100755 --- a/pom.xml +++ b/pom.xml @@ -36,20 +36,21 @@ ${project.name} /var/log/${pkg.name} /usr/share/${pkg.name} - 1.3.2 - 2.3.2 - 2.3.2 - 2.7.10 - 2.7.10 - 5.3.26 - 5.5.17 - 5.7.7 - 2.7.10 - 3.8.0 - 0.7.0 - 1.7.32 - 2.17.1 - 1.2.10 + 2.1.1 + 4.0.0 + 2.3.1 + 4.0.2 + 3.1.0 + 3.1.0 + 6.0.9 + 6.1.0 + 6.1.0 + 3.1.0 + 4.3.2 + 0.9.1 + 2.0.7 + 2.19.0 + 1.4.7 0.10 4.15.0 4.0.5 @@ -73,8 +74,8 @@ 2.0.0-M5 2.9.0 2.3.30 - 1.6.2 - 4.2.0 + 2.0.1 + 5.5.0 3.8.1 3.21.9 1.42.1 @@ -82,8 +83,9 @@ 1.18.26 1.2.4 1.2.5 - 4.1.91.Final - 2.0.51.Final + 4.1.93.Final + 2.0.61.Final + 1.1.7 1.7.0 4.8.0 3.0.0-M9 @@ -111,25 +113,25 @@ 1.11.747 1.105.0 2.1.0 - 3.2.0 + 3.6.7 1.5.0 1.5.4 1.9.4 3.2.2 - 1.9.0 + 1.11.0 1.0.4TB 3.4.0 - 8.17.0 - 6.0.20.Final - 3.0.0 - 2.0.1.Final - 1.7.2 + 9.6.1 + 8.0.0.Final + 4.0.2 + 3.0.2 + 1.7.3 2.8.5 4.1.0 2.7.2 1.5.2 - 5.8.2 + 5.9.3 2.6.0 5.13.1 1.3.0 @@ -612,6 +614,7 @@ -Xlint:deprecation -Xlint:removal -Xlint:unchecked + -parameters @@ -663,7 +666,7 @@ ${surefire.version} - --illegal-access=permit -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=20 + -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=20 --add-opens java.base/java.lang.reflect=ALL-UNNAMED @@ -1073,15 +1076,20 @@ test - javax.annotation - javax.annotation-api - ${javax-annotation.version} + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation.version} jakarta.xml.bind jakarta.xml.bind-api ${jakarta.xml.bind-api.version} + + javax.xml.bind + jaxb-api + ${javax.xml.bind-api.version} + org.glassfish.jaxb jaxb-runtime @@ -1149,6 +1157,16 @@ spring-data-commons ${spring-data.version} + + org.springframework.boot + spring-boot-starter-webflux + ${spring-boot.version} + + + io.projectreactor.netty + reactor-netty-http + ${reactor-netty.version} + org.apache.kafka kafka-clients @@ -1218,7 +1236,7 @@ com.sun.mail - javax.mail + jakarta.mail ${mail.version} @@ -1324,12 +1342,32 @@ netty-transport ${netty.version} + + io.netty + netty-transport-classes-epoll + ${netty.version} + + + io.netty + netty-transport-classes-kqueue + ${netty.version} + + + io.netty + netty-transport-native-epoll + ${netty.version} + io.netty netty-transport-native-epoll ${netty.version} linux-x86_64 + + io.netty + netty-transport-native-kqueue + ${netty.version} + io.netty netty-transport-native-kqueue @@ -1901,6 +1939,10 @@ io.jsonwebtoken jjwt-impl + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + @@ -1910,13 +1952,13 @@ org.glassfish - javax.el - ${javax.el.version} + jakarta.el + ${jakarta.el.version} - javax.validation - validation-api - ${javax.validation-api.version} + jakarta.validation + jakarta.validation-api + ${jakarta.validation-api.version} org.owasp.antisamy diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 47d13e5658..eb57b59c3f 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -95,7 +95,7 @@ com.sun.mail - javax.mail + jakarta.mail provided diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 34c6e315f7..c449b590fe 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -84,6 +84,14 @@ spring-web provided + + org.springframework.boot + spring-boot-starter-webflux + + + io.projectreactor.netty + reactor-netty-http + org.apache.kafka kafka-clients @@ -118,7 +126,7 @@ com.sun.mail - javax.mail + jakarta.mail provided 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 6f7bb7cf8d..cbb15f5854 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 @@ -39,7 +39,7 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.adaptor.JsonConverter; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Set; 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 3377ac9ded..9d458fdc1c 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 @@ -43,7 +43,7 @@ import org.thingsboard.server.dao.cassandra.guava.GuavaSession; import org.thingsboard.server.dao.nosql.CassandraStatementTask; import org.thingsboard.server.dao.nosql.TbResultSetFuture; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Map; 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 dcaf6698cd..add560431f 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 @@ -32,8 +32,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; -import javax.annotation.Nullable; -import java.io.IOException; +import jakarta.annotation.Nullable; @Slf4j @RuleNode( diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNodeConfiguration.java index 9508a6a848..27be78a683 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNodeConfiguration.java @@ -19,8 +19,8 @@ import lombok.Data; import org.thingsboard.rule.engine.api.NodeConfiguration; import org.thingsboard.server.common.data.id.NotificationTemplateId; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import java.util.List; import java.util.UUID; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbSlackNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbSlackNodeConfiguration.java index 6e15bd834f..29b2c6029c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbSlackNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbSlackNodeConfiguration.java @@ -20,9 +20,9 @@ import org.thingsboard.rule.engine.api.NodeConfiguration; import org.thingsboard.server.common.data.notification.targets.slack.SlackConversation; import org.thingsboard.server.common.data.notification.targets.slack.SlackConversationType; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; @Data public class TbSlackNodeConfiguration implements NodeConfiguration { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 6f9541f5b1..28deb5b4da 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -15,30 +15,19 @@ */ package org.thingsboard.rule.engine.rest; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.handler.ssl.SslContext; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; -import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; -import org.apache.http.impl.nio.client.HttpAsyncClients; -import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory; -import org.springframework.http.client.Netty4ClientHttpRequestFactory; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.ListenableFutureCallback; -import org.springframework.web.client.AsyncRestTemplate; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.client.RestClientResponseException; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec; import org.springframework.web.util.UriComponentsBuilder; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.TbContext; @@ -51,24 +40,20 @@ import org.thingsboard.rule.engine.credentials.CredentialsType; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; +import reactor.netty.http.client.HttpClient; +import reactor.netty.transport.ProxyProvider; -import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; -import java.net.Authenticator; -import java.net.PasswordAuthentication; import java.net.URI; import java.nio.charset.StandardCharsets; -import java.security.NoSuchAlgorithmException; -import java.util.Deque; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @Data @Slf4j -@SuppressWarnings("deprecation") public class TbHttpClient { private static final String STATUS = "status"; @@ -80,86 +65,58 @@ public class TbHttpClient { private final TbRestApiCallNodeConfiguration config; - private EventLoopGroup eventLoopGroup; - private AsyncRestTemplate httpClient; - private Deque>> pendingFutures; + private WebClient webClient; + private Semaphore semaphore; - TbHttpClient(TbRestApiCallNodeConfiguration config, EventLoopGroup eventLoopGroupShared) throws TbNodeException { + TbHttpClient(TbRestApiCallNodeConfiguration config) throws TbNodeException { try { this.config = config; if (config.getMaxParallelRequestsCount() > 0) { - pendingFutures = new ConcurrentLinkedDeque<>(); + semaphore = new Semaphore(config.getMaxParallelRequestsCount()); } + HttpClient httpClient = HttpClient.create(); + if (config.isEnableProxy()) { checkProxyHost(config.getProxyHost()); checkProxyPort(config.getProxyPort()); - String proxyUser; - String proxyPassword; - - CloseableHttpAsyncClient asyncClient; - HttpComponentsAsyncClientHttpRequestFactory requestFactory = new HttpComponentsAsyncClientHttpRequestFactory(); - if (config.isUseSystemProxyProperties()) { checkSystemProxyProperties(); - - asyncClient = HttpAsyncClients.createSystem(); - - proxyUser = System.getProperty("tb.proxy.user"); - proxyPassword = System.getProperty("tb.proxy.password"); - - if (useAuth(proxyUser, proxyPassword)) { - Authenticator.setDefault(new Authenticator() { - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(proxyUser, proxyPassword.toCharArray()); - } - }); - } + //TODO: maybe we should replace it and manually get all system props + httpClient = httpClient.proxyWithSystemProperties(); } else { - HttpAsyncClientBuilder httpAsyncClientBuilder = HttpAsyncClientBuilder.create() - .setSSLHostnameVerifier(new DefaultHostnameVerifier()) - .setSSLContext(SSLContext.getDefault()) - .setProxy(new HttpHost(config.getProxyHost(), config.getProxyPort(), config.getProxyScheme())); - - proxyUser = config.getProxyUser(); - proxyPassword = config.getProxyPassword(); - - if (useAuth(proxyUser, proxyPassword)) { - CredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials( - new AuthScope(config.getProxyHost(), config.getProxyPort()), - new UsernamePasswordCredentials(proxyUser, proxyPassword) - ); - httpAsyncClientBuilder.setDefaultCredentialsProvider(credsProvider); - } - asyncClient = httpAsyncClientBuilder.build(); + checkProxyHost(config.getProxyHost()); + checkProxyPort(config.getProxyPort()); + + String proxyUser = config.getProxyUser(); + String proxyPassword = config.getProxyPassword(); + + httpClient = httpClient.proxy(options -> + options.type(ProxyProvider.Proxy.HTTP) + .host(config.getProxyHost()) + .port(config.getProxyPort()) + .username(proxyUser) + .password(u -> proxyPassword)); } - - requestFactory.setAsyncClient(asyncClient); - requestFactory.setReadTimeout(config.getReadTimeoutMs()); - httpClient = new AsyncRestTemplate(requestFactory); - } else if (config.isUseSimpleClientHttpFactory()) { + } else if (!config.isUseSimpleClientHttpFactory()) { if (CredentialsType.CERT_PEM == config.getCredentials().getType()) { throw new TbNodeException("Simple HTTP Factory does not support CERT PEM credentials!"); } - httpClient = new AsyncRestTemplate(); + + httpClient = HttpClient.create(); + } else { - Netty4ClientHttpRequestFactory nettyFactory = new Netty4ClientHttpRequestFactory(getSharedOrCreateEventLoopGroup(eventLoopGroupShared)); - nettyFactory.setSslContext(config.getCredentials().initSslContext()); - nettyFactory.setReadTimeout(config.getReadTimeoutMs()); - httpClient = new AsyncRestTemplate(nettyFactory); + SslContext sslContext = config.getCredentials().initSslContext(); + httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext)); } - } catch (SSLException | NoSuchAlgorithmException e) { - throw new TbNodeException(e); - } - } - EventLoopGroup getSharedOrCreateEventLoopGroup(EventLoopGroup eventLoopGroupShared) { - if (eventLoopGroupShared != null) { - return eventLoopGroupShared; + this.webClient = WebClient.builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build(); + } catch (SSLException e) { + throw new TbNodeException(e); } - return this.eventLoopGroup = new NioEventLoopGroup(); } private void checkSystemProxyProperties() throws TbNodeException { @@ -176,48 +133,52 @@ public class TbHttpClient { return !StringUtils.isEmpty(proxyUser) && !StringUtils.isEmpty(proxyPassword); } - void destroy() { - if (this.eventLoopGroup != null) { - this.eventLoopGroup.shutdownGracefully(0, 5, TimeUnit.SECONDS); - } - } - public void processMessage(TbContext ctx, TbMsg msg) { - String endpointUrl = TbNodeUtils.processPattern(config.getRestEndpointUrlPattern(), msg); - HttpHeaders headers = prepareHeaders(msg); - HttpMethod method = HttpMethod.valueOf(config.getRequestMethod()); - HttpEntity entity; - if(HttpMethod.GET.equals(method) || HttpMethod.HEAD.equals(method) || - HttpMethod.OPTIONS.equals(method) || HttpMethod.TRACE.equals(method) || - config.isIgnoreRequestBody()) { - entity = new HttpEntity<>(headers); - } else { - entity = new HttpEntity<>(getData(msg), headers); - } - - URI uri = buildEncodedUri(endpointUrl); - ListenableFuture> future = httpClient.exchange( - uri, method, entity, String.class); - future.addCallback(new ListenableFutureCallback>() { - @Override - public void onFailure(Throwable throwable) { - TbMsg next = processException(ctx, msg, throwable); - ctx.tellFailure(next, throwable); + try { + if (semaphore != null) { + semaphore.tryAcquire(config.getReadTimeoutMs(), TimeUnit.MILLISECONDS); } - @Override - public void onSuccess(ResponseEntity responseEntity) { - if (responseEntity.getStatusCode().is2xxSuccessful()) { - TbMsg next = processResponse(ctx, msg, responseEntity); - ctx.tellSuccess(next); - } else { - TbMsg next = processFailureResponse(ctx, msg, responseEntity); - ctx.tellNext(next, TbRelationTypes.FAILURE); - } + String endpointUrl = TbNodeUtils.processPattern(config.getRestEndpointUrlPattern(), msg); + HttpMethod method = HttpMethod.valueOf(config.getRequestMethod()); + URI uri = buildEncodedUri(endpointUrl); + + RequestBodySpec request = webClient + .method(method) + .uri(uri) + .headers(headers -> prepareHeaders(headers, msg)); + + if (HttpMethod.POST.equals(method) || HttpMethod.PUT.equals(method) || + HttpMethod.PATCH.equals(method) || HttpMethod.DELETE.equals(method) || + config.isIgnoreRequestBody()) { + request.body(BodyInserters.fromValue(getData(msg))); } - }); - if (pendingFutures != null) { - processParallelRequests(future); + + request + .retrieve() + .toEntity(String.class) + .subscribe(responseEntity -> { + if (semaphore != null) { + semaphore.release(); + } + + if (responseEntity.getStatusCode().is2xxSuccessful()) { + TbMsg next = processResponse(ctx, msg, responseEntity); + ctx.tellSuccess(next); + } else { + TbMsg next = processFailureResponse(ctx, msg, responseEntity); + ctx.tellNext(next, TbRelationTypes.FAILURE); + } + }, throwable -> { + if (semaphore != null) { + semaphore.release(); // Make sure to release in case of error + } + + TbMsg next = processException(ctx, msg, throwable); + ctx.tellFailure(next, throwable); + }); + } catch (InterruptedException e) { + log.warn("Timeout during waiting for reply!", e); } } @@ -248,7 +209,7 @@ public class TbHttpClient { if (config.isTrimDoubleQuotes()) { final String dataBefore = data; - data = data.replaceAll("^\"|\"$", "");; + data = data.replaceAll("^\"|\"$", ""); log.trace("Trimming double quotes. Before trim: [{}], after trim: [{}]", dataBefore, data); } @@ -257,9 +218,10 @@ public class TbHttpClient { private TbMsg processResponse(TbContext ctx, TbMsg origMsg, ResponseEntity response) { TbMsgMetaData metaData = origMsg.getMetaData(); - metaData.putValue(STATUS, response.getStatusCode().name()); + HttpStatus httpStatus = (HttpStatus) response.getStatusCode(); + metaData.putValue(STATUS, httpStatus.name()); metaData.putValue(STATUS_CODE, response.getStatusCode().value() + ""); - metaData.putValue(STATUS_REASON, response.getStatusCode().getReasonPhrase()); + metaData.putValue(STATUS_REASON, httpStatus.getReasonPhrase()); headersToMetaData(response.getHeaders(), metaData::putValue); String body = response.getBody() == null ? "{}" : response.getBody(); return ctx.transformMsg(origMsg, origMsg.getType(), origMsg.getOriginator(), metaData, body); @@ -281,10 +243,11 @@ public class TbHttpClient { } private TbMsg processFailureResponse(TbContext ctx, TbMsg origMsg, ResponseEntity response) { + HttpStatus httpStatus = (HttpStatus) response.getStatusCode(); TbMsgMetaData metaData = origMsg.getMetaData(); - metaData.putValue(STATUS, response.getStatusCode().name()); + metaData.putValue(STATUS, httpStatus.name()); metaData.putValue(STATUS_CODE, response.getStatusCode().value() + ""); - metaData.putValue(STATUS_REASON, response.getStatusCode().getReasonPhrase()); + metaData.putValue(STATUS_REASON, httpStatus.getReasonPhrase()); metaData.putValue(ERROR_BODY, response.getBody()); headersToMetaData(response.getHeaders(), metaData::putValue); return ctx.transformMsg(origMsg, origMsg.getType(), origMsg.getOriginator(), metaData, origMsg.getData()); @@ -302,8 +265,7 @@ public class TbHttpClient { return ctx.transformMsg(origMsg, origMsg.getType(), origMsg.getOriginator(), metaData, origMsg.getData()); } - private HttpHeaders prepareHeaders(TbMsg msg) { - HttpHeaders headers = new HttpHeaders(); + private void prepareHeaders(HttpHeaders headers, TbMsg msg) { config.getHeaders().forEach((k, v) -> headers.add(TbNodeUtils.processPattern(k, msg), TbNodeUtils.processPattern(v, msg))); ClientCredentials credentials = config.getCredentials(); if (CredentialsType.BASIC == credentials.getType()) { @@ -312,26 +274,6 @@ public class TbHttpClient { String encodedAuthString = new String(Base64.encodeBase64(authString.getBytes(StandardCharsets.UTF_8))); headers.add("Authorization", "Basic " + encodedAuthString); } - return headers; - } - - private void processParallelRequests(ListenableFuture> future) { - pendingFutures.add(future); - if (pendingFutures.size() > config.getMaxParallelRequestsCount()) { - for (int i = 0; i < config.getMaxParallelRequestsCount(); i++) { - try { - ListenableFuture> pendingFuture = pendingFutures.removeFirst(); - try { - pendingFuture.get(config.getReadTimeoutMs(), TimeUnit.MILLISECONDS); - } catch (Exception e) { - log.warn("Timeout during waiting for reply!", e); - pendingFuture.cancel(true); - } - } catch (Exception e) { - log.warn("Failure during waiting for reply!", e); - } - } - } } private static void checkProxyHost(String proxyHost) throws TbNodeException { 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 d2356c69f7..8197315e6c 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 @@ -51,7 +51,7 @@ public class TbRestApiCallNode implements TbNode { @Override public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { TbRestApiCallNodeConfiguration config = TbNodeUtils.convert(configuration, TbRestApiCallNodeConfiguration.class); - httpClient = new TbHttpClient(config, ctx.getSharedEventLoop()); + httpClient = new TbHttpClient(config); useRedisQueueForMsgPersistence = config.isUseRedisQueueForMsgPersistence(); if (useRedisQueueForMsgPersistence) { log.warn("[{}][{}] Usage of Redis Template is deprecated starting 2.5 and will have no affect", ctx.getTenantId(), ctx.getSelfId()); @@ -63,11 +63,4 @@ public class TbRestApiCallNode implements TbNode { httpClient.processMessage(ctx, msg); } - @Override - public void destroy() { - if (this.httpClient != null) { - this.httpClient.destroy(); - } - } - } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/AttributesDeleteNodeCallback.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/AttributesDeleteNodeCallback.java index 200ab76263..a1c6b11659 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/AttributesDeleteNodeCallback.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/AttributesDeleteNodeCallback.java @@ -19,7 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.server.common.msg.TbMsg; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.List; @Slf4j diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/AttributesUpdateNodeCallback.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/AttributesUpdateNodeCallback.java index 3696812d87..6e94b85be5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/AttributesUpdateNodeCallback.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/AttributesUpdateNodeCallback.java @@ -19,7 +19,7 @@ import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.msg.TbMsg; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; import java.util.List; public class AttributesUpdateNodeCallback extends TelemetryNodeCallback { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TelemetryNodeCallback.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TelemetryNodeCallback.java index ce3e9d2455..9958ee106e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TelemetryNodeCallback.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TelemetryNodeCallback.java @@ -20,7 +20,7 @@ import lombok.Data; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.server.common.msg.TbMsg; -import javax.annotation.Nullable; +import jakarta.annotation.Nullable; /** * Created by ashvayka on 02.04.18. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java index 14ab6cfbbf..46e31d0f69 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java @@ -16,11 +16,8 @@ package org.thingsboard.rule.engine.rest; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; import org.assertj.core.api.Assertions; import org.awaitility.Awaitility; -import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -28,7 +25,6 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.mockserver.integration.ClientAndServer; import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.client.AsyncRestTemplate; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; @@ -41,9 +37,6 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willCallRealMethod; @@ -57,32 +50,11 @@ import static org.mockserver.model.HttpResponse.response; public class TbHttpClientTest { - EventLoopGroup eventLoop; TbHttpClient client; @Before public void setUp() throws Exception { client = mock(TbHttpClient.class); - willCallRealMethod().given(client).getSharedOrCreateEventLoopGroup(any()); - } - - @After - public void tearDown() throws Exception { - if (eventLoop != null) { - eventLoop.shutdownGracefully(); - } - } - - @Test - public void givenSharedEventLoop_whenGetEventLoop_ThenReturnShared() { - eventLoop = mock(EventLoopGroup.class); - assertThat(client.getSharedOrCreateEventLoopGroup(eventLoop), is(eventLoop)); - } - - @Test - public void givenNull_whenGetEventLoop_ThenReturnShared() { - eventLoop = client.getSharedOrCreateEventLoopGroup(null); - assertThat(eventLoop, instanceOf(NioEventLoopGroup.class)); } @Test @@ -139,10 +111,7 @@ public class TbHttpClientTest { config.setRestEndpointUrlPattern(endpointUrl); config.setUseSimpleClientHttpFactory(true); - var asyncRestTemplate = new AsyncRestTemplate(); - - var httpClient = new TbHttpClient(config, eventLoop); - httpClient.setHttpClient(asyncRestTemplate); + var httpClient = new TbHttpClient(config); var msg = TbMsg.newMsg("GET", new DeviceId(EntityId.NULL_UUID), TbMsgMetaData.EMPTY, "{}"); var successMsg = TbMsg.newMsg( diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java index 9185a31118..2b6698d415 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java @@ -16,7 +16,6 @@ package org.thingsboard.rule.engine.rest; import com.datastax.oss.driver.api.core.uuid.Uuids; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; @@ -49,14 +48,13 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; @RunWith(MockitoJUnitRunner.class) public class TbRestApiCallNodeTest { - + private TbRestApiCallNode restNode; @Mock @@ -68,17 +66,17 @@ public class TbRestApiCallNodeTest { private RuleChainId ruleChainId = new RuleChainId(Uuids.timeBased()); private RuleNodeId ruleNodeId = new RuleNodeId(Uuids.timeBased()); - private HttpServer server; + private HttpServer server; public void setupServer(String pattern, HttpRequestHandler handler) throws IOException { - SocketConfig config = SocketConfig.custom().setSoReuseAddress(true).setTcpNoDelay(true).build(); - server = ServerBootstrap.bootstrap() + SocketConfig config = SocketConfig.custom().setSoReuseAddress(true).setTcpNoDelay(true).build(); + server = ServerBootstrap.bootstrap() .setSocketConfig(config) - .registerHandler(pattern, handler) - .create(); + .registerHandler(pattern, handler) + .create(); server.start(); } - + private void initWithConfig(TbRestApiCallNodeConfiguration config) { try { TbNodeConfiguration nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); @@ -93,19 +91,18 @@ public class TbRestApiCallNodeTest { public void teardown() { server.stop(); } - + @Test public void deleteRequestWithoutBody() throws IOException, InterruptedException { final CountDownLatch latch = new CountDownLatch(1); final String path = "/path/to/delete"; - setupServer("*", new HttpRequestHandler() { - - @Override - public void handle(HttpRequest request, HttpResponse response, HttpContext context) - throws HttpException, IOException { + setupServer("*", new HttpRequestHandler() { + + @Override + public void handle(HttpRequest request, HttpResponse response, HttpContext context) + throws HttpException, IOException { try { assertEquals("Request path matches", request.getRequestLine().getUri(), path); - assertFalse("Content-Type not included", request.containsHeader("Content-Type")); assertTrue("Custom header included", request.containsHeader("Foo")); assertEquals("Custom header value", "Bar", request.getFirstHeader("Foo").getValue()); response.setStatusCode(200); @@ -121,13 +118,13 @@ public class TbRestApiCallNodeTest { } } }).start(); - } catch ( Exception e ) { + } catch (Exception e) { System.out.println("Exception handling request: " + e.toString()); e.printStackTrace(); latch.countDown(); } } - }); + }); TbRestApiCallNodeConfiguration config = new TbRestApiCallNodeConfiguration().defaultConfiguration(); config.setRequestMethod("DELETE"); @@ -136,7 +133,7 @@ public class TbRestApiCallNodeTest { config.setRestEndpointUrlPattern(String.format("http://localhost:%d%s", server.getLocalPort(), path)); initWithConfig(config); - TbMsg msg = TbMsg.newMsg( "USER", originator, metaData, TbMsgDataType.JSON, "{}", ruleChainId, ruleNodeId); + TbMsg msg = TbMsg.newMsg("USER", originator, metaData, TbMsgDataType.JSON, "{}", ruleChainId, ruleNodeId); restNode.onMsg(ctx, msg); assertTrue("Server handled request", latch.await(10, TimeUnit.SECONDS)); @@ -167,7 +164,7 @@ public class TbRestApiCallNodeTest { try { assertEquals("Request path matches", path, request.getRequestLine().getUri()); assertTrue("Content-Type included", request.containsHeader("Content-Type")); - assertEquals("Content-Type value", "text/plain;charset=ISO-8859-1", + assertEquals("Content-Type value", "text/plain;charset=UTF-8", request.getFirstHeader("Content-Type").getValue()); assertTrue("Content-Length included", request.containsHeader("Content-Length")); assertEquals("Content-Length value", "2", @@ -187,7 +184,7 @@ public class TbRestApiCallNodeTest { } } }).start(); - } catch ( Exception e ) { + } catch (Exception e) { System.out.println("Exception handling request: " + e.toString()); e.printStackTrace(); latch.countDown(); @@ -202,7 +199,7 @@ public class TbRestApiCallNodeTest { config.setRestEndpointUrlPattern(String.format("http://localhost:%d%s", server.getLocalPort(), path)); initWithConfig(config); - TbMsg msg = TbMsg.newMsg( "USER", originator, metaData, TbMsgDataType.JSON, "{}", ruleChainId, ruleNodeId); + TbMsg msg = TbMsg.newMsg("USER", originator, metaData, TbMsgDataType.JSON, "{}", ruleChainId, ruleNodeId); restNode.onMsg(ctx, msg); assertTrue("Server handled request", latch.await(10, TimeUnit.SECONDS)); @@ -213,7 +210,7 @@ public class TbRestApiCallNodeTest { ArgumentCaptor metadataCaptor = ArgumentCaptor.forClass(TbMsgMetaData.class); ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(String.class); verify(ctx).transformMsg(msgCaptor.capture(), typeCaptor.capture(), originatorCaptor.capture(), metadataCaptor.capture(), dataCaptor.capture()); - + assertEquals("USER", typeCaptor.getValue()); assertEquals(originator, originatorCaptor.getValue()); assertNotSame(metaData, metadataCaptor.getValue()); From ae2fd08c36d4d335da2969b105b0a442b87e8be8 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Mon, 13 Mar 2023 22:32:44 +0100 Subject: [PATCH 015/397] refactored HttpClient proxy --- .../rule/engine/rest/TbHttpClient.java | 122 +++++++++++++++--- 1 file changed, 102 insertions(+), 20 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index 28deb5b4da..7a5ca407af 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.rest; import io.netty.handler.ssl.SslContext; +import io.netty.handler.timeout.ReadTimeoutHandler; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; @@ -48,6 +49,7 @@ import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @@ -63,6 +65,19 @@ public class TbHttpClient { private static final String ERROR_BODY = "error_body"; private static final String ERROR_SYSTEM_PROPERTIES = "Didn't set any system proxy properties. Should be added next system proxy properties: \"http.proxyHost\" and \"http.proxyPort\" or \"https.proxyHost\" and \"https.proxyPort\" or \"socksProxyHost\" and \"socksProxyPort\""; + private static final String HTTP_PROXY_HOST = "http.proxyHost"; + private static final String HTTP_PROXY_PORT = "http.proxyPort"; + private static final String HTTPS_PROXY_HOST = "https.proxyHost"; + private static final String HTTPS_PROXY_PORT = "https.proxyPort"; + + private static final String SOCKS_PROXY_HOST = "socksProxyHost"; + private static final String SOCKS_PROXY_PORT = "socksProxyPort"; + private static final String SOCKS_VERSION = "socksProxyVersion"; + private static final String SOCKS_VERSION_5 = "5"; + private static final String SOCKS_VERSION_4 = "4"; + public static final String PROXY_USER = "tb.proxy.user"; + public static final String PROXY_PASSWORD = "tb.proxy.password"; + private final TbRestApiCallNodeConfiguration config; private WebClient webClient; @@ -75,29 +90,29 @@ public class TbHttpClient { semaphore = new Semaphore(config.getMaxParallelRequestsCount()); } - HttpClient httpClient = HttpClient.create(); + HttpClient httpClient = HttpClient.create() + .doOnConnected(c -> + c.addHandlerLast(new ReadTimeoutHandler(config.getReadTimeoutMs(), TimeUnit.MILLISECONDS))); if (config.isEnableProxy()) { - checkProxyHost(config.getProxyHost()); - checkProxyPort(config.getProxyPort()); - if (config.isUseSystemProxyProperties()) { checkSystemProxyProperties(); - //TODO: maybe we should replace it and manually get all system props - httpClient = httpClient.proxyWithSystemProperties(); + httpClient = httpClient.proxy(this::createSystemProxyProvider); } else { checkProxyHost(config.getProxyHost()); checkProxyPort(config.getProxyPort()); - String proxyUser = config.getProxyUser(); String proxyPassword = config.getProxyPassword(); - httpClient = httpClient.proxy(options -> - options.type(ProxyProvider.Proxy.HTTP) - .host(config.getProxyHost()) - .port(config.getProxyPort()) - .username(proxyUser) - .password(u -> proxyPassword)); + httpClient = httpClient.proxy(options -> { + var o = options.type(ProxyProvider.Proxy.HTTP) + .host(config.getProxyHost()) + .port(config.getProxyPort()); + + if (useAuth(proxyUser, proxyPassword)) { + o.username(proxyUser).password(u -> proxyPassword); + } + }); } } else if (!config.isUseSimpleClientHttpFactory()) { if (CredentialsType.CERT_PEM == config.getCredentials().getType()) { @@ -135,8 +150,9 @@ public class TbHttpClient { public void processMessage(TbContext ctx, TbMsg msg) { try { - if (semaphore != null) { - semaphore.tryAcquire(config.getReadTimeoutMs(), TimeUnit.MILLISECONDS); + if (semaphore != null && !semaphore.tryAcquire(config.getReadTimeoutMs(), TimeUnit.MILLISECONDS)) { + ctx.tellFailure(msg, new RuntimeException("Timeout during waiting for reply!")); + return; } String endpointUrl = TbNodeUtils.processPattern(config.getRestEndpointUrlPattern(), msg); @@ -171,7 +187,7 @@ public class TbHttpClient { } }, throwable -> { if (semaphore != null) { - semaphore.release(); // Make sure to release in case of error + semaphore.release(); } TbMsg next = processException(ctx, msg, throwable); @@ -276,15 +292,81 @@ public class TbHttpClient { } } - private static void checkProxyHost(String proxyHost) throws TbNodeException { + private static void checkProxyHost(String proxyHost) { if (StringUtils.isEmpty(proxyHost)) { - throw new TbNodeException("Proxy host can't be empty"); + throw new IllegalArgumentException("Proxy host can't be empty"); } } - private static void checkProxyPort(int proxyPort) throws TbNodeException { + private static void checkProxyPort(int proxyPort) { if (proxyPort < 0 || proxyPort > 65535) { - throw new TbNodeException("Proxy port out of range:" + proxyPort); + throw new IllegalArgumentException("Proxy port out of range:" + proxyPort); + } + } + + private void createSystemProxyProvider(ProxyProvider.TypeSpec option) { + Properties properties = System.getProperties(); + if (properties.containsKey(HTTP_PROXY_HOST) || properties.containsKey(HTTPS_PROXY_HOST)) { + createHttpProxyFrom(option, properties); + } + if (properties.containsKey(SOCKS_PROXY_HOST)) { + createSocksProxyFrom(option, properties); + } + } + + private void createHttpProxyFrom(ProxyProvider.TypeSpec option, Properties properties) { + String hostProperty; + String portProperty; + if (properties.containsKey(HTTPS_PROXY_HOST)) { + hostProperty = HTTPS_PROXY_HOST; + portProperty = HTTPS_PROXY_PORT; + } else { + hostProperty = HTTP_PROXY_HOST; + portProperty = HTTP_PROXY_PORT; + } + + String hostname = properties.getProperty(hostProperty); + int port = Integer.parseInt(properties.getProperty(portProperty)); + + checkProxyHost(config.getProxyHost()); + checkProxyPort(config.getProxyPort()); + + var proxy = option + .type(ProxyProvider.Proxy.HTTP) + .host(hostname) + .port(port); + + var proxyUser = properties.getProperty(PROXY_USER); + var proxyPassword = properties.getProperty(PROXY_PASSWORD); + + if (useAuth(proxyUser, proxyPassword)) { + proxy.username(proxyUser).password(u -> proxyPassword); + } + } + + private void createSocksProxyFrom(ProxyProvider.TypeSpec option, Properties properties) { + String hostname = properties.getProperty(SOCKS_PROXY_HOST); + String version = properties.getProperty(SOCKS_VERSION, SOCKS_VERSION_5); + if (!SOCKS_VERSION_5.equals(version) && !SOCKS_VERSION_4.equals(version)) { + throw new IllegalArgumentException(String.format("Wrong socks version %s! Supported only socks versions 4 and 5.", version)); + } + + ProxyProvider.Proxy type = SOCKS_VERSION_5.equals(version) ? ProxyProvider.Proxy.SOCKS5 : ProxyProvider.Proxy.SOCKS4; + int port = Integer.parseInt(properties.getProperty(SOCKS_PROXY_PORT)); + + checkProxyHost(config.getProxyHost()); + checkProxyPort(config.getProxyPort()); + + ProxyProvider.Builder proxy = option + .type(type) + .host(hostname) + .port(port); + + var proxyUser = properties.getProperty(PROXY_USER); + var proxyPassword = properties.getProperty(PROXY_PASSWORD); + + if (useAuth(proxyUser, proxyPassword)) { + proxy.username(proxyUser).password(u -> proxyPassword); } } From fa7fcda2c79424fedf82f394a5d248b493ae6351 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Mon, 12 Jun 2023 14:20:27 +0300 Subject: [PATCH 016/397] Fix merge issues --- .../channels/MobileNotificationChannel.java | 67 +++++++++---------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileNotificationChannel.java index 75ff7866ab..fe515f2218 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileNotificationChannel.java @@ -17,8 +17,6 @@ package org.thingsboard.server.service.notification.channels; import com.fasterxml.jackson.databind.JsonNode; import com.google.auth.oauth2.GoogleCredentials; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; import com.google.firebase.messaging.FirebaseMessaging; @@ -35,7 +33,6 @@ import org.thingsboard.server.common.data.notification.settings.MobileNotificati import org.thingsboard.server.common.data.notification.settings.NotificationSettings; import org.thingsboard.server.common.data.notification.template.MobileDeliveryMethodNotificationTemplate; import org.thingsboard.server.dao.notification.NotificationSettingsService; -import org.thingsboard.server.service.executors.ExternalCallExecutorService; import org.thingsboard.server.service.notification.NotificationProcessingContext; import java.nio.charset.StandardCharsets; @@ -45,52 +42,48 @@ import java.util.Optional; @RequiredArgsConstructor public class MobileNotificationChannel implements NotificationChannel { - private final ExternalCallExecutorService executor; private final NotificationSettingsService notificationSettingsService; @Override - public ListenableFuture sendNotification(User recipient, MobileDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) { + public void sendNotification(User recipient, MobileDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) throws Exception { String fcmToken = Optional.ofNullable(recipient.getAdditionalInfo()) .map(info -> info.get("fcmToken")).filter(JsonNode::isTextual).map(JsonNode::asText) .orElse(null); if (StringUtils.isEmpty(fcmToken)) { - return Futures.immediateFailedFuture(new RuntimeException("User doesn't have the mobile app installed")); + throw new RuntimeException("User doesn't have the mobile app installed"); } MobileNotificationDeliveryMethodConfig config = ctx.getDeliveryMethodConfig(NotificationDeliveryMethod.MOBILE); - return executor.submit(() -> { - FirebaseOptions firebaseOptions = FirebaseOptions.builder() - .setCredentials(GoogleCredentials.fromStream(IOUtils.toInputStream(config.getFirebaseServiceAccountCredentials(), StandardCharsets.UTF_8))) - .build(); - String appName = ctx.getTenantId().toString(); + FirebaseOptions firebaseOptions = FirebaseOptions.builder() + .setCredentials(GoogleCredentials.fromStream(IOUtils.toInputStream(config.getFirebaseServiceAccountCredentials(), StandardCharsets.UTF_8))) + .build(); + String appName = ctx.getTenantId().toString(); - FirebaseApp firebaseApp = FirebaseApp.getApps().stream() - .filter(app -> app.getName().equals(appName)) - .findFirst().orElseGet(() -> { - try { - return FirebaseApp.initializeApp(firebaseOptions, appName); - } catch (IllegalStateException e) { - return FirebaseApp.getInstance(appName); - } - }); - FirebaseMessaging firebaseMessaging; - try { - firebaseMessaging = FirebaseMessaging.getInstance(firebaseApp); - } catch (IllegalArgumentException e) { - // because of concurrency issues: FirebaseMessaging.getInstance lazily loads FirebaseMessagingService - firebaseMessaging = FirebaseMessaging.getInstance(firebaseApp); - } + FirebaseApp firebaseApp = FirebaseApp.getApps().stream() + .filter(app -> app.getName().equals(appName)) + .findFirst().orElseGet(() -> { + try { + return FirebaseApp.initializeApp(firebaseOptions, appName); + } catch (IllegalStateException e) { + return FirebaseApp.getInstance(appName); + } + }); + FirebaseMessaging firebaseMessaging; + try { + firebaseMessaging = FirebaseMessaging.getInstance(firebaseApp); + } catch (IllegalArgumentException e) { + // because of concurrency issues: FirebaseMessaging.getInstance lazily loads FirebaseMessagingService + firebaseMessaging = FirebaseMessaging.getInstance(firebaseApp); + } - Message message = Message.builder() - .setNotification(Notification.builder() - .setTitle(processedTemplate.getSubject()) - .setBody(processedTemplate.getBody()) - .build()) - .setToken(fcmToken) - .build(); - firebaseMessaging.send(message); - return null; - }); + Message message = Message.builder() + .setNotification(Notification.builder() + .setTitle(processedTemplate.getSubject()) + .setBody(processedTemplate.getBody()) + .build()) + .setToken(fcmToken) + .build(); + firebaseMessaging.send(message); } @Override From ce87bc5e13bf883d5f9e2001244000736bd51249 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Mon, 12 Jun 2023 13:25:37 +0200 Subject: [PATCH 017/397] to springdoc migration --- application/pom.xml | 4 +- .../server/ThingsboardInstallApplication.java | 3 +- .../server/config/SwaggerConfiguration.java | 506 +++++++----------- .../config/annotations/ApiOperation.java | 45 ++ .../controller/AbstractRpcController.java | 2 +- .../server/controller/AdminController.java | 24 +- .../controller/AlarmCommentController.java | 31 +- .../server/controller/AlarmController.java | 159 +++--- .../server/controller/AssetController.java | 147 ++--- .../controller/AssetProfileController.java | 57 +- .../server/controller/AuditLogController.java | 89 +-- .../server/controller/AuthController.java | 20 +- .../server/controller/BaseController.java | 6 +- .../ComponentDescriptorController.java | 15 +- .../controller/ControllerConstants.java | 35 +- .../server/controller/CustomerController.java | 29 +- .../controller/DashboardController.java | 145 +++-- .../server/controller/DeviceController.java | 155 +++--- .../controller/DeviceProfileController.java | 69 ++- .../server/controller/EdgeController.java | 139 ++--- .../controller/EdgeEventController.java | 27 +- .../EntitiesVersionControlController.java | 70 +-- .../controller/EntityQueryController.java | 18 +- .../controller/EntityRelationController.java | 98 ++-- .../controller/EntityViewController.java | 94 ++-- .../server/controller/EventController.java | 89 +-- .../server/controller/Lwm2mController.java | 11 +- .../controller/NotificationController.java | 30 +- .../NotificationRuleController.java | 16 +- .../NotificationTargetController.java | 22 +- .../NotificationTemplateController.java | 20 +- .../OAuth2ConfigTemplateController.java | 6 +- .../server/controller/OAuth2Controller.java | 16 +- .../controller/OtaPackageController.java | 69 ++- .../server/controller/QueueController.java | 30 +- .../server/controller/RpcV1Controller.java | 12 +- .../server/controller/RpcV2Controller.java | 56 +- .../controller/RuleChainController.java | 76 +-- .../controller/SystemInfoController.java | 6 +- .../controller/TbResourceController.java | 59 +- .../controller/TelemetryController.java | 253 +++++---- .../server/controller/TenantController.java | 36 +- .../controller/TenantProfileController.java | 38 +- .../TwoFactorAuthConfigController.java | 11 +- .../controller/TwoFactorAuthController.java | 4 +- .../controller/UiSettingsController.java | 2 +- .../server/controller/UserController.java | 97 ++-- .../controller/WidgetTypeController.java | 28 +- .../controller/WidgetsBundleController.java | 23 +- .../controller/plugin/TbWebSocketHandler.java | 8 +- ...ThingsboardCredentialsExpiredResponse.java | 7 +- .../exception/ThingsboardErrorResponse.java | 17 +- .../security/auth/rest/LoginRequest.java | 9 +- .../security/auth/rest/LoginResponse.java | 9 +- .../security/model/ActivateUserRequest.java | 9 +- .../security/model/ChangePasswordRequest.java | 9 +- .../model/ResetPasswordEmailRequest.java | 7 +- .../security/model/ResetPasswordRequest.java | 9 +- .../service/telemetry/AttributeData.java | 11 +- .../server/service/telemetry/TsData.java | 9 +- ...ngfoxHandlerProviderBeanPostProcessor.java | 59 -- .../src/main/resources/thingsboard.yml | 8 +- common/data/pom.xml | 4 +- .../server/common/data/AdminSettings.java | 15 +- .../server/common/data/Customer.java | 31 +- .../server/common/data/Dashboard.java | 6 +- .../server/common/data/DashboardInfo.java | 23 +- .../server/common/data/Device.java | 29 +- .../server/common/data/DeviceInfo.java | 13 +- .../server/common/data/DeviceProfile.java | 41 +- .../server/common/data/DeviceProfileInfo.java | 12 +- .../server/common/data/EntityInfo.java | 9 +- .../server/common/data/EntityView.java | 24 +- .../server/common/data/EntityViewInfo.java | 6 +- .../server/common/data/EventInfo.java | 17 +- .../server/common/data/ExportableEntity.java | 4 +- .../server/common/data/HomeDashboard.java | 7 +- .../server/common/data/HomeDashboardInfo.java | 9 +- .../server/common/data/OtaPackage.java | 7 +- .../server/common/data/OtaPackageInfo.java | 37 +- .../SaveDeviceWithCredentialsRequest.java | 9 +- .../data/SaveOtaPackageInfoRequest.java | 7 +- .../server/common/data/ShortCustomerInfo.java | 11 +- .../server/common/data/SystemInfo.java | 6 +- .../server/common/data/SystemInfoData.java | 18 +- .../server/common/data/TbResource.java | 6 +- .../server/common/data/TbResourceInfo.java | 19 +- .../server/common/data/Tenant.java | 35 +- .../server/common/data/TenantInfo.java | 7 +- .../server/common/data/TenantProfile.java | 19 +- .../server/common/data/UpdateMessage.java | 17 +- .../thingsboard/server/common/data/User.java | 27 +- .../server/common/data/UserEmailInfo.java | 13 +- .../server/common/data/alarm/Alarm.java | 49 +- .../common/data/alarm/AlarmComment.java | 19 +- .../common/data/alarm/AlarmCommentInfo.java | 11 +- .../AlarmCreateOrUpdateActiveRequest.java | 20 +- .../server/common/data/alarm/AlarmInfo.java | 11 +- .../data/alarm/AlarmPropagationInfo.java | 10 +- .../common/data/alarm/AlarmUpdateRequest.java | 16 +- .../server/common/data/asset/Asset.java | 23 +- .../server/common/data/asset/AssetInfo.java | 11 +- .../common/data/asset/AssetProfile.java | 27 +- .../common/data/asset/AssetProfileInfo.java | 8 +- .../common/data/asset/AssetSearchQuery.java | 8 +- .../server/common/data/audit/AuditLog.java | 29 +- .../common/data/device/DeviceSearchQuery.java | 11 +- .../data/DefaultDeviceConfiguration.java | 4 +- .../data/device/data/DeviceConfiguration.java | 4 +- .../common/data/device/data/DeviceData.java | 9 +- .../data/DeviceTransportConfiguration.java | 4 +- .../data/device/profile/AlarmCondition.java | 9 +- .../device/profile/AlarmConditionFilter.java | 13 +- .../profile/AlarmConditionFilterKey.java | 9 +- .../common/data/device/profile/AlarmRule.java | 13 +- .../device/profile/DeviceProfileAlarm.java | 21 +- .../device/profile/DeviceProfileData.java | 13 +- .../bootstrap/LwM2MServerSecurityConfig.java | 43 +- .../LwM2MServerSecurityConfigDefault.java | 9 +- .../server/common/data/edge/Edge.java | 25 +- .../data/edge/EdgeInstallInstructions.java | 7 +- .../common/data/edge/EdgeSearchQuery.java | 8 +- .../entityview/EntityViewSearchQuery.java | 11 +- .../common/data/event/DebugEventFilter.java | 11 +- .../common/data/event/ErrorEventFilter.java | 11 +- .../server/common/data/event/EventFilter.java | 7 +- .../data/event/LifeCycleEventFilter.java | 13 +- .../data/event/RuleChainDebugEventFilter.java | 7 +- .../data/event/RuleNodeDebugEventFilter.java | 21 +- .../data/event/StatisticsEventFilter.java | 15 +- .../server/common/data/id/AlarmCommentId.java | 4 +- .../server/common/data/id/AlarmId.java | 7 +- .../common/data/id/ApiUsageStateId.java | 7 +- .../server/common/data/id/AssetId.java | 7 +- .../server/common/data/id/AssetProfileId.java | 4 +- .../server/common/data/id/CustomerId.java | 7 +- .../server/common/data/id/DashboardId.java | 7 +- .../server/common/data/id/DeviceId.java | 7 +- .../common/data/id/DeviceProfileId.java | 4 +- .../server/common/data/id/EdgeId.java | 4 +- .../server/common/data/id/EntityId.java | 9 +- .../server/common/data/id/EntityViewId.java | 4 +- .../server/common/data/id/OtaPackageId.java | 4 +- .../server/common/data/id/RpcId.java | 4 +- .../server/common/data/id/RuleChainId.java | 4 +- .../server/common/data/id/RuleNodeId.java | 4 +- .../server/common/data/id/TbResourceId.java | 4 +- .../server/common/data/id/TenantId.java | 4 +- .../common/data/id/TenantProfileId.java | 4 +- .../server/common/data/id/UUIDBased.java | 7 +- .../server/common/data/id/UserId.java | 4 +- .../server/common/data/id/WidgetTypeId.java | 4 +- .../common/data/id/WidgetsBundleId.java | 4 +- .../common/data/lwm2m/LwM2mInstance.java | 9 +- .../server/common/data/lwm2m/LwM2mObject.java | 17 +- .../data/lwm2m/LwM2mResourceObserve.java | 17 +- .../data/oauth2/OAuth2BasicMapperConfig.java | 21 +- .../common/data/oauth2/OAuth2ClientInfo.java | 11 +- .../OAuth2ClientRegistrationTemplate.java | 31 +- .../common/data/oauth2/OAuth2DomainInfo.java | 9 +- .../server/common/data/oauth2/OAuth2Info.java | 9 +- .../data/oauth2/OAuth2MapperConfig.java | 12 +- .../common/data/oauth2/OAuth2MobileInfo.java | 9 +- .../common/data/oauth2/OAuth2ParamsInfo.java | 11 +- .../data/oauth2/OAuth2RegistrationInfo.java | 33 +- .../data/objects/AttributesEntityView.java | 11 +- .../data/objects/TelemetryEntityView.java | 9 +- .../server/common/data/page/PageData.java | 13 +- .../data/plugin/ComponentDescriptor.java | 23 +- .../common/data/query/EntityCountQuery.java | 4 +- .../server/common/data/query/EntityKey.java | 4 +- .../server/common/data/query/KeyFilter.java | 4 +- .../common/data/relation/EntityRelation.java | 15 +- .../data/relation/EntityRelationInfo.java | 6 +- .../data/relation/EntityRelationsQuery.java | 9 +- .../relation/RelationEntityTypeFilter.java | 9 +- .../relation/RelationsSearchParameters.java | 17 +- .../server/common/data/rpc/Rpc.java | 23 +- .../rule/DefaultRuleChainCreateRequest.java | 7 +- .../common/data/rule/NodeConnectionInfo.java | 11 +- .../server/common/data/rule/RuleChain.java | 23 +- .../data/rule/RuleChainConnectionInfo.java | 13 +- .../common/data/rule/RuleChainData.java | 9 +- .../common/data/rule/RuleChainMetaData.java | 15 +- .../data/rule/RuleChainOutputLabelsUsage.java | 15 +- .../server/common/data/rule/RuleNode.java | 23 +- .../data/security/DeviceCredentials.java | 17 +- .../common/data/security/model/JwtPair.java | 9 +- .../data/security/model/JwtSettings.java | 13 +- .../data/security/model/SecuritySettings.java | 11 +- .../security/model/UserPasswordPolicy.java | 21 +- .../settings/AbstractUserDashboardInfo.java | 9 +- .../settings/LastVisitedDashboardInfo.java | 9 +- .../data/settings/StarredDashboardInfo.java | 7 +- .../data/settings/UserDashboardsInfo.java | 9 +- .../common/data/settings/UserSettings.java | 11 +- .../AwsSnsSmsProviderConfiguration.java | 11 +- .../config/SmppSmsProviderConfiguration.java | 34 +- .../data/sms/config/TestSmsRequest.java | 11 +- .../TwilioSmsProviderConfiguration.java | 11 +- .../tenant/profile/TenantProfileData.java | 9 +- .../common/data/widget/BaseWidgetType.java | 14 +- .../server/common/data/widget/WidgetType.java | 4 +- .../common/data/widget/WidgetTypeDetails.java | 6 +- .../common/data/widget/WidgetTypeInfo.java | 8 +- .../common/data/widget/WidgetsBundle.java | 21 +- .../transport/http/DeviceApiController.java | 133 ++--- pom.xml | 30 +- 208 files changed, 2462 insertions(+), 2712 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/config/annotations/ApiOperation.java delete mode 100644 application/src/main/java/org/thingsboard/server/springfox/SpringfoxHandlerProviderBeanPostProcessor.java diff --git a/application/pom.xml b/application/pom.xml index 1838c97c65..f473986211 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -262,8 +262,8 @@ opensmpp-core - org.thingsboard - springfox-boot-starter + org.springdoc + springdoc-openapi-starter-webmvc-ui com.sun.winsw diff --git a/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java b/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java index b780f0e8cd..5b80e21fe6 100644 --- a/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java +++ b/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java @@ -33,8 +33,7 @@ import java.util.Arrays; "org.thingsboard.server.dao", "org.thingsboard.server.common.stats", "org.thingsboard.server.common.transport.config.ssl", - "org.thingsboard.server.cache", - "org.thingsboard.server.springfox" + "org.thingsboard.server.cache" }) public class ThingsboardInstallApplication { diff --git a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java index c7616ed865..50104e866d 100644 --- a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java @@ -15,84 +15,58 @@ */ package org.thingsboard.server.config; -import com.fasterxml.classmate.TypeResolver; +import io.swagger.v3.core.converter.AnnotatedType; +import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.examples.Example; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.RequestBody; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.responses.ApiResponses; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.tags.Tag; import lombok.extern.slf4j.Slf4j; +import org.springdoc.core.customizers.OpenApiCustomizer; +import org.springdoc.core.models.GroupedOpenApi; +import org.springdoc.core.properties.SwaggerUiConfigProperties; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; -import org.springframework.core.annotation.Order; -import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; -import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.exception.ThingsboardCredentialsExpiredResponse; import org.thingsboard.server.exception.ThingsboardErrorResponse; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.rest.LoginRequest; import org.thingsboard.server.service.security.auth.rest.LoginResponse; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.ExampleBuilder; -import springfox.documentation.builders.OperationBuilder; -import springfox.documentation.builders.RepresentationBuilder; -import springfox.documentation.builders.RequestParameterBuilder; -import springfox.documentation.builders.ResponseBuilder; -import springfox.documentation.schema.Example; -import springfox.documentation.service.ApiDescription; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.ApiListing; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.Contact; -import springfox.documentation.service.HttpLoginPasswordScheme; -import springfox.documentation.service.ParameterType; -import springfox.documentation.service.Response; -import springfox.documentation.service.SecurityReference; -import springfox.documentation.service.SecurityScheme; -import springfox.documentation.service.Tag; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spi.service.ApiListingBuilderPlugin; -import springfox.documentation.spi.service.ApiListingScannerPlugin; -import springfox.documentation.spi.service.contexts.ApiListingContext; -import springfox.documentation.spi.service.contexts.DocumentationContext; -import springfox.documentation.spi.service.contexts.OperationContext; -import springfox.documentation.spi.service.contexts.SecurityContext; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.spring.web.readers.operation.CachingOperationNameGenerator; -import springfox.documentation.swagger.common.SwaggerPluginSupport; -import springfox.documentation.swagger.web.DocExpansion; -import springfox.documentation.swagger.web.ModelRendering; -import springfox.documentation.swagger.web.OperationsSorter; -import springfox.documentation.swagger.web.UiConfiguration; -import springfox.documentation.swagger.web.UiConfigurationBuilder; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; + import java.util.List; -import java.util.Set; -import java.util.function.Consumer; -import java.util.function.Predicate; +import java.util.Map; -import static com.google.common.collect.Lists.newArrayList; -import static java.util.function.Predicate.not; -import static springfox.documentation.builders.PathSelectors.any; -import static springfox.documentation.builders.PathSelectors.regex; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @Slf4j -//@Configuration +@Configuration @TbCoreComponent @Profile("!test") public class SwaggerConfiguration { - @Value("${swagger.enabled:true}") - private boolean enabled; - @Value("${swagger.api_path_regex}") - private String apiPathRegex; - @Value("${swagger.security_path_regex}") - private String securityPathRegex; + public static final String LOGIN_ENDPOINT = "/api/auth/login"; + + @Value("${swagger.api_path:/api/**}") + private String apiPath; @Value("${swagger.non_security_path_regex}") private String nonSecurityPathRegex; @Value("${swagger.title}") @@ -115,288 +89,206 @@ public class SwaggerConfiguration { private String appVersion; @Bean - public Docket thingsboardApi() { - TypeResolver typeResolver = new TypeResolver(); - return new Docket(DocumentationType.OAS_30) - .enable(enabled) - .groupName("thingsboard") - .apiInfo(apiInfo()) - .additionalModels( - typeResolver.resolve(ThingsboardErrorResponse.class), - typeResolver.resolve(ThingsboardCredentialsExpiredResponse.class), - typeResolver.resolve(LoginRequest.class), - typeResolver.resolve(LoginResponse.class) - ) - .select() - .paths(apiPaths()) - .paths(any()) - .build() - .globalResponses(HttpMethod.GET, - defaultErrorResponses(false) - ) - .globalResponses(HttpMethod.POST, - defaultErrorResponses(true) - ) - .globalResponses(HttpMethod.DELETE, - defaultErrorResponses(false) - ) - .securitySchemes(newArrayList(httpLogin())) - .securityContexts(newArrayList(securityContext())) - .ignoredParameterTypes(AuthenticationPrincipal.class) - .enableUrlTemplating(true); - } + public OpenAPI tbOpenAPI() { + Contact contact = new Contact() + .name(contactName) + .url(contactUrl) + .email(contactEmail); - @Bean - @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER) - ApiListingScannerPlugin loginEndpointListingScanner(final CachingOperationNameGenerator operationNames) { - return new ApiListingScannerPlugin() { - @Override - public List apply(DocumentationContext context) { - return List.of(loginEndpointApiDescription(operationNames)); - } - - @Override - public boolean supports(DocumentationType delimiter) { - return DocumentationType.SWAGGER_2.equals(delimiter) || DocumentationType.OAS_30.equals(delimiter); - } - }; - } + License license = new License() + .name(licenseTitle) + .url(licenseUrl); - @Bean - @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER) - ApiListingBuilderPlugin loginEndpointListingBuilder() { - return new ApiListingBuilderPlugin() { - @Override - public void apply(ApiListingContext apiListingContext) { - if (apiListingContext.getResourceGroup().getGroupName().equals("default")) { - ApiListing apiListing = apiListingContext.apiListingBuilder().build(); - if (apiListing.getResourcePath().equals("/api/auth/login")) { - apiListingContext.apiListingBuilder().tags(Set.of(new Tag("login-endpoint", "Login Endpoint"))); - apiListingContext.apiListingBuilder().description("Login Endpoint"); - } - } - } + String apiVersion = version; + if (StringUtils.isEmpty(apiVersion)) { + apiVersion = appVersion; + } - @Override - public boolean supports(DocumentationType delimiter) { - return DocumentationType.SWAGGER_2.equals(delimiter) || DocumentationType.OAS_30.equals(delimiter); - } - }; + Info info = new Info() + .title(title) + .description(description) + .contact(contact) + .license(license) + .version(apiVersion); + + SecurityScheme securityScheme = new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("basic") + .bearerFormat("JWT") + .in(SecurityScheme.In.HEADER) + .description("Enter Username / Password"); + + var openApi = new OpenAPI() + .components(new Components().addSecuritySchemes("HTTP login form", securityScheme)) + .info(info); + addLoginOperation(openApi); + return openApi; } - @Bean - UiConfiguration uiConfig() { - return UiConfigurationBuilder.builder() - .deepLinking(true) - .displayOperationId(false) - .defaultModelsExpandDepth(1) - .defaultModelExpandDepth(1) - .defaultModelRendering(ModelRendering.EXAMPLE) - .displayRequestDuration(false) - .docExpansion(DocExpansion.NONE) - .filter(false) - .maxDisplayedTags(null) - .operationsSorter(OperationsSorter.ALPHA) - .showExtensions(false) - .showCommonExtensions(false) - .supportedSubmitMethods(UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS) - .validatorUrl(null) - .persistAuthorization(true) - .syntaxHighlightActivate(true) - .syntaxHighlightTheme("agate") - .build(); + public void addLoginOperation(OpenAPI openAPI) { + openAPI.getComponents() + .addSchemas("LoginRequest", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginRequest.class)).schema) + .addSchemas("LoginResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginResponse.class)).schema) + .addSchemas("ThingsboardErrorResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardErrorResponse.class)).schema) + .addSchemas("ThingsboardCredentialsExpiredResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardCredentialsExpiredResponse.class)).schema); + + var operation = new Operation(); + operation.summary("Login method to get user JWT token data"); + operation.description("Login method used to authenticate user and get JWT token data.\n\nValue of the response **token** " + + "field can be used as **X-Authorization** header value:\n\n`X-Authorization: Bearer $JWT_TOKEN_VALUE`."); + var requestBody = new RequestBody().content(new Content().addMediaType(APPLICATION_JSON_VALUE, + new MediaType().schema(new Schema().$ref("#/components/schemas/LoginRequest")))); + operation.requestBody(requestBody); + operation.responses(getResponses()); + operation.addTagsItem("login-endpoint"); + var pathItem = new PathItem().post(operation); + openAPI.path(LOGIN_ENDPOINT, pathItem); } - private SecurityScheme httpLogin() { - return HttpLoginPasswordScheme - .X_AUTHORIZATION_BUILDER - .loginEndpoint("/api/auth/login") - .name("HTTP login form") - .description("Enter Username / Password") - .build(); - } + private ApiResponses getResponses() { + ApiResponses apiResponses = new ApiResponses(); + + apiResponses.addApiResponse("200", new ApiResponse().description("OK") + .content(new Content().addMediaType(APPLICATION_JSON_VALUE, + new MediaType().schema(new Schema().$ref("#/components/schemas/LoginResponse"))))); + + ApiResponse unauthorizedResponse = new ApiResponse().description("Unauthorized"); + Content content = new Content(); + MediaType mediaType = new MediaType().schema(new Schema().$ref("#/components/schemas/ThingsboardErrorResponse")); + + Map examples = Map.of( + "bad-credentials", errorExample("Bad credentials", + ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), + "token-expired", errorExample("JWT token expired", + ThingsboardErrorResponse.of("Token has expired", ThingsboardErrorCode.JWT_TOKEN_EXPIRED, HttpStatus.UNAUTHORIZED)), + "account-disabled", errorExample("Disabled account", + ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), + "account-locked", errorExample("Locked account", + ThingsboardErrorResponse.of("User account is locked due to security policy", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), + "authentication-failed", errorExample("General authentication error", + ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)) + ); - private SecurityContext securityContext() { - return SecurityContext.builder() - .securityReferences(defaultAuth()) - .operationSelector(securityPathOperationSelector()) - .build(); + mediaType.setExamples(examples); + content.addMediaType(APPLICATION_JSON_VALUE, mediaType); + unauthorizedResponse.setContent(content); + apiResponses.addApiResponse("401", unauthorizedResponse); + + ApiResponse expiredCredentialsResponse = new ApiResponse().description("Unauthorized (**Expired credentials**)"); + Content expiredContent = new Content(); + MediaType expiredMediaType = new MediaType().schema(new Schema().$ref("#/components/schemas/ThingsboardCredentialsExpiredResponse")); + expiredMediaType.addExamples("credentials-expired", errorExample("Expired credentials", + ThingsboardCredentialsExpiredResponse.of("User password expired!", StringUtils.randomAlphanumeric(30)))); + expiredContent.addMediaType(APPLICATION_JSON_VALUE, expiredMediaType); + expiredCredentialsResponse.setContent(expiredContent); + apiResponses.addApiResponse("401 ", expiredCredentialsResponse); + + return apiResponses; } - private Predicate apiPaths() { - return regex(apiPathRegex); + private Example errorExample(String summary, ThingsboardErrorResponse example) { + return new Example() + .summary(summary) + .value(example); } - private Predicate securityPathOperationSelector() { - return new SecurityPathOperationSelector(securityPathRegex, nonSecurityPathRegex); + @Bean + public GroupedOpenApi thingsboardApi() { + return GroupedOpenApi.builder() + .group("thingsboard") + .pathsToMatch(apiPath) + .addOpenApiCustomizer(customOpenApiCustomizer()) + .build(); } - List defaultAuth() { - AuthorizationScope[] authorizationScopes = new AuthorizationScope[3]; - authorizationScopes[0] = new AuthorizationScope(Authority.SYS_ADMIN.name(), "System administrator"); - authorizationScopes[1] = new AuthorizationScope(Authority.TENANT_ADMIN.name(), "Tenant administrator"); - authorizationScopes[2] = new AuthorizationScope(Authority.CUSTOMER_USER.name(), "Customer"); - return newArrayList( - new SecurityReference("HTTP login form", authorizationScopes)); + @Bean + @Primary + public SwaggerUiConfigProperties swaggerUiConfig(SwaggerUiConfigProperties uiProperties) { + uiProperties.setDeepLinking(true); + uiProperties.setDisplayOperationId(false); + uiProperties.setDefaultModelsExpandDepth(1); + uiProperties.setDefaultModelExpandDepth(1); + uiProperties.setDefaultModelRendering("example"); + uiProperties.setDisplayRequestDuration(false); + uiProperties.setDocExpansion("none"); + uiProperties.setFilter("false"); + uiProperties.setMaxDisplayedTags(null); + uiProperties.setOperationsSorter("alpha"); + uiProperties.setTagsSorter("alpha"); + uiProperties.setShowExtensions(false); + uiProperties.setShowCommonExtensions(false); + uiProperties.setSupportedSubmitMethods(List.of("get", "put", "post", "delete", "options", "head", "patch", "trace")); + uiProperties.setValidatorUrl(null); + uiProperties.setPersistAuthorization(true); + + var syntaxHighLight = new SwaggerUiConfigProperties.SyntaxHighlight(); + syntaxHighLight.setActivated(true); + syntaxHighLight.setTheme("agate"); + + uiProperties.setSyntaxHighlight(syntaxHighLight); + return uiProperties; } - private ApiInfo apiInfo() { - String apiVersion = version; - if (StringUtils.isEmpty(apiVersion)) { - apiVersion = appVersion; - } - return new ApiInfoBuilder() - .title(title) - .description(description) - .contact(new Contact(contactName, contactUrl, contactEmail)) - .license(licenseTitle) - .licenseUrl(licenseUrl) - .version(apiVersion) - .build(); - } + public OpenApiCustomizer customOpenApiCustomizer() { + SecurityRequirement loginForm = new SecurityRequirement().addList("HTTP login form"); - private ApiDescription loginEndpointApiDescription(final CachingOperationNameGenerator operationNames) { - return new ApiDescription(null, "/api/auth/login", "Login method to get user JWT token data", "Login endpoint", Collections.singletonList( - new OperationBuilder(operationNames) - .summary("Login method to get user JWT token data") - .tags(Set.of("login-endpoint")) - .authorizations(new ArrayList<>()) - .position(0) - .codegenMethodNameStem("loginPost") - .method(HttpMethod.POST) - .notes("Login method used to authenticate user and get JWT token data.\n\nValue of the response **token** " + - "field can be used as **X-Authorization** header value:\n\n`X-Authorization: Bearer $JWT_TOKEN_VALUE`.") - .requestParameters( - List.of( - new RequestParameterBuilder() - .in(ParameterType.BODY) - .required(true) - .description("Login request") - .content(c -> - c.requestBody(true) - .representation(MediaType.APPLICATION_JSON) - .apply(classRepresentation(LoginRequest.class, false)) - ) - .build() - ) - ) - .responses(loginResponses()) - .build() - ), false); - } + return openAPI -> openAPI.getPaths().entrySet().stream().peek(entry -> { + if (!(entry.getKey().matches(nonSecurityPathRegex) || entry.getKey().equals(LOGIN_ENDPOINT))) { + entry.getValue() + .readOperationsMap() + .values() + .forEach(operation -> operation.addSecurityItem(loginForm)); + } - private Collection loginResponses() { - List responses = new ArrayList<>(); - responses.add( - new ResponseBuilder() - .code("200") - .description("OK") - .representation(MediaType.APPLICATION_JSON) - .apply(classRepresentation(LoginResponse.class, true)). - build() - ); - responses.addAll(loginErrorResponses()); - return responses; - } + entry.getValue().readOperationsMap().forEach(((httpMethod, operation) -> { + operation.setResponses(getResponses(operation.getResponses(), httpMethod.equals(PathItem.HttpMethod.POST))); + })); - /** Helper methods **/ - - private List defaultErrorResponses(boolean isPost) { - return List.of( - errorResponse("400", "Bad Request", - ThingsboardErrorResponse.of(isPost ? "Invalid request body" : "Invalid UUID string: 123", ThingsboardErrorCode.BAD_REQUEST_PARAMS, HttpStatus.BAD_REQUEST)), - errorResponse("401", "Unauthorized", - ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), - errorResponse("403", "Forbidden", - ThingsboardErrorResponse.of("You don't have permission to perform this operation!", - ThingsboardErrorCode.PERMISSION_DENIED, HttpStatus.FORBIDDEN)), - errorResponse("404", "Not Found", - ThingsboardErrorResponse.of("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND)), - errorResponse("429", "Too Many Requests", - ThingsboardErrorResponse.of("Too many requests for current tenant!", - ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS)) - ); + }).map(entry -> { + String tagItem = entry.getValue().readOperationsMap().values().stream().findAny().get().getTags().get(0); + return tagFromTagItem(tagItem); + }).forEach(openAPI::addTagsItem); } - private List loginErrorResponses() { - return List.of( - errorResponse("401", "Unauthorized", - List.of( - errorExample("bad-credentials", "Bad credentials", - ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), - errorExample("token-expired", "JWT token expired", - ThingsboardErrorResponse.of("Token has expired", ThingsboardErrorCode.JWT_TOKEN_EXPIRED, HttpStatus.UNAUTHORIZED)), - errorExample("account-disabled", "Disabled account", - ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), - errorExample("account-locked", "Locked account", - ThingsboardErrorResponse.of("User account is locked due to security policy", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), - errorExample("authentication-failed", "General authentication error", - ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)) - ) - ), - errorResponse("401 ", "Unauthorized (**Expired credentials**)", - List.of( - errorExample("credentials-expired", "Expired credentials", - ThingsboardCredentialsExpiredResponse.of("User password expired!", StringUtils.randomAlphanumeric(30))) - ), ThingsboardCredentialsExpiredResponse.class - ) - ); - } + private Tag tagFromTagItem(String tagItem) { + String[] words = tagItem.split("-"); + StringBuilder sb = new StringBuilder(); - private Response errorResponse(String code, String description, ThingsboardErrorResponse example) { - return errorResponse(code, description, List.of(errorExample("error-code-" + code, description, example))); - } + for (String word : words) { + sb.append(word.substring(0, 1).toUpperCase()); + sb.append(word.substring(1).toLowerCase()); + sb.append(" "); + } - private Response errorResponse(String code, String description, List examples) { - return errorResponse(code, description, examples, ThingsboardErrorResponse.class); + return new Tag().name(tagItem).description(sb.toString().trim()); } - private Response errorResponse(String code, String description, List examples, - Class errorResponseClass) { - return new ResponseBuilder() - .code(code) - .description(description) - .examples(examples) - .representation(MediaType.APPLICATION_JSON) - .apply(classRepresentation(errorResponseClass, true)) - .build(); - } + private ApiResponses getResponses(ApiResponses apiResponses, boolean isPost) { + if (apiResponses == null) { + apiResponses = new ApiResponses(); + } - private Example errorExample(String id, String summary, ThingsboardErrorResponse example) { - return new ExampleBuilder() - .mediaType(MediaType.APPLICATION_JSON_VALUE) - .summary(summary) - .id(id) - .value(example).build(); - } + apiResponses.addApiResponse("400", new ApiResponse().description("Bad Request") + .content(getErrorContent(ThingsboardErrorResponse.of(isPost ? "Invalid request body" : "Invalid UUID string: 123", ThingsboardErrorCode.BAD_REQUEST_PARAMS, HttpStatus.BAD_REQUEST)))); - private Consumer classRepresentation(Class clazz, boolean isResponse) { - return r -> r.model( - m -> - m.referenceModel(ref -> - ref.key(k -> - k.qualifiedModelName(q -> - q.namespace(clazz.getPackageName()) - .name(clazz.getSimpleName())).isResponse(isResponse))) - ); - } + apiResponses.addApiResponse("401", new ApiResponse().description("Unauthorized") + .content(getErrorContent(ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)))); - private static class SecurityPathOperationSelector implements Predicate { + apiResponses.addApiResponse("403", new ApiResponse().description("Forbidden") + .content(getErrorContent(ThingsboardErrorResponse.of("You don't have permission to perform this operation!", ThingsboardErrorCode.PERMISSION_DENIED, HttpStatus.FORBIDDEN)))); - private final Predicate securityPathSelector; + apiResponses.addApiResponse("404", new ApiResponse().description("Not Found") + .content(getErrorContent(ThingsboardErrorResponse.of("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND)))); - SecurityPathOperationSelector(String securityPathRegex, String nonSecurityPathRegex) { - this.securityPathSelector = regex(securityPathRegex).and( - not( - regex(nonSecurityPathRegex) - )); - } + apiResponses.addApiResponse("429", new ApiResponse().description("Too Many Requests") + .content(getErrorContent(ThingsboardErrorResponse.of("Too many requests for current tenant!", ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS)))); - @Override - public boolean test(OperationContext operationContext) { - return this.securityPathSelector.test(operationContext.requestMappingPattern()); - } + return apiResponses; } + private Content getErrorContent(ThingsboardErrorResponse errorResponse) { + return new Content().addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, + new MediaType().schema(new Schema().example(errorResponse))); + } } diff --git a/application/src/main/java/org/thingsboard/server/config/annotations/ApiOperation.java b/application/src/main/java/org/thingsboard/server/config/annotations/ApiOperation.java new file mode 100644 index 0000000000..d8710149a6 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/config/annotations/ApiOperation.java @@ -0,0 +1,45 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.config.annotations; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import org.springframework.core.annotation.AliasFor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Operation +public @interface ApiOperation { + + @AliasFor(annotation = Operation.class, attribute = "summary") + String value(); + + @AliasFor(annotation = Operation.class, attribute = "description") + String notes() default ""; + + boolean hidden() default false; + + RequestBody requestBody() default @RequestBody; + + ApiResponse[] responses() default {}; + +} diff --git a/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java b/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java index 5f33eb951e..faef8edd4a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java @@ -17,6 +17,7 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; import com.google.common.util.concurrent.FutureCallback; +import jakarta.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -45,7 +46,6 @@ import org.thingsboard.server.service.security.AccessValidator; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; -import jakarta.annotation.Nullable; import java.util.Optional; import java.util.UUID; diff --git a/application/src/main/java/org/thingsboard/server/controller/AdminController.java b/application/src/main/java/org/thingsboard/server/controller/AdminController.java index 5cf97a7cda..12c5abf47d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AdminController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AdminController.java @@ -19,8 +19,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; @@ -53,6 +54,7 @@ import org.thingsboard.server.common.data.sync.vc.AutoCommitSettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettings; import org.thingsboard.server.common.data.sync.vc.RepositorySettingsInfo; import org.thingsboard.server.common.data.sync.vc.VcUtils; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.audit.AuditLogService; import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -96,7 +98,7 @@ public class AdminController extends BaseController { @RequestMapping(value = "/settings/{key}", method = RequestMethod.GET) @ResponseBody public AdminSettings getAdminSettings( - @ApiParam(value = "A string value of the key (e.g. 'general' or 'mail').") + @Parameter(description = "A string value of the key (e.g. 'general' or 'mail').") @PathVariable("key") String key) throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); AdminSettings adminSettings = checkNotNull(adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, key), "No Administration settings found for key: " + key); @@ -114,7 +116,7 @@ public class AdminController extends BaseController { @RequestMapping(value = "/settings", method = RequestMethod.POST) @ResponseBody public AdminSettings saveAdminSettings( - @ApiParam(value = "A JSON value representing the Administration Settings.") + @Parameter(description = "A JSON value representing the Administration Settings.") @RequestBody AdminSettings adminSettings) throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE); adminSettings.setTenantId(getTenantId()); @@ -144,7 +146,7 @@ public class AdminController extends BaseController { @RequestMapping(value = "/securitySettings", method = RequestMethod.POST) @ResponseBody public SecuritySettings saveSecuritySettings( - @ApiParam(value = "A JSON value representing the Security Settings.") + @Parameter(description = "A JSON value representing the Security Settings.") @RequestBody SecuritySettings securitySettings) throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE); securitySettings = checkNotNull(systemSecurityService.saveSecuritySettings(TenantId.SYS_TENANT_ID, securitySettings)); @@ -153,7 +155,7 @@ public class AdminController extends BaseController { @ApiOperation(value = "Get the JWT Settings object (getJwtSettings)", notes = "Get the JWT Settings object that contains JWT token policy, etc. " + SYSTEM_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/jwtSettings", method = RequestMethod.GET) @ResponseBody @@ -164,12 +166,12 @@ public class AdminController extends BaseController { @ApiOperation(value = "Update JWT Settings (saveJwtSettings)", notes = "Updates the JWT Settings object that contains JWT token policy, etc. The tokenSigningKey field is a Base64 encoded string." + SYSTEM_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/jwtSettings", method = RequestMethod.POST) @ResponseBody public JwtPair saveJwtSettings( - @ApiParam(value = "A JSON value representing the JWT Settings.") + @Parameter(description = "A JSON value representing the JWT Settings.") @RequestBody JwtSettings jwtSettings) throws ThingsboardException { SecurityUser securityUser = getCurrentUser(); accessControlService.checkPermission(securityUser, Resource.ADMIN_SETTINGS, Operation.WRITE); @@ -183,7 +185,7 @@ public class AdminController extends BaseController { @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/settings/testMail", method = RequestMethod.POST) public void sendTestMail( - @ApiParam(value = "A JSON value representing the Mail Settings.") + @Parameter(description = "A JSON value representing the Mail Settings.") @RequestBody AdminSettings adminSettings) throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); adminSettings = checkNotNull(adminSettings); @@ -203,7 +205,7 @@ public class AdminController extends BaseController { @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/settings/testSms", method = RequestMethod.POST) public void sendTestSms( - @ApiParam(value = "A JSON value representing the Test SMS request.") + @Parameter(description = "A JSON value representing the Test SMS request.") @RequestBody TestSmsRequest testSmsRequest) throws ThingsboardException { SecurityUser user = getCurrentUser(); accessControlService.checkPermission(user, Resource.ADMIN_SETTINGS, Operation.READ); @@ -286,7 +288,7 @@ public class AdminController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/repositorySettings/checkAccess", method = RequestMethod.POST) public DeferredResult checkRepositoryAccess( - @ApiParam(value = "A JSON value representing the Repository Settings.") + @Parameter(description = "A JSON value representing the Repository Settings.") @RequestBody RepositorySettings settings) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); settings = checkNotNull(settings); diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index 92b2cb923f..529b1fe48a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; @@ -35,17 +37,16 @@ import org.thingsboard.server.common.data.id.AlarmCommentId; import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.alarm.TbAlarmCommentService; import org.thingsboard.server.service.security.permission.Operation; import static org.thingsboard.server.controller.ControllerConstants.ALARM_COMMENT_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.ALARM_COMMENT_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH; @@ -69,12 +70,12 @@ public class AlarmCommentController extends BaseController { "\n\n To create new Alarm comment entity it is enough to specify 'comment' json element with 'text' node, for example: {\"comment\": { \"text\": \"my comment\"}}. " + "\n\n If comment type is not specified the default value 'OTHER' will be saved. If 'alarmId' or 'userId' specified in body it will be ignored." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH - , produces = MediaType.APPLICATION_JSON_VALUE) + , responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.POST) @ResponseBody - public AlarmComment saveAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) - @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = "A JSON value representing the comment.") @RequestBody AlarmComment alarmComment) throws ThingsboardException { + public AlarmComment saveAlarmComment(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) + @PathVariable(ALARM_ID) String strAlarmId, @Parameter(description = "A JSON value representing the comment.") @RequestBody AlarmComment alarmComment) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); @@ -83,11 +84,11 @@ public class AlarmCommentController extends BaseController { } @ApiOperation(value = "Delete Alarm comment (deleteAlarmComment)", - notes = "Deletes the Alarm comment. Referencing non-existing Alarm comment Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + notes = "Deletes the Alarm comment. Referencing non-existing Alarm comment Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment/{commentId}", method = RequestMethod.DELETE) @ResponseBody - public void deleteAlarmComment(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @ApiParam(value = ALARM_COMMENT_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_COMMENT_ID) String strCommentId) throws ThingsboardException { + public void deleteAlarmComment(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, @Parameter(description = ALARM_COMMENT_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_COMMENT_ID) String strCommentId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); @@ -99,20 +100,20 @@ public class AlarmCommentController extends BaseController { @ApiOperation(value = "Get Alarm comments (getAlarmComments)", notes = "Returns a page of alarm comments for specified alarm. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.GET) @ResponseBody public PageData getAlarmComments( - @ApiParam(value = ALARM_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ALARM_ID_PARAM_DESCRIPTION, required = true) @PathVariable(ALARM_ID) String strAlarmId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ALARM_COMMENT_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "id"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder ) throws Exception { checkParameter(ALARM_ID, strAlarmId); diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index 44263d19bd..18ad89f1a0 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -45,6 +47,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.alarm.TbAlarmService; import org.thingsboard.server.service.security.permission.Operation; @@ -59,7 +62,6 @@ import java.util.concurrent.ExecutionException; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ALARM_INFO_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.ALARM_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.ASSIGNEE_ID; import static org.thingsboard.server.controller.ControllerConstants.ASSIGN_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID; @@ -69,7 +71,6 @@ import static org.thingsboard.server.controller.ControllerConstants.ENTITY_TYPE_ import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH; @@ -104,11 +105,11 @@ public class AlarmController extends BaseController { "filled in the AlarmInfo object field: 'originatorName' or will returns as null."; @ApiOperation(value = "Get Alarm (getAlarmById)", - notes = "Fetch the Alarm object based on the provided Alarm Id. " + ALARM_SECURITY_CHECK, produces = MediaType.APPLICATION_JSON_VALUE) + notes = "Fetch the Alarm object based on the provided Alarm Id. " + ALARM_SECURITY_CHECK, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.GET) @ResponseBody - public Alarm getAlarmById(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) + public Alarm getAlarmById(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); @@ -117,11 +118,11 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Get Alarm Info (getAlarmInfoById)", notes = "Fetch the Alarm Info object based on the provided Alarm Id. " + - ALARM_SECURITY_CHECK + ALARM_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + ALARM_SECURITY_CHECK + ALARM_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET) @ResponseBody - public AlarmInfo getAlarmInfoById(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) + public AlarmInfo getAlarmInfoById(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); @@ -139,11 +140,11 @@ public class AlarmController extends BaseController { "If the user clears the alarm (see 'Clear Alarm(clearAlarm)'), than new alarm with the same type and same device may be created. " + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Alarm entity. " + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH - , produces = MediaType.APPLICATION_JSON_VALUE) + , responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm", method = RequestMethod.POST) @ResponseBody - public Alarm saveAlarm(@ApiParam(value = "A JSON value representing the alarm.") @RequestBody Alarm alarm) throws ThingsboardException { + public Alarm saveAlarm(@Parameter(description = "A JSON value representing the alarm.") @RequestBody Alarm alarm) throws ThingsboardException { alarm.setTenantId(getTenantId()); checkNotNull(alarm.getOriginator()); checkEntity(alarm.getId(), alarm, Resource.ALARM); @@ -155,11 +156,11 @@ public class AlarmController extends BaseController { } @ApiOperation(value = "Delete Alarm (deleteAlarm)", - notes = "Deletes the Alarm. Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + notes = "Deletes the Alarm. Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.DELETE) @ResponseBody - public Boolean deleteAlarm(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws ThingsboardException { + public Boolean deleteAlarm(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmId(alarmId, Operation.DELETE); @@ -169,11 +170,11 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Acknowledge Alarm (ackAlarm)", notes = "Acknowledge the Alarm. " + "Once acknowledged, the 'ack_ts' field will be set to current timestamp and special rule chain event 'ALARM_ACK' will be generated. " + - "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) - public AlarmInfo ackAlarm(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws Exception { + public AlarmInfo ackAlarm(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws Exception { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); @@ -184,11 +185,11 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Clear Alarm (clearAlarm)", notes = "Clear the Alarm. " + "Once cleared, the 'clear_ts' field will be set to current timestamp and special rule chain event 'ALARM_CLEAR' will be generated. " + - "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) - public AlarmInfo clearAlarm(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws Exception { + public AlarmInfo clearAlarm(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId) throws Exception { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmId(alarmId, Operation.WRITE); @@ -200,13 +201,13 @@ public class AlarmController extends BaseController { notes = "Assign the Alarm. " + "Once assigned, the 'assign_ts' field will be set to current timestamp and special rule chain event 'ALARM_ASSIGNED' " + "(or ALARM_REASSIGNED in case of assigning already assigned alarm) will be generated. " + - "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/assign/{assigneeId}", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) - public Alarm assignAlarm(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) + public Alarm assignAlarm(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId, - @ApiParam(value = ASSIGN_ID_PARAM_DESCRIPTION) + @Parameter(description = ASSIGN_ID_PARAM_DESCRIPTION) @PathVariable(ASSIGNEE_ID) String strAssigneeId ) throws Exception { checkParameter(ALARM_ID, strAlarmId); @@ -221,11 +222,11 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Unassign Alarm (unassignAlarm)", notes = "Unassign the Alarm. " + "Once unassigned, the 'assign_ts' field will be set to current timestamp and special rule chain event 'ALARM_UNASSIGNED' will be generated. " + - "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/assign", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public Alarm unassignAlarm(@ApiParam(value = ALARM_ID_PARAM_DESCRIPTION) + public Alarm unassignAlarm(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) @PathVariable(ALARM_ID) String strAlarmId ) throws Exception { checkParameter(ALARM_ID, strAlarmId); @@ -236,36 +237,36 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Get Alarms (getAlarms)", notes = "Returns a page of alarms for the selected entity. Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) @ResponseBody public PageData getAlarms( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable(ENTITY_TYPE) String strEntityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_ID) String strEntityId, - @ApiParam(value = ALARM_QUERY_SEARCH_STATUS_DESCRIPTION, allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_SEARCH_STATUS_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES)) @RequestParam(required = false) String searchStatus, - @ApiParam(value = ALARM_QUERY_STATUS_DESCRIPTION, allowableValues = ALARM_QUERY_STATUS_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_STATUS_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_STATUS_ALLOWABLE_VALUES)) @RequestParam(required = false) String status, - @ApiParam(value = ALARM_QUERY_ASSIGNEE_DESCRIPTION) + @Parameter(description = ALARM_QUERY_ASSIGNEE_DESCRIPTION) @RequestParam(required = false) String assigneeId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ALARM_QUERY_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ALARM_QUERY_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ALARM_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "startTs", "endTs", "type", "ackTs", "clearTs", "severity", "status"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = ALARM_QUERY_START_TIME_DESCRIPTION) + @Parameter(description = ALARM_QUERY_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = ALARM_QUERY_END_TIME_DESCRIPTION) + @Parameter(description = ALARM_QUERY_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime, - @ApiParam(value = ALARM_QUERY_FETCH_ORIGINATOR_DESCRIPTION) + @Parameter(description = ALARM_QUERY_FETCH_ORIGINATOR_DESCRIPTION) @RequestParam(required = false) Boolean fetchOriginator ) throws ThingsboardException, ExecutionException, InterruptedException { checkParameter("EntityId", strEntityId); @@ -292,32 +293,32 @@ public class AlarmController extends BaseController { "If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " + "If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " + "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarms", method = RequestMethod.GET) @ResponseBody public PageData getAllAlarms( - @ApiParam(value = ALARM_QUERY_SEARCH_STATUS_DESCRIPTION, allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_SEARCH_STATUS_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES)) @RequestParam(required = false) String searchStatus, - @ApiParam(value = ALARM_QUERY_STATUS_DESCRIPTION, allowableValues = ALARM_QUERY_STATUS_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_STATUS_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_STATUS_ALLOWABLE_VALUES)) @RequestParam(required = false) String status, - @ApiParam(value = ALARM_QUERY_ASSIGNEE_DESCRIPTION) + @Parameter(description = ALARM_QUERY_ASSIGNEE_DESCRIPTION) @RequestParam(required = false) String assigneeId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ALARM_QUERY_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ALARM_QUERY_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ALARM_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "startTs", "endTs", "type", "ackTs", "clearTs", "severity", "status"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = ALARM_QUERY_START_TIME_DESCRIPTION) + @Parameter(description = ALARM_QUERY_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = ALARM_QUERY_END_TIME_DESCRIPTION) + @Parameter(description = ALARM_QUERY_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime, - @ApiParam(value = ALARM_QUERY_FETCH_ORIGINATOR_DESCRIPTION) + @Parameter(description = ALARM_QUERY_FETCH_ORIGINATOR_DESCRIPTION) @RequestParam(required = false) Boolean fetchOriginator ) throws ThingsboardException, ExecutionException, InterruptedException { AlarmSearchStatus alarmSearchStatus = StringUtils.isEmpty(searchStatus) ? null : AlarmSearchStatus.valueOf(searchStatus); @@ -341,36 +342,36 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Get Alarms (getAlarmsV2)", notes = "Returns a page of alarms for the selected entity. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/v2/alarm/{entityType}/{entityId}", method = RequestMethod.GET) @ResponseBody public PageData getAlarmsV2( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable(ENTITY_TYPE) String strEntityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_ID) String strEntityId, - @ApiParam(value = ALARM_QUERY_SEARCH_STATUS_ARRAY_DESCRIPTION, allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_SEARCH_STATUS_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES)) @RequestParam(required = false) String[] statusList, - @ApiParam(value = ALARM_QUERY_SEVERITY_ARRAY_DESCRIPTION, allowableValues = ALARM_QUERY_SEVERITY_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_SEVERITY_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_SEVERITY_ALLOWABLE_VALUES)) @RequestParam(required = false) String[] severityList, - @ApiParam(value = ALARM_QUERY_TYPE_ARRAY_DESCRIPTION) + @Parameter(description = ALARM_QUERY_TYPE_ARRAY_DESCRIPTION) @RequestParam(required = false) String[] typeList, - @ApiParam(value = ALARM_QUERY_ASSIGNEE_DESCRIPTION) + @Parameter(description = ALARM_QUERY_ASSIGNEE_DESCRIPTION) @RequestParam(required = false) String assigneeId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ALARM_QUERY_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ALARM_QUERY_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ALARM_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "startTs", "endTs", "type", "ackTs", "clearTs", "severity", "status"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = ALARM_QUERY_START_TIME_DESCRIPTION) + @Parameter(description = ALARM_QUERY_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = ALARM_QUERY_END_TIME_DESCRIPTION) + @Parameter(description = ALARM_QUERY_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime ) throws ThingsboardException, ExecutionException, InterruptedException { checkParameter("EntityId", strEntityId); @@ -407,32 +408,32 @@ public class AlarmController extends BaseController { notes = "Returns a page of alarms that belongs to the current user owner. " + "If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " + "If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/v2/alarms", method = RequestMethod.GET) @ResponseBody public PageData getAllAlarmsV2( - @ApiParam(value = ALARM_QUERY_SEARCH_STATUS_ARRAY_DESCRIPTION, allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_SEARCH_STATUS_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES)) @RequestParam(required = false) String[] statusList, - @ApiParam(value = ALARM_QUERY_SEVERITY_ARRAY_DESCRIPTION, allowableValues = ALARM_QUERY_SEVERITY_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_SEVERITY_ARRAY_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_SEVERITY_ALLOWABLE_VALUES)) @RequestParam(required = false) String[] severityList, - @ApiParam(value = ALARM_QUERY_TYPE_ARRAY_DESCRIPTION) + @Parameter(description = ALARM_QUERY_TYPE_ARRAY_DESCRIPTION) @RequestParam(required = false) String[] typeList, - @ApiParam(value = ALARM_QUERY_ASSIGNEE_DESCRIPTION) + @Parameter(description = ALARM_QUERY_ASSIGNEE_DESCRIPTION) @RequestParam(required = false) String assigneeId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ALARM_QUERY_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ALARM_QUERY_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ALARM_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "startTs", "endTs", "type", "ackTs", "clearTs", "severity", "status"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = ALARM_QUERY_START_TIME_DESCRIPTION) + @Parameter(description = ALARM_QUERY_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = ALARM_QUERY_END_TIME_DESCRIPTION) + @Parameter(description = ALARM_QUERY_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime ) throws ThingsboardException, ExecutionException, InterruptedException { List alarmStatusList = new ArrayList<>(); @@ -468,20 +469,20 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Get Highest Alarm Severity (getHighestAlarmSeverity)", notes = "Search the alarms by originator ('entityType' and entityId') and optional 'status' or 'searchStatus' filters and returns the highest AlarmSeverity(CRITICAL, MAJOR, MINOR, WARNING or INDETERMINATE). " + "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH - , produces = MediaType.APPLICATION_JSON_VALUE) + , responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) @ResponseBody public AlarmSeverity getHighestAlarmSeverity( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable(ENTITY_TYPE) String strEntityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_ID) String strEntityId, - @ApiParam(value = ALARM_QUERY_SEARCH_STATUS_DESCRIPTION, allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_SEARCH_STATUS_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_SEARCH_STATUS_ALLOWABLE_VALUES)) @RequestParam(required = false) String searchStatus, - @ApiParam(value = ALARM_QUERY_STATUS_DESCRIPTION, allowableValues = ALARM_QUERY_STATUS_ALLOWABLE_VALUES) + @Parameter(description = ALARM_QUERY_STATUS_DESCRIPTION, schema = @Schema(allowableValues = ALARM_QUERY_STATUS_ALLOWABLE_VALUES)) @RequestParam(required = false) String status, - @ApiParam(value = ALARM_QUERY_ASSIGNEE_DESCRIPTION) + @Parameter(description = ALARM_QUERY_ASSIGNEE_DESCRIPTION) @RequestParam(required = false) String assigneeId ) throws ThingsboardException { checkParameter("EntityId", strEntityId); diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 510fefe305..79d8d88352 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -16,8 +16,10 @@ package org.thingsboard.server.controller; import com.google.common.util.concurrent.ListenableFuture; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -49,6 +51,7 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportRequest; import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportResult; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -67,7 +70,6 @@ import static org.thingsboard.server.controller.ControllerConstants.ASSET_ID_PAR import static org.thingsboard.server.controller.ControllerConstants.ASSET_INFO_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ASSET_NAME_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.ASSET_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.ASSET_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ASSET_TYPE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; @@ -79,7 +81,6 @@ import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIG import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -102,11 +103,11 @@ public class AssetController extends BaseController { notes = "Fetch the Asset object based on the provided Asset Id. " + "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " + "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH - , produces = MediaType.APPLICATION_JSON_VALUE) + , responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset/{assetId}", method = RequestMethod.GET) @ResponseBody - public Asset getAssetById(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) + public Asset getAssetById(@Parameter(description = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(ASSET_ID, strAssetId); AssetId assetId = new AssetId(toUUID(strAssetId)); @@ -117,11 +118,11 @@ public class AssetController extends BaseController { notes = "Fetch the Asset Info object based on the provided Asset Id. " + "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " + "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer. " - + ASSET_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + + ASSET_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset/info/{assetId}", method = RequestMethod.GET) @ResponseBody - public AssetInfo getAssetInfoById(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) + public AssetInfo getAssetInfoById(@Parameter(description = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(ASSET_ID, strAssetId); AssetId assetId = new AssetId(toUUID(strAssetId)); @@ -134,11 +135,11 @@ public class AssetController extends BaseController { "Specify existing Asset id to update the asset. " + "Referencing non-existing Asset Id will cause 'Not Found' error. " + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Asset entity. " - + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset", method = RequestMethod.POST) @ResponseBody - public Asset saveAsset(@ApiParam(value = "A JSON value representing the asset.") @RequestBody Asset asset) throws Exception { + public Asset saveAsset(@Parameter(description = "A JSON value representing the asset.") @RequestBody Asset asset) throws Exception { asset.setTenantId(getTenantId()); checkEntity(asset.getId(), asset, Resource.ASSET); return tbAssetService.save(asset, getCurrentUser()); @@ -149,7 +150,7 @@ public class AssetController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/asset/{assetId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public void deleteAsset(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws Exception { + public void deleteAsset(@Parameter(description = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws Exception { checkParameter(ASSET_ID, strAssetId); AssetId assetId = new AssetId(toUUID(strAssetId)); Asset asset = checkAssetId(assetId, Operation.DELETE); @@ -157,12 +158,12 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Assign asset to customer (assignAssetToCustomer)", - notes = "Creates assignment of the asset to customer. Customer will be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + notes = "Creates assignment of the asset to customer. Customer will be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/asset/{assetId}", method = RequestMethod.POST) @ResponseBody - public Asset assignAssetToCustomer(@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, - @ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { + public Asset assignAssetToCustomer(@Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, + @Parameter(description = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter("customerId", strCustomerId); checkParameter(ASSET_ID, strAssetId); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); @@ -173,11 +174,11 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Unassign asset from customer (unassignAssetFromCustomer)", - notes = "Clears assignment of the asset to customer. Customer will not be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + notes = "Clears assignment of the asset to customer. Customer will not be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/asset/{assetId}", method = RequestMethod.DELETE) @ResponseBody - public Asset unassignAssetFromCustomer(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { + public Asset unassignAssetFromCustomer(@Parameter(description = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(ASSET_ID, strAssetId); AssetId assetId = new AssetId(toUUID(strAssetId)); Asset asset = checkAssetId(assetId, Operation.UNASSIGN_FROM_CUSTOMER); @@ -191,11 +192,11 @@ public class AssetController extends BaseController { @ApiOperation(value = "Make asset publicly available (assignAssetToPublicCustomer)", notes = "Asset will be available for non-authorized (not logged-in) users. " + "This is useful to create dashboards that you plan to share/embed on a publicly available website. " + - "However, users that are logged-in and belong to different tenant will not be able to access the asset." + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + "However, users that are logged-in and belong to different tenant will not be able to access the asset." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/public/asset/{assetId}", method = RequestMethod.POST) @ResponseBody - public Asset assignAssetToPublicCustomer(@ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { + public Asset assignAssetToPublicCustomer(@Parameter(description = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(ASSET_ID, strAssetId); AssetId assetId = new AssetId(toUUID(strAssetId)); checkAssetId(assetId, Operation.ASSIGN_TO_CUSTOMER); @@ -204,22 +205,22 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Tenant Assets (getTenantAssets)", notes = "Returns a page of assets owned by tenant. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantAssets( - @ApiParam(value = PAGE_SIZE_DESCRIPTION) + @Parameter(description = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION) + @Parameter(description = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, - @ApiParam(value = ASSET_TYPE_DESCRIPTION) + @Parameter(description = ASSET_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ASSET_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -232,24 +233,24 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Tenant Asset Infos (getTenantAssetInfos)", notes = "Returns a page of assets info objects owned by tenant. " + - PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantAssetInfos( - @ApiParam(value = PAGE_SIZE_DESCRIPTION) + @Parameter(description = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION) + @Parameter(description = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, - @ApiParam(value = ASSET_TYPE_DESCRIPTION) + @Parameter(description = ASSET_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = ASSET_PROFILE_ID_PARAM_DESCRIPTION) @RequestParam(required = false) String assetProfileId, - @ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ASSET_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -265,12 +266,12 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Tenant Asset (getTenantAsset)", notes = "Requested asset must be owned by tenant that the user belongs to. " + - "Asset name is an unique property of asset. So it can be used to identify the asset." + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + "Asset name is an unique property of asset. So it can be used to identify the asset." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/assets", params = {"assetName"}, method = RequestMethod.GET) @ResponseBody public Asset getTenantAsset( - @ApiParam(value = ASSET_NAME_DESCRIPTION) + @Parameter(description = ASSET_NAME_DESCRIPTION) @RequestParam String assetName) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(assetService.findAssetByTenantIdAndName(tenantId, assetName)); @@ -278,24 +279,24 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Customer Assets (getCustomerAssets)", notes = "Returns a page of assets objects assigned to customer. " + - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerAssets( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION) + @Parameter(description = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION) + @Parameter(description = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, - @ApiParam(value = ASSET_TYPE_DESCRIPTION) + @Parameter(description = ASSET_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ASSET_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -311,26 +312,26 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Customer Asset Infos (getCustomerAssetInfos)", notes = "Returns a page of assets info objects assigned to customer. " + - PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerAssetInfos( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION) + @Parameter(description = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION) + @Parameter(description = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, - @ApiParam(value = ASSET_TYPE_DESCRIPTION) + @Parameter(description = ASSET_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = ASSET_PROFILE_ID_PARAM_DESCRIPTION) @RequestParam(required = false) String assetProfileId, - @ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ASSET_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -348,12 +349,12 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Get Assets By Ids (getAssetsByIds)", - notes = "Requested assets must be owned by tenant or assigned to customer which user is performing the request. ", produces = MediaType.APPLICATION_JSON_VALUE) + notes = "Requested assets must be owned by tenant or assigned to customer which user is performing the request. ", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assets", params = {"assetIds"}, method = RequestMethod.GET) @ResponseBody public List getAssetsByIds( - @ApiParam(value = "A list of assets ids, separated by comma ','") + @Parameter(description = "A list of assets ids, separated by comma ','") @RequestParam("assetIds") String[] strAssetIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("assetIds", strAssetIds); SecurityUser user = getCurrentUser(); @@ -375,7 +376,7 @@ public class AssetController extends BaseController { @ApiOperation(value = "Find related assets (findByQuery)", notes = "Returns all assets that are related to the specific entity. " + "The entity id, relation type, asset types, depth of the search, and other query parameters defined using complex 'AssetSearchQuery' object. " + - "See 'Model' tab of the Parameters for more info.", produces = MediaType.APPLICATION_JSON_VALUE) + "See 'Model' tab of the Parameters for more info.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assets", method = RequestMethod.POST) @ResponseBody @@ -397,7 +398,7 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Get Asset Types (getAssetTypes)", - notes = "Returns a set of unique asset types based on assets that are either owned by the tenant or assigned to the customer which user is performing the request.", produces = MediaType.APPLICATION_JSON_VALUE) + notes = "Returns a set of unique asset types based on assets that are either owned by the tenant or assigned to the customer which user is performing the request.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset/types", method = RequestMethod.GET) @ResponseBody @@ -414,12 +415,12 @@ public class AssetController extends BaseController { "Second, remote edge service will receive a copy of assignment asset " + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once asset will be delivered to edge service, it's going to be available for usage on remote edge instance.", - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.POST) @ResponseBody - public Asset assignAssetToEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { + public Asset assignAssetToEdge(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId, + @Parameter(description = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(ASSET_ID, strAssetId); @@ -438,12 +439,12 @@ public class AssetController extends BaseController { "Second, remote edge service will receive an 'unassign' command to remove asset " + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once 'unassign' command will be delivered to edge service, it's going to remove asset locally.", - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.DELETE) @ResponseBody - public Asset unassignAssetFromEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { + public Asset unassignAssetFromEdge(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId, + @Parameter(description = ASSET_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(ASSET_ID, strAssetId); EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); @@ -457,28 +458,28 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get assets assigned to edge (getEdgeAssets)", notes = "Returns a page of assets assigned to edge. " + - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getEdgeAssets( - @ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) + @Parameter(description = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION) + @Parameter(description = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION) + @Parameter(description = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, - @ApiParam(value = ASSET_TYPE_DESCRIPTION) + @Parameter(description = ASSET_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = ASSET_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ASSET_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = "Timestamp. Assets with creation time before it won't be queried") + @Parameter(description = "Timestamp. Assets with creation time before it won't be queried") @RequestParam(required = false) Long startTime, - @ApiParam(value = "Timestamp. Assets with creation time after it won't be queried") + @Parameter(description = "Timestamp. Assets with creation time after it won't be queried") @RequestParam(required = false) Long endTime) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -507,7 +508,7 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Import the bulk of assets (processAssetsBulkImport)", - notes = "There's an ability to import the bulk of assets using the only .csv file.", produces = MediaType.APPLICATION_JSON_VALUE) + notes = "There's an ability to import the bulk of assets using the only .csv file.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PostMapping("/asset/bulk_import") public BulkImportResult processAssetsBulkImport(@RequestBody BulkImportRequest request) throws Exception { diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java index 47a7eede4b..0d6f652241 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java @@ -15,11 +15,14 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -35,6 +38,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.asset.profile.TbAssetProfileService; import org.thingsboard.server.service.security.permission.Operation; @@ -43,13 +47,11 @@ import org.thingsboard.server.service.security.permission.Resource; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_INFO_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.ASSET_PROFILE_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -68,12 +70,12 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Asset Profile (getAssetProfileById)", notes = "Fetch the Asset Profile object based on the provided Asset Profile Id. " + "The server checks that the asset profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.GET) @ResponseBody public AssetProfile getAssetProfileById( - @ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = ASSET_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { checkParameter(ASSET_PROFILE_ID, strAssetProfileId); AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); @@ -83,12 +85,12 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Asset Profile Info (getAssetProfileInfoById)", notes = "Fetch the Asset Profile Info object based on the provided Asset Profile Id. " + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assetProfileInfo/{assetProfileId}", method = RequestMethod.GET) @ResponseBody public AssetProfileInfo getAssetProfileInfoById( - @ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = ASSET_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { checkParameter(ASSET_PROFILE_ID, strAssetProfileId); AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); @@ -98,7 +100,7 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Default Asset Profile (getDefaultAssetProfileInfo)", notes = "Fetch the Default Asset Profile Info object. " + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assetProfileInfo/default", method = RequestMethod.GET) @ResponseBody @@ -114,13 +116,12 @@ public class AssetProfileController extends BaseController { "Asset profile name is unique in the scope of tenant. Only one 'default' asset profile may exist in scope of tenant. " + "Remove 'id', 'tenantId' from the request body example (below) to create new Asset Profile entity. " + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json", - consumes = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfile", method = RequestMethod.POST) @ResponseBody public AssetProfile saveAssetProfile( - @ApiParam(value = "A JSON value representing the asset profile.") + @Parameter(description = "A JSON value representing the asset profile.") @RequestBody AssetProfile assetProfile) throws Exception { assetProfile.setTenantId(getTenantId()); checkEntity(assetProfile.getId(), assetProfile, Resource.ASSET_PROFILE); @@ -130,12 +131,12 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Delete asset profile (deleteAssetProfile)", notes = "Deletes the asset profile. Referencing non-existing asset profile Id will cause an error. " + "Can't delete the asset profile if it is referenced by existing assets." + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) public void deleteAssetProfile( - @ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = ASSET_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { checkParameter(ASSET_PROFILE_ID, strAssetProfileId); AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); @@ -145,12 +146,12 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Make Asset Profile Default (setDefaultAssetProfile)", notes = "Marks asset profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfile/{assetProfileId}/default", method = RequestMethod.POST) @ResponseBody public AssetProfile setDefaultAssetProfile( - @ApiParam(value = ASSET_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = ASSET_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable(ASSET_PROFILE_ID) String strAssetProfileId) throws ThingsboardException { checkParameter(ASSET_PROFILE_ID, strAssetProfileId); AssetProfileId assetProfileId = new AssetProfileId(toUUID(strAssetProfileId)); @@ -162,20 +163,20 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Asset Profiles (getAssetProfiles)", notes = "Returns a page of asset profile objects owned by tenant. " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getAssetProfiles( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ASSET_PROFILE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ASSET_PROFILE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "description", "isDefault"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(assetProfileService.findAssetProfiles(getTenantId(), pageLink)); @@ -184,20 +185,20 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Asset Profile infos (getAssetProfileInfos)", notes = "Returns a page of asset profile info objects owned by tenant. " + PAGE_DATA_PARAMETERS + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assetProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getAssetProfileInfos( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ASSET_PROFILE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ASSET_PROFILE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ASSET_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "description", "isDefault"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(assetProfileService.findAssetProfileInfos(getTenantId(), pageLink)); diff --git a/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java b/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java index 387f0d014b..71113d41fa 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; @@ -35,6 +37,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import java.util.Arrays; @@ -42,7 +45,6 @@ import java.util.List; import java.util.UUID; import java.util.stream.Collectors; -import static org.thingsboard.server.controller.ControllerConstants.AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.AUDIT_LOG_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ENTITY_ID_PARAM_DESCRIPTION; @@ -50,7 +52,6 @@ import static org.thingsboard.server.controller.ControllerConstants.ENTITY_TYPE_ import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.USER_ID_PARAM_DESCRIPTION; @@ -74,28 +75,28 @@ public class AuditLogController extends BaseController { notes = "Returns a page of audit logs related to the targeted customer entities (devices, assets, etc.), " + "and users actions (login, logout, etc.) that belong to this customer. " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getAuditLogsByCustomerId( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION) + @Parameter(description = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION) + @Parameter(description = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, - @ApiParam(value = AUDIT_LOG_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = AUDIT_LOG_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = AUDIT_LOG_SORT_PROPERTY_DESCRIPTION, allowableValues = AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = AUDIT_LOG_SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "entityType", "entityName", "userName", "actionType", "actionStatus"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = AUDIT_LOG_QUERY_START_TIME_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = AUDIT_LOG_QUERY_END_TIME_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime, - @ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { checkParameter("CustomerId", strCustomerId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -108,28 +109,28 @@ public class AuditLogController extends BaseController { notes = "Returns a page of audit logs related to the actions of targeted user. " + "For example, RPC call to a particular device, or alarm acknowledgment for a specific device, etc. " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/audit/logs/user/{userId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getAuditLogsByUserId( - @ApiParam(value = USER_ID_PARAM_DESCRIPTION) + @Parameter(description = USER_ID_PARAM_DESCRIPTION) @PathVariable("userId") String strUserId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION) + @Parameter(description = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION) + @Parameter(description = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, - @ApiParam(value = AUDIT_LOG_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = AUDIT_LOG_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = AUDIT_LOG_SORT_PROPERTY_DESCRIPTION, allowableValues = AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = AUDIT_LOG_SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "entityType", "entityName", "userName", "actionType", "actionStatus"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = AUDIT_LOG_QUERY_START_TIME_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = AUDIT_LOG_QUERY_END_TIME_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime, - @ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { checkParameter("UserId", strUserId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -143,30 +144,30 @@ public class AuditLogController extends BaseController { "Basically, this API call is used to get the full lifecycle of some specific entity. " + "For example to see when a device was created, updated, assigned to some customer, or even deleted from the system. " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getAuditLogsByEntityId( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String strEntityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String strEntityId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = AUDIT_LOG_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = AUDIT_LOG_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = AUDIT_LOG_SORT_PROPERTY_DESCRIPTION, allowableValues = AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = AUDIT_LOG_SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "entityType", "entityName", "userName", "actionType", "actionStatus"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = AUDIT_LOG_QUERY_START_TIME_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = AUDIT_LOG_QUERY_END_TIME_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime, - @ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { checkParameter("EntityId", strEntityId); checkParameter("EntityType", strEntityType); @@ -179,26 +180,26 @@ public class AuditLogController extends BaseController { @ApiOperation(value = "Get all audit logs (getAuditLogs)", notes = "Returns a page of audit logs related to all entities in the scope of the current user's Tenant. " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/audit/logs", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getAuditLogs( - @ApiParam(value = PAGE_SIZE_DESCRIPTION) + @Parameter(description = PAGE_SIZE_DESCRIPTION) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION) + @Parameter(description = PAGE_NUMBER_DESCRIPTION) @RequestParam int page, - @ApiParam(value = AUDIT_LOG_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = AUDIT_LOG_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = AUDIT_LOG_SORT_PROPERTY_DESCRIPTION, allowableValues = AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = AUDIT_LOG_SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "entityType", "entityName", "userName", "actionType", "actionStatus"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = AUDIT_LOG_QUERY_START_TIME_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = AUDIT_LOG_QUERY_END_TIME_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime, - @ApiParam(value = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) + @Parameter(description = AUDIT_LOG_QUERY_ACTION_TYPES_DESCRIPTION) @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); List actionTypes = parseActionTypesStr(actionTypesStr); diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index 5357c0e2a4..86941e2b07 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -16,8 +16,8 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -48,9 +48,10 @@ import org.thingsboard.server.common.data.security.event.UserSessionInvalidation import org.thingsboard.server.common.data.security.model.JwtPair; import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; -import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.util.limits.LimitedApi; import org.thingsboard.server.dao.util.limits.RateLimitService; +import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails; import org.thingsboard.server.service.security.model.ActivateUserRequest; import org.thingsboard.server.service.security.model.ChangePasswordRequest; @@ -61,7 +62,6 @@ import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.system.SystemSecurityService; -import jakarta.servlet.http.HttpServletRequest; import java.net.URI; import java.net.URISyntaxException; @@ -107,7 +107,7 @@ public class AuthController extends BaseController { @RequestMapping(value = "/auth/changePassword", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) public ObjectNode changePassword( - @ApiParam(value = "Change Password Request") + @Parameter(description = "Change Password Request") @RequestBody ChangePasswordRequest changePasswordRequest) throws ThingsboardException { String currentPassword = changePasswordRequest.getCurrentPassword(); String newPassword = changePasswordRequest.getNewPassword(); @@ -148,7 +148,7 @@ public class AuthController extends BaseController { "If token is not valid, returns '409 Conflict'.") @RequestMapping(value = "/noauth/activate", params = {"activateToken"}, method = RequestMethod.GET) public ResponseEntity checkActivateToken( - @ApiParam(value = "The activate token string.") + @Parameter(description = "The activate token string.") @RequestParam(value = "activateToken") String activateToken) { HttpHeaders headers = new HttpHeaders(); HttpStatus responseStatus; @@ -175,7 +175,7 @@ public class AuthController extends BaseController { @RequestMapping(value = "/noauth/resetPasswordByEmail", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) public void requestResetPasswordByEmail( - @ApiParam(value = "The JSON object representing the reset password email request.") + @Parameter(description = "The JSON object representing the reset password email request.") @RequestBody ResetPasswordEmailRequest resetPasswordByEmailRequest, HttpServletRequest request) throws ThingsboardException { try { @@ -198,7 +198,7 @@ public class AuthController extends BaseController { "If token is not valid, returns '409 Conflict'.") @RequestMapping(value = "/noauth/resetPassword", params = {"resetToken"}, method = RequestMethod.GET) public ResponseEntity checkResetToken( - @ApiParam(value = "The reset token string.") + @Parameter(description = "The reset token string.") @RequestParam(value = "resetToken") String resetToken) { HttpHeaders headers = new HttpHeaders(); HttpStatus responseStatus; @@ -234,7 +234,7 @@ public class AuthController extends BaseController { @ResponseStatus(value = HttpStatus.OK) @ResponseBody public JwtPair activateUser( - @ApiParam(value = "Activate user request.") + @Parameter(description = "Activate user request.") @RequestBody ActivateUserRequest activateRequest, @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, HttpServletRequest request) throws ThingsboardException { @@ -272,7 +272,7 @@ public class AuthController extends BaseController { @ResponseStatus(value = HttpStatus.OK) @ResponseBody public JwtPair resetPassword( - @ApiParam(value = "Reset password request.") + @Parameter(description = "Reset password request.") @RequestBody ResetPasswordRequest resetPasswordRequest, HttpServletRequest request) throws ThingsboardException { String resetToken = resetPasswordRequest.getResetToken(); diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index da2740a3b7..13118645a8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -20,6 +20,9 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import jakarta.mail.MessagingException; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.ConstraintViolation; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -160,9 +163,6 @@ import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService; import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; -import jakarta.mail.MessagingException; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.ConstraintViolation; import java.util.List; import java.util.Objects; import java.util.Optional; diff --git a/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java b/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java index 33a4edfbe0..b0f1786437 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ComponentDescriptorController.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.plugin.ComponentDescriptor; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.data.rule.RuleChainType; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import java.util.HashSet; @@ -54,7 +55,7 @@ public class ComponentDescriptorController extends BaseController { @RequestMapping(value = "/component/{componentDescriptorClazz:.+}", method = RequestMethod.GET) @ResponseBody public ComponentDescriptor getComponentDescriptorByClazz( - @ApiParam(value = "Component Descriptor class name", required = true) + @Parameter(description = "Component Descriptor class name", required = true) @PathVariable("componentDescriptorClazz") String strComponentDescriptorClazz) throws ThingsboardException { checkParameter("strComponentDescriptorClazz", strComponentDescriptorClazz); return checkComponentDescriptorByClazz(strComponentDescriptorClazz); @@ -67,9 +68,9 @@ public class ComponentDescriptorController extends BaseController { @RequestMapping(value = "/components/{componentType}", method = RequestMethod.GET) @ResponseBody public List getComponentDescriptorsByType( - @ApiParam(value = "Type of the Rule Node", allowableValues = "ENRICHMENT,FILTER,TRANSFORMATION,ACTION,EXTERNAL", required = true) + @Parameter(description = "Type of the Rule Node", schema = @Schema(allowableValues = "ENRICHMENT,FILTER,TRANSFORMATION,ACTION,EXTERNAL", required = true)) @PathVariable("componentType") String strComponentType, - @ApiParam(value = "Type of the Rule Chain", allowableValues = "CORE,EDGE") + @Parameter(description = "Type of the Rule Chain", schema = @Schema(allowableValues = "CORE,EDGE")) @RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException { checkParameter("componentType", strComponentType); return checkComponentDescriptorsByType(ComponentType.valueOf(strComponentType), getRuleChainType(strRuleChainType)); @@ -82,9 +83,9 @@ public class ComponentDescriptorController extends BaseController { @RequestMapping(value = "/components", params = {"componentTypes"}, method = RequestMethod.GET) @ResponseBody public List getComponentDescriptorsByTypes( - @ApiParam(value = "List of types of the Rule Nodes, (ENRICHMENT, FILTER, TRANSFORMATION, ACTION or EXTERNAL)", required = true) + @Parameter(description = "List of types of the Rule Nodes, (ENRICHMENT, FILTER, TRANSFORMATION, ACTION or EXTERNAL)", required = true) @RequestParam("componentTypes") String[] strComponentTypes, - @ApiParam(value = "Type of the Rule Chain", allowableValues = "CORE,EDGE") + @Parameter(description = "Type of the Rule Chain", schema = @Schema(allowableValues = "CORE,EDGE")) @RequestParam(value = "ruleChainType", required = false) String strRuleChainType) throws ThingsboardException { checkArrayParameter("componentTypes", strComponentTypes); Set componentTypes = new HashSet<>(); diff --git a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java index f425bde86c..8f95dbff35 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java +++ b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java @@ -89,33 +89,8 @@ public class ControllerConstants { protected static final String EVENT_TEXT_SEARCH_DESCRIPTION = "The value is not used in searching."; protected static final String AUDIT_LOG_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'substring' filter based on one of the next properties: entityType, entityName, userName, actionType, actionStatus."; protected static final String SORT_PROPERTY_DESCRIPTION = "Property of entity to sort by"; - protected static final String DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title"; - protected static final String CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, city"; - protected static final String RPC_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, expirationTime, request, response"; - protected static final String DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, deviceProfileName, label, customerTitle"; - protected static final String ENTITY_VIEW_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type"; - protected static final String ENTITY_VIEW_INFO_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, customerTitle"; - protected static final String USER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, firstName, lastName, email"; - protected static final String TENANT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, state, city, address, address2, zip, phone, email"; - protected static final String TENANT_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, description, isDefault"; - protected static final String TENANT_PROFILE_INFO_SORT_PROPERTY_ALLOWABLE_VALUES = "id, name"; - protected static final String TENANT_INFO_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, tenantProfileName, title, email, country, state, city, address, address2, zip, phone, email"; - protected static final String DEVICE_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, transportType, description, isDefault"; - - protected static final String ASSET_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, description, isDefault"; - protected static final String ASSET_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle"; - protected static final String ALARM_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, startTs, endTs, type, ackTs, clearTs, severity, status"; - protected static final String ALARM_COMMENT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, id"; - protected static final String EVENT_SORT_PROPERTY_ALLOWABLE_VALUES = "ts, id"; - protected static final String EDGE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, type, label, customerTitle"; - protected static final String RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, root"; - protected static final String WIDGET_BUNDLE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, tenantId"; - protected static final String AUDIT_LOG_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, entityType, entityName, userName, actionType, actionStatus"; + protected static final String SORT_ORDER_DESCRIPTION = "Sort order. ASC (ASCENDING) or DESC (DESCENDING)"; - protected static final String SORT_ORDER_ALLOWABLE_VALUES = "ASC, DESC"; - protected static final String RPC_STATUS_ALLOWABLE_VALUES = "QUEUED, SENT, DELIVERED, SUCCESSFUL, TIMEOUT, EXPIRED, FAILED"; - protected static final String RULE_CHAIN_TYPES_ALLOWABLE_VALUES = "CORE, EDGE"; - protected static final String TRANSPORT_TYPE_ALLOWABLE_VALUES = "DEFAULT, MQTT, COAP, LWM2M, SNMP"; protected static final String DEVICE_INFO_DESCRIPTION = "Device Info is an extension of the default Device object that contains information about the assigned customer name and device profile name. "; protected static final String ASSET_INFO_DESCRIPTION = "Asset Info is an extension of the default Asset object that contains information about the assigned customer name. "; protected static final String ALARM_INFO_DESCRIPTION = "Alarm Info is an extension of the default Alarm object that also contains name of the alarm originator."; @@ -125,23 +100,17 @@ public class ControllerConstants { protected static final String ASSET_PROFILE_INFO_DESCRIPTION = "Asset Profile Info is a lightweight object that includes main information about Asset Profile. "; protected static final String QUEUE_SERVICE_TYPE_DESCRIPTION = "Service type (implemented only for the TB-RULE-ENGINE)"; - protected static final String QUEUE_SERVICE_TYPE_ALLOWABLE_VALUES = "TB-RULE-ENGINE, TB-CORE, TB-TRANSPORT, JS-EXECUTOR"; protected static final String QUEUE_QUEUE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'substring' filter based on the queue name."; - protected static final String QUEUE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, topic"; protected static final String QUEUE_ID_PARAM_DESCRIPTION = "A string value representing the queue id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'"; protected static final String QUEUE_NAME_PARAM_DESCRIPTION = "A string value representing the queue id. For example, 'Main'"; protected static final String OTA_PACKAGE_INFO_DESCRIPTION = "OTA Package Info is a lightweight object that includes main information about the OTA Package excluding the heavyweight data. "; protected static final String OTA_PACKAGE_DESCRIPTION = "OTA Package is a heavyweight object that includes main information about the OTA Package and also data. "; - protected static final String OTA_PACKAGE_CHECKSUM_ALGORITHM_ALLOWABLE_VALUES = "MD5, SHA256, SHA384, SHA512, CRC32, MURMUR3_32, MURMUR3_128"; protected static final String OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'substring' filter based on the ota package title."; - protected static final String OTA_PACKAGE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, type, title, version, tag, url, fileName, dataSize, checksum"; protected static final String RESOURCE_INFO_DESCRIPTION = "Resource Info is a lightweight object that includes main information about the Resource excluding the heavyweight data. "; protected static final String RESOURCE_DESCRIPTION = "Resource is a heavyweight object that includes main information about the Resource and also data. "; protected static final String RESOURCE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'substring' filter based on the resource title."; - protected static final String RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, resourceType, tenantId"; protected static final String LWM2M_OBJECT_DESCRIPTION = "LwM2M Object is a object that includes information about the LwM2M model which can be used in transport configuration for the LwM2M device profile. "; - protected static final String LWM2M_OBJECT_SORT_PROPERTY_ALLOWABLE_VALUES = "id, name"; protected static final String DEVICE_NAME_DESCRIPTION = "A string value representing the Device name."; protected static final String ASSET_NAME_DESCRIPTION = "A string value representing the Asset name."; @@ -1439,8 +1408,6 @@ public class ControllerConstants { protected static final String ATTRIBUTES_SCOPE_DESCRIPTION = "A string value representing the attributes scope. For example, 'SERVER_SCOPE'."; protected static final String ATTRIBUTES_KEYS_DESCRIPTION = "A string value representing the comma-separated list of attributes keys. For example, 'active,inactivityAlarmTime'."; - protected static final String ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES = "SERVER_SCOPE, SHARED_SCOPE"; - protected static final String ATTRIBUTES_SCOPE_ALLOWED_VALUES = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES + ", CLIENT_SCOPE"; protected static final String ATTRIBUTES_JSON_REQUEST_DESCRIPTION = "A string value representing the json object. For example, '{\"key\":\"value\"}'. See API call description for more details."; protected static final String TELEMETRY_KEYS_BASE_DESCRIPTION = "A string value representing the comma-separated list of telemetry keys."; diff --git a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java index dd904add2e..7203f71392 100644 --- a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java +++ b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java @@ -17,8 +17,8 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.customer.TbCustomerService; import org.thingsboard.server.service.security.permission.Operation; @@ -44,13 +45,11 @@ import org.thingsboard.server.service.security.permission.Resource; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.HOME_DASHBOARD; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -76,7 +75,7 @@ public class CustomerController extends BaseController { @RequestMapping(value = "/customer/{customerId}", method = RequestMethod.GET) @ResponseBody public Customer getCustomerById( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException { checkParameter(CUSTOMER_ID, strCustomerId); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); @@ -95,7 +94,7 @@ public class CustomerController extends BaseController { @RequestMapping(value = "/customer/{customerId}/shortInfo", method = RequestMethod.GET) @ResponseBody public JsonNode getShortCustomerInfoById( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException { checkParameter(CUSTOMER_ID, strCustomerId); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); @@ -113,7 +112,7 @@ public class CustomerController extends BaseController { @RequestMapping(value = "/customer/{customerId}/title", method = RequestMethod.GET, produces = "application/text") @ResponseBody public String getCustomerTitleById( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException { checkParameter(CUSTOMER_ID, strCustomerId); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); @@ -131,7 +130,7 @@ public class CustomerController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer", method = RequestMethod.POST) @ResponseBody - public Customer saveCustomer(@ApiParam(value = "A JSON value representing the customer.") @RequestBody Customer customer) throws Exception { + public Customer saveCustomer(@Parameter(description = "A JSON value representing the customer.") @RequestBody Customer customer) throws Exception { customer.setTenantId(getTenantId()); checkEntity(customer.getId(), customer, Resource.CUSTOMER); return tbCustomerService.save(customer, getCurrentUser()); @@ -144,7 +143,7 @@ public class CustomerController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public void deleteCustomer(@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + public void deleteCustomer(@Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable(CUSTOMER_ID) String strCustomerId) throws ThingsboardException { checkParameter(CUSTOMER_ID, strCustomerId); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); @@ -159,15 +158,15 @@ public class CustomerController extends BaseController { @RequestMapping(value = "/customers", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomers( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = CUSTOMER_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = CUSTOMER_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "title", "email", "country, city"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); TenantId tenantId = getCurrentUser().getTenantId(); @@ -180,7 +179,7 @@ public class CustomerController extends BaseController { @RequestMapping(value = "/tenant/customers", params = {"customerTitle"}, method = RequestMethod.GET) @ResponseBody public Customer getTenantCustomer( - @ApiParam(value = "A string value representing the Customer title.") + @Parameter(description = "A string value representing the Customer title.") @RequestParam String customerTitle) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(customerService.findCustomerByTenantIdAndTitle(tenantId, customerTitle), "Customer with title [" + customerTitle + "] is not found"); diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index afc737ab88..c6678deffe 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -17,11 +17,11 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.Example; -import io.swagger.annotations.ExampleProperty; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; @@ -51,6 +51,7 @@ import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.dashboard.TbDashboardService; import org.thingsboard.server.service.security.model.SecurityUser; @@ -66,7 +67,6 @@ import java.util.stream.Collectors; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DASHBOARD_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.DASHBOARD_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION; @@ -77,7 +77,6 @@ import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIG import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH; @@ -111,7 +110,7 @@ public class DashboardController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/serverTime", method = RequestMethod.GET) @ResponseBody - @ApiResponse(code = 200, message = "OK", examples = @Example(value = @ExampleProperty(value = "1636023857137", mediaType = "application/json"))) + @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", examples = @ExampleObject(value = "1636023857137"))) public long getServerTime() throws ThingsboardException { return System.currentTimeMillis(); } @@ -124,20 +123,20 @@ public class DashboardController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/maxDatapointsLimit", method = RequestMethod.GET) @ResponseBody - @ApiResponse(code = 200, message = "OK", examples = @Example(value = @ExampleProperty(value = "5000", mediaType = "application/json"))) + @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", examples = @ExampleObject(value = "5000"))) public long getMaxDatapointsLimit() throws ThingsboardException { return maxDatapointsLimit; } @ApiOperation(value = "Get Dashboard Info (getDashboardInfoById)", notes = "Get the information about the dashboard based on 'dashboardId' parameter. " + DASHBOARD_INFO_DEFINITION, - produces = MediaType.APPLICATION_JSON_VALUE + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)) ) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/info/{dashboardId}", method = RequestMethod.GET) @ResponseBody public DashboardInfo getDashboardInfoById( - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { checkParameter(DASHBOARD_ID, strDashboardId); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); @@ -146,13 +145,13 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Dashboard (getDashboardById)", notes = "Get the dashboard based on 'dashboardId' parameter. " + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)) ) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/{dashboardId}", method = RequestMethod.GET) @ResponseBody public Dashboard getDashboardById( - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { checkParameter(DASHBOARD_ID, strDashboardId); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); @@ -166,13 +165,12 @@ public class DashboardController extends BaseController { "Referencing non-existing dashboard Id will cause 'Not Found' error. " + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Dashboard entity. " + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE, - consumes = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/dashboard", method = RequestMethod.POST) @ResponseBody public Dashboard saveDashboard( - @ApiParam(value = "A JSON value representing the dashboard.") + @Parameter(description = "A JSON value representing the dashboard.") @RequestBody Dashboard dashboard) throws Exception { dashboard.setTenantId(getTenantId()); checkEntity(dashboard.getId(), dashboard, Resource.DASHBOARD); @@ -185,7 +183,7 @@ public class DashboardController extends BaseController { @RequestMapping(value = "/dashboard/{dashboardId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) public void deleteDashboard( - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { checkParameter(DASHBOARD_ID, strDashboardId); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); @@ -196,14 +194,14 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Assign the Dashboard (assignDashboardToCustomer)", notes = "Assign the Dashboard to specified Customer or do nothing if the Dashboard is already assigned to that Customer. " + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.POST) @ResponseBody public Dashboard assignDashboardToCustomer( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable(CUSTOMER_ID) String strCustomerId, - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { checkParameter(CUSTOMER_ID, strCustomerId); checkParameter(DASHBOARD_ID, strDashboardId); @@ -219,14 +217,14 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Unassign the Dashboard (unassignDashboardFromCustomer)", notes = "Unassign the Dashboard from specified Customer or do nothing if the Dashboard is already assigned to that Customer. " + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) @ResponseBody public Dashboard unassignDashboardFromCustomer( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable(CUSTOMER_ID) String strCustomerId, - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { checkParameter("customerId", strCustomerId); checkParameter(DASHBOARD_ID, strDashboardId); @@ -240,16 +238,15 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Update the Dashboard Customers (updateDashboardCustomers)", notes = "Updates the list of Customers that this Dashboard is assigned to. Removes previous assignments to customers that are not in the provided list. " + "Returns the Dashboard object. " + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE, - consumes = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/dashboard/{dashboardId}/customers", method = RequestMethod.POST) @ResponseBody public Dashboard updateDashboardCustomers( - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId, - @ApiParam(value = "JSON array with the list of customer ids, or empty to remove all customers") + @Parameter(description = "JSON array with the list of customer ids, or empty to remove all customers") @RequestBody(required = false) String[] strCustomerIds) throws ThingsboardException { checkParameter(DASHBOARD_ID, strDashboardId); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); @@ -261,15 +258,14 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Adds the Dashboard Customers (addDashboardCustomers)", notes = "Adds the list of Customers to the existing list of assignments for the Dashboard. Keeps previous assignments to customers that are not in the provided list. " + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE, - consumes = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/dashboard/{dashboardId}/customers/add", method = RequestMethod.POST) @ResponseBody public Dashboard addDashboardCustomers( - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId, - @ApiParam(value = "JSON array with the list of customer ids") + @Parameter(description = "JSON array with the list of customer ids") @RequestBody String[] strCustomerIds) throws ThingsboardException { checkParameter(DASHBOARD_ID, strDashboardId); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); @@ -281,15 +277,14 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Remove the Dashboard Customers (removeDashboardCustomers)", notes = "Removes the list of Customers from the existing list of assignments for the Dashboard. Keeps other assignments to customers that are not in the provided list. " + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE, - consumes = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/dashboard/{dashboardId}/customers/remove", method = RequestMethod.POST) @ResponseBody public Dashboard removeDashboardCustomers( - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId, - @ApiParam(value = "JSON array with the list of customer ids") + @Parameter(description = "JSON array with the list of customer ids") @RequestBody String[] strCustomerIds) throws ThingsboardException { checkParameter(DASHBOARD_ID, strDashboardId); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); @@ -305,12 +300,12 @@ public class DashboardController extends BaseController { "Use [assign Asset to Public Customer](#!/asset-controller/assignAssetToPublicCustomerUsingPOST) and " + "[assign Device to Public Customer](#!/device-controller/assignDeviceToPublicCustomerUsingPOST) for this purpose. " + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.POST) @ResponseBody public Dashboard assignDashboardToPublicCustomer( - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { checkParameter(DASHBOARD_ID, strDashboardId); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); @@ -321,12 +316,12 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Unassign the Dashboard from Public Customer (unassignDashboardFromPublicCustomer)", notes = "Unassigns the dashboard from a special, auto-generated 'Public' Customer. Once unassigned, unauthenticated users may no longer browse the dashboard. " + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.DELETE) @ResponseBody public Dashboard unassignDashboardFromPublicCustomer( - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DASHBOARD_ID) String strDashboardId) throws ThingsboardException { checkParameter(DASHBOARD_ID, strDashboardId); DashboardId dashboardId = new DashboardId(toUUID(strDashboardId)); @@ -337,22 +332,22 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Tenant Dashboards by System Administrator (getTenantDashboards)", notes = "Returns a page of dashboard info objects owned by tenant. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + SYSTEM_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/tenant/{tenantId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantDashboards( - @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = TENANT_ID_PARAM_DESCRIPTION, required = true) @PathVariable(TENANT_ID) String strTenantId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = DASHBOARD_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DASHBOARD_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "title"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); checkTenantId(tenantId, Operation.READ); @@ -363,22 +358,22 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Tenant Dashboards (getTenantDashboards)", notes = "Returns a page of dashboard info objects owned by the tenant of a current user. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantDashboards( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = HIDDEN_FOR_MOBILE) + @Parameter(description = HIDDEN_FOR_MOBILE) @RequestParam(required = false) Boolean mobile, - @ApiParam(value = DASHBOARD_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DASHBOARD_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "title"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -392,24 +387,24 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Customer Dashboards (getCustomerDashboards)", notes = "Returns a page of dashboard info objects owned by the specified customer. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerDashboards( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) @PathVariable(CUSTOMER_ID) String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = HIDDEN_FOR_MOBILE) + @Parameter(description = HIDDEN_FOR_MOBILE) @RequestParam(required = false) Boolean mobile, - @ApiParam(value = DASHBOARD_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DASHBOARD_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "title"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter(CUSTOMER_ID, strCustomerId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -428,7 +423,7 @@ public class DashboardController extends BaseController { "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " + "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/home", method = RequestMethod.GET) @ResponseBody @@ -461,7 +456,7 @@ public class DashboardController extends BaseController { "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " + "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/home/info", method = RequestMethod.GET) @ResponseBody @@ -492,7 +487,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the corresponding tenant. " + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.GET) @ResponseBody @@ -514,12 +509,12 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Update Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", notes = "Update the home dashboard assignment for the current tenant. " + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) public void setTenantHomeDashboardInfo( - @ApiParam(value = "A JSON object that represents home dashboard id and other parameters", required = true) + @Parameter(description = "A JSON object that represents home dashboard id and other parameters", required = true) @RequestBody HomeDashboardInfo homeDashboardInfo) throws ThingsboardException { if (homeDashboardInfo.getDashboardId() != null) { @@ -582,7 +577,7 @@ public class DashboardController extends BaseController { EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once dashboard will be delivered to edge service, it's going to be available for usage on remote edge instance." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.POST) @ResponseBody @@ -606,7 +601,7 @@ public class DashboardController extends BaseController { EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once 'unassign' command will be delivered to edge service, it's going to remove dashboard locally." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) @ResponseBody @@ -627,22 +622,22 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Edge Dashboards (getEdgeDashboards)", notes = "Returns a page of dashboard info objects assigned to the specified edge. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getEdgeDashboards( - @ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = DASHBOARD_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DASHBOARD_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DASHBOARD_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "title"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("edgeId", strEdgeId); TenantId tenantId = getCurrentUser().getTenantId(); diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 9de6a66041..603409bba0 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -19,8 +19,11 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.annotation.Nullable; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -62,6 +65,7 @@ import org.thingsboard.server.common.data.page.TimePageLink; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportRequest; import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportResult; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.device.claim.ClaimResponse; import org.thingsboard.server.dao.device.claim.ClaimResult; import org.thingsboard.server.dao.device.claim.ReclaimResult; @@ -74,7 +78,6 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; -import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -90,7 +93,6 @@ import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID_PA import static org.thingsboard.server.controller.ControllerConstants.DEVICE_INFO_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_NAME_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_TYPE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_WITH_DEVICE_CREDENTIALS_PARAM_DESCRIPTION_MARKDOWN; @@ -102,7 +104,6 @@ import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIG import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -133,7 +134,7 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET) @ResponseBody - public Device getDeviceById(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + public Device getDeviceById(@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -148,7 +149,7 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/info/{deviceId}", method = RequestMethod.GET) @ResponseBody - public DeviceInfo getDeviceInfoById(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + public DeviceInfo getDeviceInfoById(@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -167,8 +168,8 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device", method = RequestMethod.POST) @ResponseBody - public Device saveDevice(@ApiParam(value = "A JSON value representing the device.") @RequestBody Device device, - @ApiParam(value = "Optional value of the device credentials to be used during device creation. " + + public Device saveDevice(@Parameter(description = "A JSON value representing the device.") @RequestBody Device device, + @Parameter(description = "Optional value of the device credentials to be used during device creation. " + "If omitted, access token will be auto-generated.") @RequestParam(name = "accessToken", required = false) String accessToken) throws Exception { device.setTenantId(getCurrentUser().getTenantId()); Device oldDevice = null; @@ -190,7 +191,7 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device-with-credentials", method = RequestMethod.POST) @ResponseBody - public Device saveDeviceWithCredentials(@ApiParam(value = "The JSON object with device and credentials. See method description above for example.") + public Device saveDeviceWithCredentials(@Parameter(description = "The JSON object with device and credentials. See method description above for example.") @RequestBody SaveDeviceWithCredentialsRequest deviceAndCredentials) throws ThingsboardException { Device device = checkNotNull(deviceAndCredentials.getDevice()); DeviceCredentials credentials = checkNotNull(deviceAndCredentials.getCredentials()); @@ -204,7 +205,7 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public void deleteDevice(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + public void deleteDevice(@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws Exception { checkParameter(DEVICE_ID, strDeviceId); DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -217,9 +218,9 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/device/{deviceId}", method = RequestMethod.POST) @ResponseBody - public Device assignDeviceToCustomer(@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + public Device assignDeviceToCustomer(@Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter("customerId", strCustomerId); checkParameter(DEVICE_ID, strDeviceId); @@ -235,7 +236,7 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/device/{deviceId}", method = RequestMethod.DELETE) @ResponseBody - public Device unassignDeviceFromCustomer(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + public Device unassignDeviceFromCustomer(@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -256,7 +257,7 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/public/device/{deviceId}", method = RequestMethod.POST) @ResponseBody - public Device assignDeviceToPublicCustomer(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + public Device assignDeviceToPublicCustomer(@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -269,7 +270,7 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/{deviceId}/credentials", method = RequestMethod.GET) @ResponseBody - public DeviceCredentials getDeviceCredentialsByDeviceId(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + public DeviceCredentials getDeviceCredentialsByDeviceId(@Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(DEVICE_ID, strDeviceId); DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); @@ -285,7 +286,7 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/device/credentials", method = RequestMethod.POST) @ResponseBody public DeviceCredentials updateDeviceCredentials( - @ApiParam(value = "A JSON value representing the device credentials.") + @Parameter(description = "A JSON value representing the device credentials.") @RequestBody DeviceCredentials deviceCredentials) throws ThingsboardException { checkNotNull(deviceCredentials); Device device = checkDeviceId(deviceCredentials.getDeviceId(), Operation.WRITE_CREDENTIALS); @@ -299,17 +300,17 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/tenant/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantDevices( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = DEVICE_TYPE_DESCRIPTION) + @Parameter(description = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "deviceProfileName", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -327,21 +328,21 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/tenant/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantDeviceInfos( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = DEVICE_TYPE_DESCRIPTION) + @Parameter(description = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @RequestParam(required = false) String deviceProfileId, - @ApiParam(value = DEVICE_ACTIVE_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ACTIVE_PARAM_DESCRIPTION) @RequestParam(required = false) Boolean active, - @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "deviceProfileName", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder ) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); @@ -364,7 +365,7 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/tenant/devices", params = {"deviceName"}, method = RequestMethod.GET) @ResponseBody public Device getTenantDevice( - @ApiParam(value = DEVICE_NAME_DESCRIPTION) + @Parameter(description = DEVICE_NAME_DESCRIPTION) @RequestParam String deviceName) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(deviceService.findDeviceByTenantIdAndName(tenantId, deviceName)); @@ -377,19 +378,19 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/customer/{customerId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerDevices( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) @PathVariable(CUSTOMER_ID) String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = DEVICE_TYPE_DESCRIPTION) + @Parameter(description = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "deviceProfileName", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -410,23 +411,23 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/customer/{customerId}/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerDeviceInfos( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) @PathVariable("customerId") String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = DEVICE_TYPE_DESCRIPTION) + @Parameter(description = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @RequestParam(required = false) String deviceProfileId, - @ApiParam(value = DEVICE_ACTIVE_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ACTIVE_PARAM_DESCRIPTION) @RequestParam(required = false) Boolean active, - @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "deviceProfileName", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -451,7 +452,7 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/devices", params = {"deviceIds"}, method = RequestMethod.GET) @ResponseBody public List getDevicesByIds( - @ApiParam(value = "A list of devices ids, separated by comma ','") + @Parameter(description = "A list of devices ids, separated by comma ','") @RequestParam("deviceIds") String[] strDeviceIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("deviceIds", strDeviceIds); SecurityUser user = getCurrentUser(); @@ -478,7 +479,7 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/devices", method = RequestMethod.POST) @ResponseBody public List findByQuery( - @ApiParam(value = "The device search query JSON") + @Parameter(description = "The device search query JSON") @RequestBody DeviceSearchQuery query) throws ThingsboardException, ExecutionException, InterruptedException { checkNotNull(query); checkNotNull(query.getParameters()); @@ -519,9 +520,9 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAuthority('CUSTOMER_USER')") @RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.POST) @ResponseBody - public DeferredResult claimDevice(@ApiParam(value = "Unique name of the device which is going to be claimed") + public DeferredResult claimDevice(@Parameter(description = "Unique name of the device which is going to be claimed") @PathVariable(DEVICE_NAME) String deviceName, - @ApiParam(value = "Claiming request which can optionally contain secret key") + @Parameter(description = "Claiming request which can optionally contain secret key") @RequestBody(required = false) ClaimRequest claimRequest) throws ThingsboardException { checkParameter(DEVICE_NAME, deviceName); final DeferredResult deferredResult = new DeferredResult<>(); @@ -568,7 +569,7 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/device/{deviceName}/claim", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public DeferredResult reClaimDevice(@ApiParam(value = "Unique name of the device which is going to be reclaimed") + public DeferredResult reClaimDevice(@Parameter(description = "Unique name of the device which is going to be reclaimed") @PathVariable(DEVICE_NAME) String deviceName) throws ThingsboardException { checkParameter(DEVICE_NAME, deviceName); final DeferredResult deferredResult = new DeferredResult<>(); @@ -608,9 +609,9 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/{tenantId}/device/{deviceId}", method = RequestMethod.POST) @ResponseBody - public Device assignDeviceToTenant(@ApiParam(value = TENANT_ID_PARAM_DESCRIPTION) + public Device assignDeviceToTenant(@Parameter(description = TENANT_ID_PARAM_DESCRIPTION) @PathVariable(TENANT_ID) String strTenantId, - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(TENANT_ID, strTenantId); checkParameter(DEVICE_ID, strDeviceId); @@ -631,13 +632,13 @@ public class DeviceController extends BaseController { "Second, remote edge service will receive a copy of assignment device " + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once device will be delivered to edge service, it's going to be available for usage on remote edge instance." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.POST) @ResponseBody - public Device assignDeviceToEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) + public Device assignDeviceToEdge(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(DEVICE_ID, strDeviceId); @@ -656,13 +657,13 @@ public class DeviceController extends BaseController { "Second, remote edge service will receive an 'unassign' command to remove device " + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once 'unassign' command will be delivered to edge service, it's going to remove device locally." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.DELETE) @ResponseBody - public Device unassignDeviceFromEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION) + public Device unassignDeviceFromEdge(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); checkParameter(DEVICE_ID, strDeviceId); @@ -681,27 +682,27 @@ public class DeviceController extends BaseController { @RequestMapping(value = "/edge/{edgeId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getEdgeDevices( - @ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = DEVICE_TYPE_DESCRIPTION) + @Parameter(description = DEVICE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @RequestParam(required = false) String deviceProfileId, - @ApiParam(value = DEVICE_ACTIVE_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ACTIVE_PARAM_DESCRIPTION) @RequestParam(required = false) Boolean active, - @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "deviceProfileName", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = "Timestamp. Devices with creation time before it won't be queried") + @Parameter(description = "Timestamp. Devices with creation time before it won't be queried") @RequestParam(required = false) Long startTime, - @ApiParam(value = "Timestamp. Devices with creation time after it won't be queried") + @Parameter(description = "Timestamp. Devices with creation time after it won't be queried") @RequestParam(required = false) Long endTime) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -728,11 +729,11 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/devices/count/{otaPackageType}/{deviceProfileId}", method = RequestMethod.GET) @ResponseBody - public Long countByDeviceProfileAndEmptyOtaPackage - (@ApiParam(value = "OTA package type", allowableValues = "FIRMWARE, SOFTWARE") - @PathVariable("otaPackageType") String otaPackageType, - @ApiParam(value = "Device Profile Id. I.g. '784f394c-42b6-435a-983c-b7beff2784f9'") - @PathVariable("deviceProfileId") String deviceProfileId) throws ThingsboardException { + public Long countByDeviceProfileAndEmptyOtaPackage( + @Parameter(description = "OTA package type", schema = @Schema(allowableValues = {"FIRMWARE", "SOFTWARE"})) + @PathVariable("otaPackageType") String otaPackageType, + @Parameter(description = "Device Profile Id. I.g. '784f394c-42b6-435a-983c-b7beff2784f9'") + @PathVariable("deviceProfileId") String deviceProfileId) throws ThingsboardException { checkParameter("OtaPackageType", otaPackageType); checkParameter("DeviceProfileId", deviceProfileId); return deviceService.countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage( diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java index c888d67252..093f44dcfd 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java @@ -15,12 +15,15 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -37,6 +40,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.device.profile.TbDeviceProfileService; @@ -50,18 +54,15 @@ import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFI import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_INFO_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH; -import static org.thingsboard.server.controller.ControllerConstants.TRANSPORT_TYPE_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; @RestController @@ -79,12 +80,12 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Device Profile (getDeviceProfileById)", notes = "Fetch the Device Profile object based on the provided Device Profile Id. " + "The server checks that the device profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile/{deviceProfileId}", method = RequestMethod.GET) @ResponseBody public DeviceProfile getDeviceProfileById( - @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_PROFILE_ID) String strDeviceProfileId) throws ThingsboardException { checkParameter(DEVICE_PROFILE_ID, strDeviceProfileId); DeviceProfileId deviceProfileId = new DeviceProfileId(toUUID(strDeviceProfileId)); @@ -94,12 +95,12 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Device Profile Info (getDeviceProfileInfoById)", notes = "Fetch the Device Profile Info object based on the provided Device Profile Id. " + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/deviceProfileInfo/{deviceProfileId}", method = RequestMethod.GET) @ResponseBody public DeviceProfileInfo getDeviceProfileInfoById( - @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_PROFILE_ID) String strDeviceProfileId) throws ThingsboardException { checkParameter(DEVICE_PROFILE_ID, strDeviceProfileId); DeviceProfileId deviceProfileId = new DeviceProfileId(toUUID(strDeviceProfileId)); @@ -109,7 +110,7 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Default Device Profile (getDefaultDeviceProfileInfo)", notes = "Fetch the Default Device Profile Info object. " + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/deviceProfileInfo/default", method = RequestMethod.GET) @ResponseBody @@ -123,12 +124,12 @@ public class DeviceProfileController extends BaseController { "The call is used for auto-complete in the UI forms. " + "The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. " + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile/devices/keys/timeseries", method = RequestMethod.GET) @ResponseBody public List getTimeseriesKeys( - @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @RequestParam(name = DEVICE_PROFILE_ID, required = false) String deviceProfileIdStr) throws ThingsboardException { DeviceProfileId deviceProfileId; if (StringUtils.isNotEmpty(deviceProfileIdStr)) { @@ -147,12 +148,12 @@ public class DeviceProfileController extends BaseController { "The call is used for auto-complete in the UI forms. " + "The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. " + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile/devices/keys/attributes", method = RequestMethod.GET) @ResponseBody public List getAttributesKeys( - @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @RequestParam(name = DEVICE_PROFILE_ID, required = false) String deviceProfileIdStr) throws ThingsboardException { DeviceProfileId deviceProfileId; if (StringUtils.isNotEmpty(deviceProfileIdStr)) { @@ -173,13 +174,12 @@ public class DeviceProfileController extends BaseController { "Device profile name is unique in the scope of tenant. Only one 'default' device profile may exist in scope of tenant." + DEVICE_PROFILE_DATA + "Remove 'id', 'tenantId' from the request body example (below) to create new Device Profile entity. " + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json", - consumes = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile", method = RequestMethod.POST) @ResponseBody public DeviceProfile saveDeviceProfile( - @ApiParam(value = "A JSON value representing the device profile.") + @Parameter(description = "A JSON value representing the device profile.") @RequestBody DeviceProfile deviceProfile) throws Exception { deviceProfile.setTenantId(getTenantId()); checkEntity(deviceProfile.getId(), deviceProfile, Resource.DEVICE_PROFILE); @@ -188,13 +188,12 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Delete device profile (deleteDeviceProfile)", notes = "Deletes the device profile. Referencing non-existing device profile Id will cause an error. " + - "Can't delete the device profile if it is referenced by existing devices." + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + "Can't delete the device profile if it is referenced by existing devices." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile/{deviceProfileId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) public void deleteDeviceProfile( - @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_PROFILE_ID) String strDeviceProfileId) throws ThingsboardException { checkParameter(DEVICE_PROFILE_ID, strDeviceProfileId); DeviceProfileId deviceProfileId = new DeviceProfileId(toUUID(strDeviceProfileId)); @@ -204,12 +203,12 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Make Device Profile Default (setDefaultDeviceProfile)", notes = "Marks device profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile/{deviceProfileId}/default", method = RequestMethod.POST) @ResponseBody public DeviceProfile setDefaultDeviceProfile( - @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_PROFILE_ID) String strDeviceProfileId) throws ThingsboardException { checkParameter(DEVICE_PROFILE_ID, strDeviceProfileId); DeviceProfileId deviceProfileId = new DeviceProfileId(toUUID(strDeviceProfileId)); @@ -221,20 +220,20 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Device Profiles (getDeviceProfiles)", notes = "Returns a page of devices profile objects owned by tenant. " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getDeviceProfiles( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = DEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "transportType", "description", "isDefault"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(deviceProfileService.findDeviceProfiles(getTenantId(), pageLink)); @@ -243,22 +242,22 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Device Profiles for transport type (getDeviceProfileInfos)", notes = "Returns a page of devices profile info objects owned by tenant. " + PAGE_DATA_PARAMETERS + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/deviceProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getDeviceProfileInfos( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = DEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = DEVICE_PROFILE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "transportType", "description", "isDefault"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = "Type of the transport", allowableValues = TRANSPORT_TYPE_ALLOWABLE_VALUES) + @Parameter(description = "Type of the transport", schema = @Schema(allowableValues = {"DEFAULT", "MQTT", "COAP", "LWM2M", "SNMP"})) @RequestParam(required = false) String transportType) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(deviceProfileService.findDeviceProfileInfos(getTenantId(), pageLink, transportType)); diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 0213ae5686..153b760531 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -16,8 +16,11 @@ package org.thingsboard.server.controller; import com.google.common.util.concurrent.ListenableFuture; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -54,6 +57,7 @@ import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportReques import org.thingsboard.server.common.data.sync.ie.importing.csv.BulkImportResult; import org.thingsboard.server.common.msg.edge.FromEdgeSyncResponse; import org.thingsboard.server.common.msg.edge.ToEdgeSyncRequest; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; @@ -64,7 +68,6 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; -import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -74,14 +77,12 @@ import java.util.stream.Collectors; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.EDGE_INFO_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.EDGE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.EDGE_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.EDGE_TYPE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -112,11 +113,11 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Edge (getEdgeById)", notes = "Get the Edge object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.GET) @ResponseBody - public Edge getEdgeById(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + public Edge getEdgeById(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); @@ -125,11 +126,11 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Edge Info (getEdgeInfoById)", notes = "Get the Edge Info object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/info/{edgeId}", method = RequestMethod.GET) @ResponseBody - public EdgeInfo getEdgeInfoById(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + public EdgeInfo getEdgeInfoById(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); @@ -144,11 +145,11 @@ public class EdgeController extends BaseController { "\n\nEdge name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the edge names and non-unique 'label' field for user-friendly visualization purposes." + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Edge entity. " + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge", method = RequestMethod.POST) @ResponseBody - public Edge saveEdge(@ApiParam(value = "A JSON value representing the edge.", required = true) + public Edge saveEdge(@Parameter(description = "A JSON value representing the edge.", required = true) @RequestBody Edge edge) throws Exception { TenantId tenantId = getTenantId(); edge.setTenantId(tenantId); @@ -174,7 +175,7 @@ public class EdgeController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public void deleteEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + public void deleteEdge(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); @@ -184,19 +185,19 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Tenant Edges (getEdges)", notes = "Returns a page of edges owned by tenant. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody - public PageData getEdges(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + public PageData getEdges(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = EDGE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = EDGE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EDGE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); TenantId tenantId = getCurrentUser().getTenantId(); @@ -205,13 +206,13 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Assign edge to customer (assignEdgeToCustomer)", notes = "Creates assignment of the edge to customer. Customer will be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/edge/{edgeId}", method = RequestMethod.POST) @ResponseBody - public Edge assignEdgeToCustomer(@ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) + public Edge assignEdgeToCustomer(@Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) @PathVariable("customerId") String strCustomerId, - @ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter("customerId", strCustomerId); checkParameter(EDGE_ID, strEdgeId); @@ -224,11 +225,11 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Unassign edge from customer (unassignEdgeFromCustomer)", notes = "Clears assignment of the edge to customer. Customer will not be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/edge/{edgeId}", method = RequestMethod.DELETE) @ResponseBody - public Edge unassignEdgeFromCustomer(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + public Edge unassignEdgeFromCustomer(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); @@ -245,11 +246,11 @@ public class EdgeController extends BaseController { notes = "Edge will be available for non-authorized (not logged-in) users. " + "This is useful to create dashboards that you plan to share/embed on a publicly available website. " + "However, users that are logged-in and belong to different tenant will not be able to access the edge." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/public/edge/{edgeId}", method = RequestMethod.POST) @ResponseBody - public Edge assignEdgeToPublicCustomer(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + public Edge assignEdgeToPublicCustomer(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); @@ -259,22 +260,22 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Tenant Edges (getTenantEdges)", notes = "Returns a page of edges owned by tenant. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantEdges( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = EDGE_TYPE_DESCRIPTION) + @Parameter(description = EDGE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = EDGE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = EDGE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EDGE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -288,22 +289,22 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Tenant Edge Infos (getTenantEdgeInfos)", notes = "Returns a page of edges info objects owned by tenant. " + PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantEdgeInfos( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = EDGE_TYPE_DESCRIPTION) + @Parameter(description = EDGE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = EDGE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = EDGE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EDGE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -317,11 +318,11 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Tenant Edge (getTenantEdge)", notes = "Requested edge must be owned by tenant or customer that the user belongs to. " + "Edge name is an unique property of edge. So it can be used to identify the edge." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/edges", params = {"edgeName"}, method = RequestMethod.GET) @ResponseBody - public Edge getTenantEdge(@ApiParam(value = "Unique name of the edge", required = true) + public Edge getTenantEdge(@Parameter(description = "Unique name of the edge", required = true) @RequestParam String edgeName) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(edgeService.findEdgeByTenantIdAndName(tenantId, edgeName)); @@ -330,13 +331,13 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Set root rule chain for provided edge (setEdgeRootRuleChain)", notes = "Change root rule chain of the edge to the new provided rule chain. \n" + "This operation will send a notification to update root rule chain on remote edge service." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/{ruleChainId}/root", method = RequestMethod.POST) @ResponseBody - public Edge setEdgeRootRuleChain(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + public Edge setEdgeRootRuleChain(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION, required = true) @PathVariable("ruleChainId") String strRuleChainId) throws Exception { checkParameter(EDGE_ID, strEdgeId); checkParameter("ruleChainId", strRuleChainId); @@ -350,24 +351,24 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Customer Edges (getCustomerEdges)", notes = "Returns a page of edges objects assigned to customer. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerEdges( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = EDGE_TYPE_DESCRIPTION) + @Parameter(description = EDGE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = EDGE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = EDGE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EDGE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); SecurityUser user = getCurrentUser(); @@ -386,24 +387,24 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Customer Edge Infos (getCustomerEdgeInfos)", notes = "Returns a page of edges info objects assigned to customer. " + - PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerEdgeInfos( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable("customerId") String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = EDGE_TYPE_DESCRIPTION) + @Parameter(description = EDGE_TYPE_DESCRIPTION) @RequestParam(required = false) String type, - @ApiParam(value = EDGE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = EDGE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EDGE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); SecurityUser user = getCurrentUser(); @@ -422,12 +423,12 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Edges By Ids (getEdgesByIds)", notes = "Requested edges must be owned by tenant or assigned to customer which user is performing the request." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edges", params = {"edgeIds"}, method = RequestMethod.GET) @ResponseBody public List getEdgesByIds( - @ApiParam(value = "A list of edges ids, separated by comma ','", required = true) + @Parameter(description = "A list of edges ids, separated by comma ','", required = true) @RequestParam("edgeIds") String[] strEdgeIds) throws ThingsboardException, ExecutionException, InterruptedException { checkArrayParameter("edgeIds", strEdgeIds); SecurityUser user = getCurrentUser(); @@ -451,7 +452,7 @@ public class EdgeController extends BaseController { notes = "Returns all edges that are related to the specific entity. " + "The entity id, relation type, edge types, depth of the search, and other query parameters defined using complex 'EdgeSearchQuery' object. " + "See 'Model' tab of the Parameters for more info." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edges", method = RequestMethod.POST) @ResponseBody @@ -477,7 +478,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Edge Types (getEdgeTypes)", notes = "Returns a set of unique edge types based on edges that are either owned by the tenant or assigned to the customer which user is performing the request." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/types", method = RequestMethod.GET) @ResponseBody @@ -493,7 +494,7 @@ public class EdgeController extends BaseController { "All entities that are assigned to particular edge are going to be send to remote edge service." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/sync/{edgeId}", method = RequestMethod.POST) - public DeferredResult syncEdge(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + public DeferredResult syncEdge(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("edgeId") String strEdgeId) throws ThingsboardException { checkParameter("edgeId", strEdgeId); final DeferredResult response = new DeferredResult<>(); @@ -523,7 +524,7 @@ public class EdgeController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/missingToRelatedRuleChains/{edgeId}", method = RequestMethod.GET) @ResponseBody - public String findMissingToRelatedRuleChains(@ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + public String findMissingToRelatedRuleChains(@Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("edgeId") String strEdgeId) throws ThingsboardException { EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); edgeId = checkNotNull(edgeId); @@ -534,7 +535,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Import the bulk of edges (processEdgesBulkImport)", notes = "There's an ability to import the bulk of edges using the only .csv file." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PostMapping("/edge/bulk_import") public BulkImportResult processEdgesBulkImport(@RequestBody BulkImportRequest request) throws Exception { @@ -549,12 +550,12 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Edge Docker Install Instructions (getEdgeDockerInstallInstructions)", notes = "Get a docker install instructions for provided edge id." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/instructions/{edgeId}", method = RequestMethod.GET) @ResponseBody public EdgeInstallInstructions getEdgeDockerInstallInstructions( - @ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("edgeId") String strEdgeId, HttpServletRequest request) throws ThingsboardException { EdgeId edgeId = new EdgeId(toUUID(strEdgeId)); diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java index fc85f439e0..fc95c02217 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -33,16 +35,15 @@ import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.edge.EdgeEventService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.permission.Operation; import static org.thingsboard.server.controller.ControllerConstants.EDGE_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.EDGE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; @@ -59,26 +60,26 @@ public class EdgeEventController extends BaseController { @ApiOperation(value = "Get Edge Events (getEdgeEvents)", notes = "Returns a page of edge events for the requested edge. " + - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/events", method = RequestMethod.GET) @ResponseBody public PageData getEdgeEvents( - @ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = "The case insensitive 'substring' filter based on the edge event type name.") + @Parameter(description = "The case insensitive 'substring' filter based on the edge event type name.") @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EDGE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "label", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = "Timestamp. Edge events with creation time before it won't be queried") + @Parameter(description = "Timestamp. Edge events with creation time before it won't be queried") @RequestParam(required = false) Long startTime, - @ApiParam(value = "Timestamp. Edge events with creation time after it won't be queried") + @Parameter(description = "Timestamp. Edge events with creation time after it won't be queried") @RequestParam(required = false) Long endTime) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); TenantId tenantId = getCurrentUser().getTenantId(); diff --git a/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java b/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java index b5c8e18ed2..b501771a3e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntitiesVersionControlController.java @@ -18,8 +18,8 @@ package org.thingsboard.server.controller; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; @@ -46,6 +46,7 @@ import org.thingsboard.server.common.data.sync.vc.VersionLoadResult; import org.thingsboard.server.common.data.sync.vc.VersionedEntityInfo; import org.thingsboard.server.common.data.sync.vc.request.create.VersionCreateRequest; import org.thingsboard.server.common.data.sync.vc.request.load.VersionLoadRequest; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; @@ -67,7 +68,6 @@ import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -189,7 +189,7 @@ public class EntitiesVersionControlController extends BaseController { MARKDOWN_CODE_BLOCK_END + TENANT_AUTHORITY_PARAGRAPH) @GetMapping(value = "/version/{requestId}/status") - public VersionCreationResult getVersionCreateRequestStatus(@ApiParam(value = VC_REQUEST_ID_PARAM_DESCRIPTION, required = true) + public VersionCreationResult getVersionCreateRequestStatus(@Parameter(description = VC_REQUEST_ID_PARAM_DESCRIPTION, required = true) @PathVariable UUID requestId) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.WRITE); return versionControlService.getVersionCreateStatus(getCurrentUser(), requestId); @@ -232,21 +232,21 @@ public class EntitiesVersionControlController extends BaseController { MARKDOWN_CODE_BLOCK_END + TENANT_AUTHORITY_PARAGRAPH) @GetMapping(value = "/version/{entityType}/{externalEntityUuid}", params = {"branch", "pageSize", "page"}) - public DeferredResult> listEntityVersions(@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) + public DeferredResult> listEntityVersions(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable EntityType entityType, - @ApiParam(value = "A string value representing external entity id. This is `externalId` property of an entity, or otherwise if not set - simply id of this entity.") + @Parameter(description = "A string value representing external entity id. This is `externalId` property of an entity, or otherwise if not set - simply id of this entity.") @PathVariable UUID externalEntityUuid, - @ApiParam(value = BRANCH_PARAM_DESCRIPTION) + @Parameter(description = BRANCH_PARAM_DESCRIPTION) @RequestParam String branch, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ENTITY_VERSION_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ENTITY_VERSION_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = "timestamp") + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = "timestamp")) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); EntityId externalEntityId = EntityIdFactory.getByTypeAndUuid(entityType, externalEntityUuid); @@ -261,19 +261,19 @@ public class EntitiesVersionControlController extends BaseController { "The response structure is the same as for `listEntityVersions` API method." + TENANT_AUTHORITY_PARAGRAPH) @GetMapping(value = "/version/{entityType}", params = {"branch", "pageSize", "page"}) - public DeferredResult> listEntityTypeVersions(@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) + public DeferredResult> listEntityTypeVersions(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable EntityType entityType, - @ApiParam(value = BRANCH_PARAM_DESCRIPTION, required = true) + @Parameter(description = BRANCH_PARAM_DESCRIPTION, required = true) @RequestParam String branch, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ENTITY_VERSION_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ENTITY_VERSION_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = "timestamp") + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = "timestamp")) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -286,17 +286,17 @@ public class EntitiesVersionControlController extends BaseController { "The response format is the same as for `listEntityVersions` API method." + TENANT_AUTHORITY_PARAGRAPH) @GetMapping(value = "/version", params = {"branch", "pageSize", "page"}) - public DeferredResult> listVersions(@ApiParam(value = BRANCH_PARAM_DESCRIPTION, required = true) + public DeferredResult> listVersions(@Parameter(description = BRANCH_PARAM_DESCRIPTION, required = true) @RequestParam String branch, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ENTITY_VERSION_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ENTITY_VERSION_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = "timestamp") + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = "timestamp")) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -310,9 +310,9 @@ public class EntitiesVersionControlController extends BaseController { "Entities order will be the same as in the repository." + TENANT_AUTHORITY_PARAGRAPH) @GetMapping(value = "/entity/{entityType}/{versionId}") - public DeferredResult> listEntitiesAtVersion(@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) + public DeferredResult> listEntitiesAtVersion(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable EntityType entityType, - @ApiParam(value = VERSION_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = VERSION_ID_PARAM_DESCRIPTION, required = true) @PathVariable String versionId) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); return wrapFuture(versionControlService.listEntitiesAtVersion(getTenantId(), versionId, entityType)); @@ -324,7 +324,7 @@ public class EntitiesVersionControlController extends BaseController { "Returned entities order will be the same as in the repository." + TENANT_AUTHORITY_PARAGRAPH) @GetMapping(value = "/entity/{versionId}") - public DeferredResult> listAllEntitiesAtVersion(@ApiParam(value = VERSION_ID_PARAM_DESCRIPTION, required = true) + public DeferredResult> listAllEntitiesAtVersion(@Parameter(description = VERSION_ID_PARAM_DESCRIPTION, required = true) @PathVariable String versionId) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); return wrapFuture(versionControlService.listAllEntitiesAtVersion(getTenantId(), versionId)); @@ -337,11 +337,11 @@ public class EntitiesVersionControlController extends BaseController { "`hasCredentials` (whether stored device data has credentials)." + TENANT_AUTHORITY_PARAGRAPH) @GetMapping("/info/{versionId}/{entityType}/{externalEntityUuid}") - public DeferredResult getEntityDataInfo(@ApiParam(value = VERSION_ID_PARAM_DESCRIPTION, required = true) + public DeferredResult getEntityDataInfo(@Parameter(description = VERSION_ID_PARAM_DESCRIPTION, required = true) @PathVariable String versionId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable EntityType entityType, - @ApiParam(value = "A string value representing external entity id", required = true) + @Parameter(description = "A string value representing external entity id", required = true) @PathVariable UUID externalEntityUuid) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, externalEntityUuid); @@ -353,11 +353,11 @@ public class EntitiesVersionControlController extends BaseController { "Entity data structure is the same as stored in a repository. " + TENANT_AUTHORITY_PARAGRAPH) @GetMapping(value = "/diff/{entityType}/{internalEntityUuid}", params = {"versionId"}) - public DeferredResult compareEntityDataToVersion(@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) + public DeferredResult compareEntityDataToVersion(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable EntityType entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable UUID internalEntityUuid, - @ApiParam(value = VERSION_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = VERSION_ID_PARAM_DESCRIPTION, required = true) @RequestParam String versionId) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.READ); EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, internalEntityUuid); @@ -466,7 +466,7 @@ public class EntitiesVersionControlController extends BaseController { TENANT_AUTHORITY_PARAGRAPH ) @GetMapping(value = "/entity/{requestId}/status") - public VersionLoadResult getVersionLoadRequestStatus(@ApiParam(value = VC_REQUEST_ID_PARAM_DESCRIPTION, required = true) + public VersionLoadResult getVersionLoadRequestStatus(@Parameter(description = VC_REQUEST_ID_PARAM_DESCRIPTION, required = true) @PathVariable UUID requestId) throws Exception { accessControlService.checkPermission(getCurrentUser(), Resource.VERSION_CONTROL, Operation.WRITE); return versionControlService.getVersionLoadStatus(getCurrentUser(), requestId); diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityQueryController.java b/application/src/main/java/org/thingsboard/server/controller/EntityQueryController.java index fbb8901ca9..539d6a81f4 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityQueryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityQueryController.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -38,6 +37,7 @@ import org.thingsboard.server.common.data.query.EntityCountQuery; import org.thingsboard.server.common.data.query.EntityData; import org.thingsboard.server.common.data.query.EntityDataPageLink; import org.thingsboard.server.common.data.query.EntityDataQuery; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.query.EntityQueryService; import org.thingsboard.server.service.security.permission.Operation; @@ -61,7 +61,7 @@ public class EntityQueryController extends BaseController { @RequestMapping(value = "/entitiesQuery/count", method = RequestMethod.POST) @ResponseBody public long countEntitiesByQuery( - @ApiParam(value = "A JSON value representing the entity count query. See API call notes above for more details.") + @Parameter(description = "A JSON value representing the entity count query. See API call notes above for more details.") @RequestBody EntityCountQuery query) throws ThingsboardException { checkNotNull(query); return this.entityQueryService.countEntitiesByQuery(getCurrentUser(), query); @@ -72,7 +72,7 @@ public class EntityQueryController extends BaseController { @RequestMapping(value = "/entitiesQuery/find", method = RequestMethod.POST) @ResponseBody public PageData findEntityDataByQuery( - @ApiParam(value = "A JSON value representing the entity data query. See API call notes above for more details.") + @Parameter(description = "A JSON value representing the entity data query. See API call notes above for more details.") @RequestBody EntityDataQuery query) throws ThingsboardException { checkNotNull(query); return this.entityQueryService.findEntityDataByQuery(getCurrentUser(), query); @@ -83,7 +83,7 @@ public class EntityQueryController extends BaseController { @RequestMapping(value = "/alarmsQuery/find", method = RequestMethod.POST) @ResponseBody public PageData findAlarmDataByQuery( - @ApiParam(value = "A JSON value representing the alarm data query. See API call notes above for more details.") + @Parameter(description = "A JSON value representing the alarm data query. See API call notes above for more details.") @RequestBody AlarmDataQuery query) throws ThingsboardException { checkNotNull(query); checkNotNull(query.getPageLink()); @@ -98,7 +98,7 @@ public class EntityQueryController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarmsQuery/count", method = RequestMethod.POST) @ResponseBody - public long countAlarmsByQuery(@ApiParam(value = "A JSON value representing the alarm count query.") + public long countAlarmsByQuery(@Parameter(description = "A JSON value representing the alarm count query.") @RequestBody AlarmCountQuery query) throws ThingsboardException { checkNotNull(query); UserId assigneeId = query.getAssigneeId(); @@ -114,11 +114,11 @@ public class EntityQueryController extends BaseController { @RequestMapping(value = "/entitiesQuery/find/keys", method = RequestMethod.POST) @ResponseBody public DeferredResult findEntityTimeseriesAndAttributesKeysByQuery( - @ApiParam(value = "A JSON value representing the entity data query. See API call notes above for more details.") + @Parameter(description = "A JSON value representing the entity data query. See API call notes above for more details.") @RequestBody EntityDataQuery query, - @ApiParam(value = "Include all unique time-series keys to the result.") + @Parameter(description = "Include all unique time-series keys to the result.") @RequestParam("timeseries") boolean isTimeseries, - @ApiParam(value = "Include all unique attribute keys to the result.") + @Parameter(description = "Include all unique attribute keys to the result.") @RequestParam("attributes") boolean isAttributes) throws ThingsboardException { TenantId tenantId = getTenantId(); checkNotNull(query); diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java index 08448f1d28..cb17661e4a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java @@ -15,8 +15,9 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -35,6 +36,7 @@ import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelationInfo; import org.thingsboard.server.common.data.relation.EntityRelationsQuery; import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.entity.relation.TbEntityRelationService; import org.thingsboard.server.service.security.model.SecurityUser; @@ -79,7 +81,7 @@ public class EntityRelationController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relation", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) - public void saveRelation(@ApiParam(value = "A JSON value representing the relation.", required = true) + public void saveRelation(@Parameter(description = "A JSON value representing the relation.", required = true) @RequestBody EntityRelation relation) throws ThingsboardException { checkNotNull(relation); checkCanCreateRelation(relation.getFrom()); @@ -96,12 +98,12 @@ public class EntityRelationController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relation", method = RequestMethod.DELETE, params = {FROM_ID, FROM_TYPE, RELATION_TYPE, TO_ID, TO_TYPE}) @ResponseStatus(value = HttpStatus.OK) - public void deleteRelation(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, - @ApiParam(value = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(RELATION_TYPE) String strRelationType, - @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType) throws ThingsboardException { + public void deleteRelation(@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, + @Parameter(description = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(RELATION_TYPE) String strRelationType, + @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType) throws ThingsboardException { checkParameter(FROM_ID, strFromId); checkParameter(FROM_TYPE, strFromType); checkParameter(RELATION_TYPE, strRelationType); @@ -123,8 +125,8 @@ public class EntityRelationController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN','TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.DELETE, params = {"entityId", "entityType"}) @ResponseStatus(value = HttpStatus.OK) - public void deleteRelations(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam("entityId") String strId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam("entityType") String strType) throws ThingsboardException { + public void deleteRelations(@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam("entityId") String strId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam("entityType") String strType) throws ThingsboardException { checkParameter("entityId", strId); checkParameter("entityType", strType); EntityId entityId = EntityIdFactory.getByTypeAndId(strType, strId); @@ -134,16 +136,16 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get Relation (getRelation)", notes = "Returns relation object between two specified entities if present. Otherwise throws exception. " + SECURITY_CHECKS_ENTITIES_DESCRIPTION, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relation", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE, RELATION_TYPE, TO_ID, TO_TYPE}) @ResponseBody - public EntityRelation getRelation(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, - @ApiParam(value = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(RELATION_TYPE) String strRelationType, - @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType) throws ThingsboardException { + public EntityRelation getRelation(@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, + @Parameter(description = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(RELATION_TYPE) String strRelationType, + @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType) throws ThingsboardException { checkParameter(FROM_ID, strFromId); checkParameter(FROM_TYPE, strFromType); checkParameter(RELATION_TYPE, strRelationType); @@ -160,13 +162,13 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relations (findByFrom)", notes = "Returns list of relation objects for the specified entity by the 'from' direction. " + SECURITY_CHECKS_ENTITY_DESCRIPTION, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE}) @ResponseBody - public List findByFrom(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, - @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) + public List findByFrom(@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, + @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { checkParameter(FROM_ID, strFromId); checkParameter(FROM_TYPE, strFromType); @@ -179,13 +181,13 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relation Infos (findInfoByFrom)", notes = "Returns list of relation info objects for the specified entity by the 'from' direction. " + SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE}) @ResponseBody - public List findInfoByFrom(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, - @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) + public List findInfoByFrom(@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, + @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException, ExecutionException, InterruptedException { checkParameter(FROM_ID, strFromId); checkParameter(FROM_TYPE, strFromType); @@ -198,14 +200,14 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relations (findByFrom)", notes = "Returns list of relation objects for the specified entity by the 'from' direction and relation type. " + SECURITY_CHECKS_ENTITY_DESCRIPTION, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE, RELATION_TYPE}) @ResponseBody - public List findByFrom(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, - @ApiParam(value = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(RELATION_TYPE) String strRelationType, - @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) + public List findByFrom(@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_ID) String strFromId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(FROM_TYPE) String strFromType, + @Parameter(description = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(RELATION_TYPE) String strRelationType, + @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { checkParameter(FROM_ID, strFromId); checkParameter(FROM_TYPE, strFromType); @@ -219,13 +221,13 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relations (findByTo)", notes = "Returns list of relation objects for the specified entity by the 'to' direction. " + SECURITY_CHECKS_ENTITY_DESCRIPTION, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {TO_ID, TO_TYPE}) @ResponseBody - public List findByTo(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType, - @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) + public List findByTo(@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType, + @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { checkParameter(TO_ID, strToId); checkParameter(TO_TYPE, strToType); @@ -238,13 +240,13 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relation Infos (findInfoByTo)", notes = "Returns list of relation info objects for the specified entity by the 'to' direction. " + SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {TO_ID, TO_TYPE}) @ResponseBody - public List findInfoByTo(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType, - @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) + public List findInfoByTo(@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType, + @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException, ExecutionException, InterruptedException { checkParameter(TO_ID, strToId); checkParameter(TO_TYPE, strToType); @@ -257,14 +259,14 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relations (findByTo)", notes = "Returns list of relation objects for the specified entity by the 'to' direction and relation type. " + SECURITY_CHECKS_ENTITY_DESCRIPTION, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {TO_ID, TO_TYPE, RELATION_TYPE}) @ResponseBody - public List findByTo(@ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType, - @ApiParam(value = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(RELATION_TYPE) String strRelationType, - @ApiParam(value = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) + public List findByTo(@Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TO_ID) String strToId, + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(TO_TYPE) String strToType, + @Parameter(description = RELATION_TYPE_PARAM_DESCRIPTION, required = true) @RequestParam(RELATION_TYPE) String strRelationType, + @Parameter(description = RELATION_TYPE_GROUP_PARAM_DESCRIPTION) @RequestParam(value = "relationTypeGroup", required = false) String strRelationTypeGroup) throws ThingsboardException { checkParameter(TO_ID, strToId); checkParameter(TO_TYPE, strToType); @@ -278,11 +280,11 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Find related entities (findByQuery)", notes = "Returns all entities that are related to the specific entity. " + "The entity id, relation type, entity types, depth of the search, and other query parameters defined using complex 'EntityRelationsQuery' object. " + - "See 'Model' tab of the Parameters for more info.", produces = MediaType.APPLICATION_JSON_VALUE) + "See 'Model' tab of the Parameters for more info.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.POST) @ResponseBody - public List findByQuery(@ApiParam(value = "A JSON value representing the entity relations query object.", required = true) + public List findByQuery(@Parameter(description = "A JSON value representing the entity relations query object.", required = true) @RequestBody EntityRelationsQuery query) throws ThingsboardException, ExecutionException, InterruptedException { checkNotNull(query); checkNotNull(query.getParameters()); @@ -294,11 +296,11 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Find related entity infos (findInfoByQuery)", notes = "Returns all entity infos that are related to the specific entity. " + "The entity id, relation type, entity types, depth of the search, and other query parameters defined using complex 'EntityRelationsQuery' object. " + - "See 'Model' tab of the Parameters for more info. " + RELATION_INFO_DESCRIPTION, produces = MediaType.APPLICATION_JSON_VALUE) + "See 'Model' tab of the Parameters for more info. " + RELATION_INFO_DESCRIPTION, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations/info", method = RequestMethod.POST) @ResponseBody - public List findInfoByQuery(@ApiParam(value = "A JSON value representing the entity relations query object.", required = true) + public List findInfoByQuery(@Parameter(description = "A JSON value representing the entity relations query object.", required = true) @RequestBody EntityRelationsQuery query) throws ThingsboardException, ExecutionException, InterruptedException { checkNotNull(query); checkNotNull(query.getParameters()); diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java index b2904a0989..bff71bb43b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -16,8 +16,10 @@ package org.thingsboard.server.controller; import com.google.common.util.concurrent.ListenableFuture; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -45,6 +47,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -66,15 +69,12 @@ import static org.thingsboard.server.controller.ControllerConstants.EDGE_UNASSIG import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_INFO_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_INFO_SORT_PROPERTY_ALLOWABLE_VALUES; -import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ENTITY_VIEW_TYPE; import static org.thingsboard.server.controller.ControllerConstants.MODEL_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -98,12 +98,12 @@ public class EntityViewController extends BaseController { @ApiOperation(value = "Get entity view (getEntityViewById)", notes = "Fetch the EntityView object based on the provided entity view id. " + ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET) @ResponseBody public EntityView getEntityViewById( - @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_ID_PARAM_DESCRIPTION) @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(ENTITY_VIEW_ID, strEntityViewId); return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId)), Operation.READ); @@ -112,12 +112,12 @@ public class EntityViewController extends BaseController { @ApiOperation(value = "Get Entity View info (getEntityViewInfoById)", notes = "Fetch the Entity View info object based on the provided Entity View Id. " + ENTITY_VIEW_INFO_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityView/info/{entityViewId}", method = RequestMethod.GET) @ResponseBody public EntityViewInfo getEntityViewInfoById( - @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_ID_PARAM_DESCRIPTION) @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(ENTITY_VIEW_ID, strEntityViewId); EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); @@ -128,12 +128,12 @@ public class EntityViewController extends BaseController { notes = ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Entity View entity." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityView", method = RequestMethod.POST) @ResponseBody public EntityView saveEntityView( - @ApiParam(value = "A JSON object representing the entity view.") + @Parameter(description = "A JSON object representing the entity view.") @RequestBody EntityView entityView) throws Exception { entityView.setTenantId(getCurrentUser().getTenantId()); EntityView existingEntityView = null; @@ -153,7 +153,7 @@ public class EntityViewController extends BaseController { @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) public void deleteEntityView( - @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_ID_PARAM_DESCRIPTION) @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(ENTITY_VIEW_ID, strEntityViewId); EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); @@ -163,12 +163,12 @@ public class EntityViewController extends BaseController { @ApiOperation(value = "Get Entity View by name (getTenantEntityView)", notes = "Fetch the Entity View object based on the tenant id and entity view name. " + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/entityViews", params = {"entityViewName"}, method = RequestMethod.GET) @ResponseBody public EntityView getTenantEntityView( - @ApiParam(value = "Entity View name") + @Parameter(description = "Entity View name") @RequestParam String entityViewName) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); return checkNotNull(entityViewService.findEntityViewByTenantIdAndName(tenantId, entityViewName)); @@ -180,9 +180,9 @@ public class EntityViewController extends BaseController { @RequestMapping(value = "/customer/{customerId}/entityView/{entityViewId}", method = RequestMethod.POST) @ResponseBody public EntityView assignEntityViewToCustomer( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION) @PathVariable(CUSTOMER_ID) String strCustomerId, - @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_ID_PARAM_DESCRIPTION) @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(CUSTOMER_ID, strCustomerId); checkParameter(ENTITY_VIEW_ID, strEntityViewId); @@ -202,7 +202,7 @@ public class EntityViewController extends BaseController { @RequestMapping(value = "/customer/entityView/{entityViewId}", method = RequestMethod.DELETE) @ResponseBody public EntityView unassignEntityViewFromCustomer( - @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_ID_PARAM_DESCRIPTION) @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(ENTITY_VIEW_ID, strEntityViewId); EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); @@ -223,19 +223,19 @@ public class EntityViewController extends BaseController { @RequestMapping(value = "/customer/{customerId}/entityViews", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerEntityViews( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) @PathVariable(CUSTOMER_ID) String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ENTITY_VIEW_TYPE) + @Parameter(description = ENTITY_VIEW_TYPE) @RequestParam(required = false) String type, - @ApiParam(value = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ENTITY_VIEW_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name, type"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter(CUSTOMER_ID, strCustomerId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -256,19 +256,19 @@ public class EntityViewController extends BaseController { @RequestMapping(value = "/customer/{customerId}/entityViewInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerEntityViewInfos( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) @PathVariable(CUSTOMER_ID) String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ENTITY_VIEW_TYPE) + @Parameter(description = ENTITY_VIEW_TYPE) @RequestParam(required = false) String type, - @ApiParam(value = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ENTITY_VIEW_INFO_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -289,17 +289,17 @@ public class EntityViewController extends BaseController { @RequestMapping(value = "/tenant/entityViews", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantEntityViews( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ENTITY_VIEW_TYPE) + @Parameter(description = ENTITY_VIEW_TYPE) @RequestParam(required = false) String type, - @ApiParam(value = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ENTITY_VIEW_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name, type"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -318,17 +318,17 @@ public class EntityViewController extends BaseController { @RequestMapping(value = "/tenant/entityViewInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantEntityViewInfos( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = ENTITY_VIEW_TYPE) + @Parameter(description = ENTITY_VIEW_TYPE) @RequestParam(required = false) String type, - @ApiParam(value = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = ENTITY_VIEW_INFO_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "type", "customerTitle"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -347,7 +347,7 @@ public class EntityViewController extends BaseController { @RequestMapping(value = "/entityViews", method = RequestMethod.POST) @ResponseBody public List findByQuery( - @ApiParam(value = "The entity view search query JSON") + @Parameter(description = "The entity view search query JSON") @RequestBody EntityViewSearchQuery query) throws ThingsboardException, ExecutionException, InterruptedException { checkNotNull(query); checkNotNull(query.getParameters()); @@ -386,7 +386,7 @@ public class EntityViewController extends BaseController { @RequestMapping(value = "/customer/public/entityView/{entityViewId}", method = RequestMethod.POST) @ResponseBody public EntityView assignEntityViewToPublicCustomer( - @ApiParam(value = ENTITY_VIEW_ID_PARAM_DESCRIPTION) + @Parameter(description = ENTITY_VIEW_ID_PARAM_DESCRIPTION) @PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(ENTITY_VIEW_ID, strEntityViewId); EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); @@ -400,7 +400,7 @@ public class EntityViewController extends BaseController { "Second, remote edge service will receive a copy of assignment entity view " + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once entity view will be delivered to edge service, it's going to be available for usage on remote edge instance.", - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/entityView/{entityViewId}", method = RequestMethod.POST) @ResponseBody @@ -425,7 +425,7 @@ public class EntityViewController extends BaseController { "Second, remote edge service will receive an 'unassign' command to remove entity view " + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once 'unassign' command will be delivered to edge service, it's going to remove entity view locally.", - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/entityView/{entityViewId}", method = RequestMethod.DELETE) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/EventController.java b/application/src/main/java/org/thingsboard/server/controller/EventController.java index ec75f981a7..09ef2e9d05 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EventController.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -39,6 +41,7 @@ import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.permission.Operation; @@ -52,7 +55,6 @@ import static org.thingsboard.server.controller.ControllerConstants.EVENT_DEBUG_ import static org.thingsboard.server.controller.ControllerConstants.EVENT_END_TIME_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.EVENT_ERROR_FILTER_OBJ; import static org.thingsboard.server.controller.ControllerConstants.EVENT_LC_EVENT_FILTER_OBJ; -import static org.thingsboard.server.controller.ControllerConstants.EVENT_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.EVENT_START_TIME_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.EVENT_STATS_FILTER_OBJ; import static org.thingsboard.server.controller.ControllerConstants.EVENT_TEXT_SEARCH_DESCRIPTION; @@ -60,7 +62,6 @@ import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID; @@ -107,32 +108,32 @@ public class EventController extends BaseController { @ApiOperation(value = "Get Events by type (getEvents)", notes = "Returns a page of events for specified entity by specifying event type. " + - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/events/{entityType}/{entityId}/{eventType}", method = RequestMethod.GET) @ResponseBody public PageData getEvents( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_TYPE) String strEntityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_ID) String strEntityId, - @ApiParam(value = "A string value representing event type", example = "STATS", required = true) + @Parameter(description = "A string value representing event type", example = "STATS", required = true) @PathVariable("eventType") String eventType, - @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = TENANT_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TENANT_ID) String strTenantId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = EVENT_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = EVENT_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EVENT_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"ts", "id"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = EVENT_START_TIME_DESCRIPTION) + @Parameter(description = EVENT_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = EVENT_END_TIME_DESCRIPTION) + @Parameter(description = EVENT_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime) throws ThingsboardException { checkParameter("EntityId", strEntityId); checkParameter("EntityType", strEntityType); @@ -149,30 +150,30 @@ public class EventController extends BaseController { "The call was deprecated to improve the performance of the system. " + "Current implementation will return 'Lifecycle' events only. " + "Use 'Get events by type' or 'Get events by filter' instead. " + - PAGE_DATA_PARAMETERS, produces = MediaType.APPLICATION_JSON_VALUE) + PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.GET) @ResponseBody public PageData getEvents( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_TYPE) String strEntityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_ID) String strEntityId, - @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = TENANT_ID_PARAM_DESCRIPTION, required = true) @RequestParam("tenantId") String strTenantId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = EVENT_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = EVENT_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EVENT_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"ts", "id"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = EVENT_START_TIME_DESCRIPTION) + @Parameter(description = EVENT_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = EVENT_END_TIME_DESCRIPTION) + @Parameter(description = EVENT_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime) throws ThingsboardException { checkParameter("EntityId", strEntityId); checkParameter("EntityType", strEntityType); @@ -190,32 +191,32 @@ public class EventController extends BaseController { notes = "Returns a page of events for the chosen entity by specifying the event filter. " + PAGE_DATA_PARAMETERS + NEW_LINE + EVENT_FILTER_DEFINITION, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.POST) @ResponseBody public PageData getEvents( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_TYPE) String strEntityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_ID) String strEntityId, - @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = TENANT_ID_PARAM_DESCRIPTION, required = true) @RequestParam(TENANT_ID) String strTenantId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = "A JSON value representing the event filter.", required = true) + @Parameter(description = "A JSON value representing the event filter.", required = true) @RequestBody EventFilter eventFilter, - @ApiParam(value = EVENT_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = EVENT_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = EVENT_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"ts", "id"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder, - @ApiParam(value = EVENT_START_TIME_DESCRIPTION) + @Parameter(description = EVENT_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = EVENT_END_TIME_DESCRIPTION) + @Parameter(description = EVENT_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime) throws ThingsboardException { checkParameter("EntityId", strEntityId); checkParameter("EntityType", strEntityType); @@ -232,15 +233,15 @@ public class EventController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/events/{entityType}/{entityId}/clear", method = RequestMethod.POST) @ResponseStatus(HttpStatus.OK) - public void clearEvents(@ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) + public void clearEvents(@Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_TYPE) String strEntityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable(ENTITY_ID) String strEntityId, - @ApiParam(value = EVENT_START_TIME_DESCRIPTION) + @Parameter(description = EVENT_START_TIME_DESCRIPTION) @RequestParam(required = false) Long startTime, - @ApiParam(value = EVENT_END_TIME_DESCRIPTION) + @Parameter(description = EVENT_END_TIME_DESCRIPTION) @RequestParam(required = false) Long endTime, - @ApiParam(value = EVENT_FILTER_DEFINITION) + @Parameter(description = EVENT_FILTER_DEFINITION) @RequestBody EventFilter eventFilter) throws ThingsboardException { checkParameter("EntityId", strEntityId); checkParameter("EntityType", strEntityType); diff --git a/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java b/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java index 8949cd95dd..433eea639e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java +++ b/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java @@ -15,11 +15,13 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.http.MediaType; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -33,6 +35,7 @@ import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest; import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MServerSecurityConfigDefault; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.service.lwm2m.LwM2MService; import java.util.Map; @@ -57,12 +60,12 @@ public class Lwm2mController extends BaseController { @ApiOperation(value = "Get Lwm2m Bootstrap SecurityInfo (getLwm2mBootstrapSecurityInfo)", notes = "Get the Lwm2m Bootstrap SecurityInfo object (of the current server) based on the provided isBootstrapServer parameter. If isBootstrapServer == true, get the parameters of the current Bootstrap Server. If isBootstrapServer == false, get the parameters of the current Lwm2m Server. Used for client settings when starting the client in Bootstrap mode. " + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{isBootstrapServer}", method = RequestMethod.GET) @ResponseBody public LwM2MServerSecurityConfigDefault getLwm2mBootstrapSecurityInfo( - @ApiParam(value = IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION) + @Parameter(description = IS_BOOTSTRAP_SERVER_PARAM_DESCRIPTION) @PathVariable(IS_BOOTSTRAP_SERVER) boolean bootstrapServer) throws ThingsboardException { return lwM2MService.getServerSecurityInfo(bootstrapServer); } diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationController.java index 5893410b2a..e2a1f1a417 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationController.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; @@ -55,6 +55,7 @@ import org.thingsboard.server.common.data.notification.template.NotificationTemp import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.SortOrder; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.notification.NotificationRequestService; import org.thingsboard.server.dao.notification.NotificationService; import org.thingsboard.server.dao.notification.NotificationSettingsService; @@ -66,7 +67,6 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; -import jakarta.validation.Valid; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; @@ -158,17 +158,17 @@ public class NotificationController extends BaseController { "}\n```") @GetMapping("/notifications") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - public PageData getNotifications(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + public PageData getNotifications(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = "Case-insensitive 'substring' filter based on notification subject or text") + @Parameter(description = "Case-insensitive 'substring' filter based on notification subject or text") @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION) + @Parameter(description = SORT_PROPERTY_DESCRIPTION) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION) + @Parameter(description = SORT_ORDER_DESCRIPTION) @RequestParam(required = false) String sortOrder, - @ApiParam(value = "To search for unread notifications only") + @Parameter(description = "To search for unread notifications only") @RequestParam(defaultValue = "false") boolean unreadOnly, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { // no permissions @@ -266,7 +266,7 @@ public class NotificationController extends BaseController { @PostMapping("/notification/request/preview") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") public NotificationRequestPreview getNotificationRequestPreview(@RequestBody @Valid NotificationRequest request, - @ApiParam(value = "Amount of the recipients to show in preview") + @Parameter(description = "Amount of the recipients to show in preview") @RequestParam(defaultValue = "20") int recipientsPreviewSize, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { NotificationTemplate template; @@ -361,15 +361,15 @@ public class NotificationController extends BaseController { SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @GetMapping("/notification/requests") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") - public PageData getNotificationRequests(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + public PageData getNotificationRequests(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = "Case-insensitive 'substring' filed based on the used template name") + @Parameter(description = "Case-insensitive 'substring' filed based on the used template name") @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION) + @Parameter(description = SORT_PROPERTY_DESCRIPTION) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION) + @Parameter(description = SORT_ORDER_DESCRIPTION) @RequestParam(required = false) String sortOrder, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { // generic permission diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java index 06eabbc215..457fac9304 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationRuleController.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; @@ -38,12 +38,12 @@ import org.thingsboard.server.common.data.notification.rule.trigger.Notification import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.notification.NotificationRuleService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; -import jakarta.validation.Valid; import java.util.UUID; import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_CODE_BLOCK_END; @@ -150,15 +150,15 @@ public class NotificationRuleController extends BaseController { SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @GetMapping("/rules") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") - public PageData getNotificationRules(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + public PageData getNotificationRules(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = "Case-insensitive 'substring' filter based on rule's name") + @Parameter(description = "Case-insensitive 'substring' filter based on rule's name") @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION) + @Parameter(description = SORT_PROPERTY_DESCRIPTION) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION) + @Parameter(description = SORT_ORDER_DESCRIPTION) @RequestParam(required = false) String sortOrder, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { // generic permission diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java index 6b13e9de9d..1dd16ea462 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationTargetController.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; @@ -48,12 +48,12 @@ import org.thingsboard.server.common.data.notification.targets.platform.UserList import org.thingsboard.server.common.data.notification.targets.platform.UsersFilter; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.notification.NotificationTargetService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; -import jakarta.validation.Valid; import java.util.Arrays; import java.util.List; import java.util.UUID; @@ -134,9 +134,9 @@ public class NotificationTargetController extends BaseController { @PostMapping("/target/recipients") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") public PageData getRecipientsForNotificationTargetConfig(@RequestBody NotificationTarget notificationTarget, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { // generic permission @@ -156,7 +156,7 @@ public class NotificationTargetController extends BaseController { SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @GetMapping(value = "/targets", params = {"ids"}) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") - public List getNotificationTargetsByIds(@ApiParam(value = "Comma-separated list of uuids representing targets ids", required = true) + public List getNotificationTargetsByIds(@Parameter(description = "Comma-separated list of uuids representing targets ids", required = true) @RequestParam("ids") UUID[] ids, @AuthenticationPrincipal SecurityUser user) { // generic permission @@ -170,15 +170,15 @@ public class NotificationTargetController extends BaseController { SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @GetMapping("/targets") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") - public PageData getNotificationTargets(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + public PageData getNotificationTargets(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = "Case-insensitive 'substring' filed based on the target's name") + @Parameter(description = "Case-insensitive 'substring' filed based on the target's name") @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION) + @Parameter(description = SORT_PROPERTY_DESCRIPTION) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION) + @Parameter(description = SORT_ORDER_DESCRIPTION) @RequestParam(required = false) String sortOrder, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { // generic permission diff --git a/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java b/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java index fef919d710..a28e218809 100644 --- a/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java +++ b/application/src/main/java/org/thingsboard/server/controller/NotificationTemplateController.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.security.access.prepost.PreAuthorize; @@ -42,13 +42,13 @@ import org.thingsboard.server.common.data.notification.targets.slack.SlackConver import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.notification.NotificationSettingsService; import org.thingsboard.server.dao.notification.NotificationTemplateService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; -import jakarta.validation.Valid; import java.util.List; import java.util.UUID; @@ -137,17 +137,17 @@ public class NotificationTemplateController extends BaseController { SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @GetMapping("/templates") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") - public PageData getNotificationTemplates(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + public PageData getNotificationTemplates(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = "Case-insensitive 'substring' filter based on template's name and notification type") + @Parameter(description = "Case-insensitive 'substring' filter based on template's name and notification type") @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION) + @Parameter(description = SORT_PROPERTY_DESCRIPTION) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION) + @Parameter(description = SORT_ORDER_DESCRIPTION) @RequestParam(required = false) String sortOrder, - @ApiParam(value = "Comma-separated list of notification types to filter the templates") + @Parameter(description = "Comma-separated list of notification types to filter the templates") @RequestParam(required = false) NotificationType[] notificationTypes, @AuthenticationPrincipal SecurityUser user) throws ThingsboardException { // generic permission @@ -177,7 +177,7 @@ public class NotificationTemplateController extends BaseController { @GetMapping("/slack/conversations") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") public List listSlackConversations(@RequestParam SlackConversationType type, - @ApiParam(value = "Slack bot token. If absent - system Slack settings will be used") + @Parameter(description = "Slack bot token. If absent - system Slack settings will be used") @RequestParam(required = false) String token, @AuthenticationPrincipal SecurityUser user) { // generic permission diff --git a/application/src/main/java/org/thingsboard/server/controller/OAuth2ConfigTemplateController.java b/application/src/main/java/org/thingsboard/server/controller/OAuth2ConfigTemplateController.java index f547a5f0ad..63258c5196 100644 --- a/application/src/main/java/org/thingsboard/server/controller/OAuth2ConfigTemplateController.java +++ b/application/src/main/java/org/thingsboard/server/controller/OAuth2ConfigTemplateController.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -30,6 +29,7 @@ import org.springframework.web.bind.annotation.RestController; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.OAuth2ClientRegistrationTemplateId; import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; @@ -63,7 +63,7 @@ public class OAuth2ConfigTemplateController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") @RequestMapping(value = "/{clientRegistrationTemplateId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public void deleteClientRegistrationTemplate(@ApiParam(value = "String representation of client registration template id to delete", example = "139b1f81-2f5d-11ec-9dbe-9b627e1a88f4") + public void deleteClientRegistrationTemplate(@Parameter(description = "String representation of client registration template id to delete", example = "139b1f81-2f5d-11ec-9dbe-9b627e1a88f4") @PathVariable(CLIENT_REGISTRATION_TEMPLATE_ID) String strClientRegistrationTemplateId) throws ThingsboardException { checkParameter(CLIENT_REGISTRATION_TEMPLATE_ID, strClientRegistrationTemplateId); accessControlService.checkPermission(getCurrentUser(), Resource.OAUTH2_CONFIGURATION_TEMPLATE, Operation.DELETE); diff --git a/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java b/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java index 519629fbc3..1688f08b52 100644 --- a/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java +++ b/application/src/main/java/org/thingsboard/server/controller/OAuth2Controller.java @@ -15,8 +15,9 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -33,13 +34,13 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.oauth2.OAuth2ClientInfo; import org.thingsboard.server.common.data.oauth2.OAuth2Info; import org.thingsboard.server.common.data.oauth2.PlatformType; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.oauth2.OAuth2Configuration; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.utils.MiscUtils; -import jakarta.servlet.http.HttpServletRequest; import java.util.Enumeration; import java.util.List; @@ -61,13 +62,13 @@ public class OAuth2Controller extends BaseController { @RequestMapping(value = "/noauth/oauth2Clients", method = RequestMethod.POST) @ResponseBody public List getOAuth2Clients(HttpServletRequest request, - @ApiParam(value = "Mobile application package name, to find OAuth2 clients " + + @Parameter(description = "Mobile application package name, to find OAuth2 clients " + "where there is configured mobile application with such package name") @RequestParam(required = false) String pkgName, - @ApiParam(value = "Platform type to search OAuth2 clients for which " + + @Parameter(description = "Platform type to search OAuth2 clients for which " + "the usage with this platform type is allowed in the settings. " + "If platform type is not one of allowable values - it will just be ignored", - allowableValues = "WEB, ANDROID, IOS") + schema = @Schema(allowableValues = "WEB, ANDROID, IOS")) @RequestParam(required = false) String platform) throws ThingsboardException { if (log.isDebugEnabled()) { log.debug("Executing getOAuth2Clients: [{}][{}][{}]", request.getScheme(), request.getServerName(), request.getServerPort()); @@ -81,7 +82,8 @@ public class OAuth2Controller extends BaseController { if (StringUtils.isNotEmpty(platform)) { try { platformType = PlatformType.valueOf(platform); - } catch (Exception e) {} + } catch (Exception e) { + } } return oAuth2Service.getOAuth2Clients(MiscUtils.getScheme(request), MiscUtils.getDomainNameAndPort(request), pkgName, platformType); } diff --git a/application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java b/application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java index 9b923e01dc..2ee07ce196 100644 --- a/application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java +++ b/application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.ByteArrayResource; @@ -42,6 +44,7 @@ import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.ota.TbOtaPackageService; import org.thingsboard.server.service.security.permission.Operation; @@ -52,16 +55,13 @@ import java.io.IOException; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_PROFILE_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_CHECKSUM_ALGORITHM_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_INFO_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -84,7 +84,7 @@ public class OtaPackageController extends BaseController { @PreAuthorize("hasAnyAuthority( 'TENANT_ADMIN')") @RequestMapping(value = "/otaPackage/{otaPackageId}/download", method = RequestMethod.GET) @ResponseBody - public ResponseEntity downloadOtaPackage(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION) + public ResponseEntity downloadOtaPackage(@Parameter(description = OTA_PACKAGE_ID_PARAM_DESCRIPTION) @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { checkParameter(OTA_PACKAGE_ID, strOtaPackageId); OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); @@ -106,11 +106,11 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Get OTA Package Info (getOtaPackageInfoById)", notes = "Fetch the OTA Package Info object based on the provided OTA Package Id. " + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/otaPackage/info/{otaPackageId}", method = RequestMethod.GET) @ResponseBody - public OtaPackageInfo getOtaPackageInfoById(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION) + public OtaPackageInfo getOtaPackageInfoById(@Parameter(description = OTA_PACKAGE_ID_PARAM_DESCRIPTION) @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { checkParameter(OTA_PACKAGE_ID, strOtaPackageId); OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); @@ -120,11 +120,11 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Get OTA Package (getOtaPackageById)", notes = "Fetch the OTA Package object based on the provided OTA Package Id. " + "The server checks that the OTA Package is owned by the same tenant. " + OTA_PACKAGE_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, - produces = APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.GET) @ResponseBody - public OtaPackage getOtaPackageById(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION) + public OtaPackage getOtaPackageById(@Parameter(description = OTA_PACKAGE_ID_PARAM_DESCRIPTION) @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId) throws ThingsboardException { checkParameter(OTA_PACKAGE_ID, strOtaPackageId); OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); @@ -137,12 +137,11 @@ public class OtaPackageController extends BaseController { "Specify existing OTA Package id to update the OTA Package Info. " + "Referencing non-existing OTA Package Id will cause 'Not Found' error. " + "\n\nOTA Package combination of the title with the version is unique in the scope of tenant. " + TENANT_AUTHORITY_PARAGRAPH, - produces = APPLICATION_JSON_VALUE, - consumes = APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/otaPackage", method = RequestMethod.POST) @ResponseBody - public OtaPackageInfo saveOtaPackageInfo(@ApiParam(value = "A JSON value representing the OTA Package.") + public OtaPackageInfo saveOtaPackageInfo(@Parameter(description = "A JSON value representing the OTA Package.") @RequestBody SaveOtaPackageInfoRequest otaPackageInfo) throws ThingsboardException { otaPackageInfo.setTenantId(getTenantId()); checkEntity(otaPackageInfo.getId(), otaPackageInfo, Resource.OTA_PACKAGE); @@ -152,18 +151,18 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Save OTA Package data (saveOtaPackageData)", notes = "Update the OTA Package. Adds the date to the existing OTA Package Info" + TENANT_AUTHORITY_PARAGRAPH, - produces = APPLICATION_JSON_VALUE, - consumes = MULTIPART_FORM_DATA_VALUE) + responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE)), + requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(mediaType = MULTIPART_FORM_DATA_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.POST, consumes = MULTIPART_FORM_DATA_VALUE) @ResponseBody - public OtaPackageInfo saveOtaPackageData(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION) + public OtaPackageInfo saveOtaPackageData(@Parameter(description = OTA_PACKAGE_ID_PARAM_DESCRIPTION) @PathVariable(OTA_PACKAGE_ID) String strOtaPackageId, - @ApiParam(value = "OTA Package checksum. For example, '0xd87f7e0c'") + @Parameter(description = "OTA Package checksum. For example, '0xd87f7e0c'") @RequestParam(required = false) String checksum, - @ApiParam(value = "OTA Package checksum algorithm.", allowableValues = OTA_PACKAGE_CHECKSUM_ALGORITHM_ALLOWABLE_VALUES) + @Parameter(description = "OTA Package checksum algorithm.", schema = @Schema(allowableValues = {"MD5", "SHA256", "SHA384", "SHA512", "CRC32", "MURMUR3_32", "MURMUR3_128"})) @RequestParam(CHECKSUM_ALGORITHM) String checksumAlgorithmStr, - @ApiParam(value = "OTA Package data.") + @Parameter(description = "OTA Package data.") @RequestPart MultipartFile file) throws ThingsboardException, IOException { checkParameter(OTA_PACKAGE_ID, strOtaPackageId); checkParameter(CHECKSUM_ALGORITHM, checksumAlgorithmStr); @@ -178,19 +177,19 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Get OTA Package Infos (getOtaPackages)", notes = "Returns a page of OTA Package Info objects owned by tenant. " + PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/otaPackages", method = RequestMethod.GET) @ResponseBody - public PageData getOtaPackages(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + public PageData getOtaPackages(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = OTA_PACKAGE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "type", "title", "version", "tag", "url", "fileName", "dataSize", "checksum"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(otaPackageService.findTenantOtaPackagesByTenantId(getTenantId(), pageLink)); @@ -199,23 +198,23 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Get OTA Package Infos (getOtaPackages)", notes = "Returns a page of OTA Package Info objects owned by tenant. " + PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/otaPackages/{deviceProfileId}/{type}", method = RequestMethod.GET) @ResponseBody - public PageData getOtaPackages(@ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) + public PageData getOtaPackages(@Parameter(description = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable("deviceProfileId") String strDeviceProfileId, - @ApiParam(value = "OTA Package type.", allowableValues = "FIRMWARE, SOFTWARE") + @Parameter(description = "OTA Package type.", schema = @Schema(allowableValues = "FIRMWARE, SOFTWARE")) @PathVariable("type") String strType, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = OTA_PACKAGE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = OTA_PACKAGE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "type", "title", "version", "tag", "url", "fileName", "dataSize", "checksum"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("deviceProfileId", strDeviceProfileId); checkParameter("type", strType); @@ -227,11 +226,11 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Delete OTA Package (deleteOtaPackage)", notes = "Deletes the OTA Package. Referencing non-existing OTA Package Id will cause an error. " + "Can't delete the OTA Package if it is referenced by existing devices or device profile." + TENANT_AUTHORITY_PARAGRAPH, - produces = APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.DELETE) @ResponseBody - public void deleteOtaPackage(@ApiParam(value = OTA_PACKAGE_ID_PARAM_DESCRIPTION) + public void deleteOtaPackage(@Parameter(description = OTA_PACKAGE_ID_PARAM_DESCRIPTION) @PathVariable("otaPackageId") String strOtaPackageId) throws ThingsboardException { checkParameter(OTA_PACKAGE_ID, strOtaPackageId); OtaPackageId otaPackageId = new OtaPackageId(toUUID(strOtaPackageId)); diff --git a/application/src/main/java/org/thingsboard/server/controller/QueueController.java b/application/src/main/java/org/thingsboard/server/controller/QueueController.java index 0e79ae7955..774c991f94 100644 --- a/application/src/main/java/org/thingsboard/server/controller/QueueController.java +++ b/application/src/main/java/org/thingsboard/server/controller/QueueController.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; @@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.msg.queue.ServiceType; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.queue.TbQueueService; import org.thingsboard.server.service.security.permission.Operation; @@ -45,10 +46,7 @@ import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DE import static org.thingsboard.server.controller.ControllerConstants.QUEUE_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.QUEUE_NAME_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.QUEUE_QUEUE_TEXT_SEARCH_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.QUEUE_SERVICE_TYPE_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.QUEUE_SERVICE_TYPE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.QUEUE_SORT_PROPERTY_ALLOWABLE_VALUES; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH; @@ -69,17 +67,17 @@ public class QueueController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/queues", params = {"serviceType", "pageSize", "page"}, method = RequestMethod.GET) @ResponseBody - public PageData getTenantQueuesByServiceType(@ApiParam(value = QUEUE_SERVICE_TYPE_DESCRIPTION, allowableValues = QUEUE_SERVICE_TYPE_ALLOWABLE_VALUES, required = true) + public PageData getTenantQueuesByServiceType(@Parameter(description = QUEUE_SERVICE_TYPE_DESCRIPTION, schema = @Schema(allowableValues = {"TB-RULE-ENGINE", "TB-CORE", "TB-TRANSPORT", "JS-EXECUTOR"}, required = true)) @RequestParam String serviceType, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = QUEUE_QUEUE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = QUEUE_QUEUE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = QUEUE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "topic"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("serviceType", serviceType); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -97,7 +95,7 @@ public class QueueController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/queues/{queueId}", method = RequestMethod.GET) @ResponseBody - public Queue getQueueById(@ApiParam(value = QUEUE_ID_PARAM_DESCRIPTION) + public Queue getQueueById(@Parameter(description = QUEUE_ID_PARAM_DESCRIPTION) @PathVariable("queueId") String queueIdStr) throws ThingsboardException { checkParameter("queueId", queueIdStr); QueueId queueId = new QueueId(UUID.fromString(queueIdStr)); @@ -110,7 +108,7 @@ public class QueueController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/queues/name/{queueName}", method = RequestMethod.GET) @ResponseBody - public Queue getQueueByName(@ApiParam(value = QUEUE_NAME_PARAM_DESCRIPTION) + public Queue getQueueByName(@Parameter(description = QUEUE_NAME_PARAM_DESCRIPTION) @PathVariable("queueName") String queueName) throws ThingsboardException { checkParameter("queueName", queueName); return checkNotNull(queueService.findQueueByTenantIdAndName(getTenantId(), queueName)); @@ -127,9 +125,9 @@ public class QueueController extends BaseController { @RequestMapping(value = "/queues", params = {"serviceType"}, method = RequestMethod.POST) @ResponseBody - public Queue saveQueue(@ApiParam(value = "A JSON value representing the queue.") + public Queue saveQueue(@Parameter(description = "A JSON value representing the queue.") @RequestBody Queue queue, - @ApiParam(value = QUEUE_SERVICE_TYPE_DESCRIPTION, allowableValues = QUEUE_SERVICE_TYPE_ALLOWABLE_VALUES, required = true) + @Parameter(description = QUEUE_SERVICE_TYPE_DESCRIPTION, schema = @Schema(allowableValues = {"TB-RULE-ENGINE", "TB-CORE", "TB-TRANSPORT", "JS-EXECUTOR"}, required = true)) @RequestParam String serviceType) throws ThingsboardException { checkParameter("serviceType", serviceType); queue.setTenantId(getCurrentUser().getTenantId()); @@ -152,7 +150,7 @@ public class QueueController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") @RequestMapping(value = "/queues/{queueId}", method = RequestMethod.DELETE) @ResponseBody - public void deleteQueue(@ApiParam(value = QUEUE_ID_PARAM_DESCRIPTION) + public void deleteQueue(@Parameter(description = QUEUE_ID_PARAM_DESCRIPTION) @PathVariable("queueId") String queueIdStr) throws ThingsboardException { checkParameter("queueId", queueIdStr); QueueId queueId = new QueueId(toUUID(queueIdStr)); diff --git a/application/src/main/java/org/thingsboard/server/controller/RpcV1Controller.java b/application/src/main/java/org/thingsboard/server/controller/RpcV1Controller.java index 509e91e546..fd207dcc34 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RpcV1Controller.java +++ b/application/src/main/java/org/thingsboard/server/controller/RpcV1Controller.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -30,6 +29,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import java.util.UUID; @@ -48,9 +48,9 @@ public class RpcV1Controller extends AbstractRpcController { @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST) @ResponseBody public DeferredResult handleOneWayDeviceRPCRequest( - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable("deviceId") String deviceIdStr, - @ApiParam(value = "A JSON value representing the RPC request.") + @Parameter(description = "A JSON value representing the RPC request.") @RequestBody String requestBody) throws ThingsboardException { return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT, HttpStatus.CONFLICT); } @@ -60,9 +60,9 @@ public class RpcV1Controller extends AbstractRpcController { @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST) @ResponseBody public DeferredResult handleTwoWayDeviceRPCRequest( - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable("deviceId") String deviceIdStr, - @ApiParam(value = "A JSON value representing the RPC request.") + @Parameter(description = "A JSON value representing the RPC request.") @RequestBody String requestBody) throws ThingsboardException { return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT, HttpStatus.CONFLICT); } diff --git a/application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java b/application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java index c611cfda54..eb7481c6e2 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java +++ b/application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java @@ -16,10 +16,11 @@ package org.thingsboard.server.controller; import com.google.common.util.concurrent.FutureCallback; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -44,12 +45,12 @@ import org.thingsboard.server.common.data.rpc.Rpc; import org.thingsboard.server.common.data.rpc.RpcStatus; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.exception.ToErrorResponseEntity; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.rpc.RemoveRpcActorMsg; import org.thingsboard.server.service.security.permission.Operation; -import jakarta.annotation.Nullable; import java.util.UUID; import static org.thingsboard.server.common.data.DataConstants.RPC_DELETED; @@ -61,10 +62,7 @@ import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_ import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.RPC_ID; import static org.thingsboard.server.controller.ControllerConstants.RPC_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.RPC_SORT_PROPERTY_ALLOWABLE_VALUES; -import static org.thingsboard.server.controller.ControllerConstants.RPC_STATUS_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.RPC_TEXT_SEARCH_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -117,36 +115,36 @@ public class RpcV2Controller extends AbstractRpcController { @ApiOperation(value = "Send one-way RPC request", notes = ONE_WAY_RPC_REQUEST_DESCRIPTION) @ApiResponses(value = { - @ApiResponse(code = 200, message = "Persistent RPC request was saved to the database or lightweight RPC request was sent to the device."), - @ApiResponse(code = 400, message = "Invalid structure of the request."), - @ApiResponse(code = 401, message = "User is not authorized to send the RPC request. Most likely, User belongs to different Customer or Tenant."), - @ApiResponse(code = 504, message = "Timeout to process the RPC call. Most likely, device is offline."), + @ApiResponse(responseCode = "200", description = "Persistent RPC request was saved to the database or lightweight RPC request was sent to the device."), + @ApiResponse(responseCode = "400", description = "Invalid structure of the request."), + @ApiResponse(responseCode = "401", description = "User is not authorized to send the RPC request. Most likely, User belongs to different Customer or Tenant."), + @ApiResponse(responseCode = "504", description = "Timeout to process the RPC call. Most likely, device is offline."), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST) @ResponseBody public DeferredResult handleOneWayDeviceRPCRequest( - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable("deviceId") String deviceIdStr, - @ApiParam(value = "A JSON value representing the RPC request.") + @Parameter(description = "A JSON value representing the RPC request.") @RequestBody String requestBody) throws ThingsboardException { return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT); } @ApiOperation(value = "Send two-way RPC request", notes = TWO_WAY_RPC_REQUEST_DESCRIPTION) @ApiResponses(value = { - @ApiResponse(code = 200, message = "Persistent RPC request was saved to the database or lightweight RPC response received."), - @ApiResponse(code = 400, message = "Invalid structure of the request."), - @ApiResponse(code = 401, message = "User is not authorized to send the RPC request. Most likely, User belongs to different Customer or Tenant."), - @ApiResponse(code = 504, message = "Timeout to process the RPC call. Most likely, device is offline."), + @ApiResponse(responseCode = "200", description = "Persistent RPC request was saved to the database or lightweight RPC response received."), + @ApiResponse(responseCode = "400", description = "Invalid structure of the request."), + @ApiResponse(responseCode = "401", description = "User is not authorized to send the RPC request. Most likely, User belongs to different Customer or Tenant."), + @ApiResponse(responseCode = "504", description = "Timeout to process the RPC call. Most likely, device is offline."), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST) @ResponseBody public DeferredResult handleTwoWayDeviceRPCRequest( - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION) + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION) @PathVariable(DEVICE_ID) String deviceIdStr, - @ApiParam(value = "A JSON value representing the RPC request.") + @Parameter(description = "A JSON value representing the RPC request.") @RequestBody String requestBody) throws ThingsboardException { return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT); } @@ -156,7 +154,7 @@ public class RpcV2Controller extends AbstractRpcController { @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.GET) @ResponseBody public Rpc getPersistedRpc( - @ApiParam(value = RPC_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = RPC_ID_PARAM_DESCRIPTION, required = true) @PathVariable(RPC_ID) String strRpc) throws ThingsboardException { checkParameter("RpcId", strRpc); RpcId rpcId = new RpcId(UUID.fromString(strRpc)); @@ -168,19 +166,19 @@ public class RpcV2Controller extends AbstractRpcController { @RequestMapping(value = "/persistent/device/{deviceId}", method = RequestMethod.GET) @ResponseBody public DeferredResult getPersistedRpcByDevice( - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(DEVICE_ID) String strDeviceId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = "Status of the RPC", allowableValues = RPC_STATUS_ALLOWABLE_VALUES) + @Parameter(description = "Status of the RPC", schema = @Schema(allowableValues = {"QUEUED", "SENT", "DELIVERED", "SUCCESSFUL", "TIMEOUT", "EXPIRED", "FAILED"})) @RequestParam(required = false) RpcStatus rpcStatus, - @ApiParam(value = RPC_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = RPC_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = RPC_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "expirationTime", "request", "response"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("DeviceId", strDeviceId); if (rpcStatus != null && rpcStatus.equals(RpcStatus.DELETED)) { @@ -223,7 +221,7 @@ public class RpcV2Controller extends AbstractRpcController { @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.DELETE) @ResponseBody public void deleteRpc( - @ApiParam(value = RPC_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = RPC_ID_PARAM_DESCRIPTION, required = true) @PathVariable(RPC_ID) String strRpc) throws ThingsboardException { checkParameter("RpcId", strRpc); RpcId rpcId = new RpcId(UUID.fromString(strRpc)); diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index 50abb3de1d..64606968b5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -20,8 +20,10 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -66,6 +68,7 @@ import org.thingsboard.server.common.data.script.ScriptLanguage; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.rule.TbRuleChainService; @@ -93,12 +96,9 @@ import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PA import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TEXT_SEARCH_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TYPES_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.RULE_CHAIN_TYPE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.RULE_NODE_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_AUTHORITY_PARAGRAPH; @@ -163,7 +163,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.GET) @ResponseBody public RuleChain getRuleChainById( - @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) + @Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION) @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { checkParameter(RULE_CHAIN_ID, strRuleChainId); RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); @@ -177,7 +177,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain/{ruleChainId}/output/labels", method = RequestMethod.GET) @ResponseBody public Set getRuleChainOutputLabels( - @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) + @Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION) @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { checkParameter(RULE_CHAIN_ID, strRuleChainId); RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); @@ -192,7 +192,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain/{ruleChainId}/output/labels/usage", method = RequestMethod.GET) @ResponseBody public List getRuleChainOutputLabelsUsage( - @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) + @Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION) @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { checkParameter(RULE_CHAIN_ID, strRuleChainId); RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); @@ -206,7 +206,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain/{ruleChainId}/metadata", method = RequestMethod.GET) @ResponseBody public RuleChainMetaData getRuleChainMetaData( - @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) + @Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION) @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { checkParameter(RULE_CHAIN_ID, strRuleChainId); RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); @@ -226,7 +226,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain", method = RequestMethod.POST) @ResponseBody public RuleChain saveRuleChain( - @ApiParam(value = "A JSON value representing the rule chain.") + @Parameter(description = "A JSON value representing the rule chain.") @RequestBody RuleChain ruleChain) throws Exception { ruleChain.setTenantId(getCurrentUser().getTenantId()); checkEntity(ruleChain.getId(), ruleChain, Resource.RULE_CHAIN); @@ -240,7 +240,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain/device/default", method = RequestMethod.POST) @ResponseBody public RuleChain saveRuleChain( - @ApiParam(value = "A JSON value representing the request.") + @Parameter(description = "A JSON value representing the request.") @RequestBody DefaultRuleChainCreateRequest request) throws Exception { checkNotNull(request); checkParameter(request.getName(), "name"); @@ -253,7 +253,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain/{ruleChainId}/root", method = RequestMethod.POST) @ResponseBody public RuleChain setRootRuleChain( - @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) + @Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION) @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { checkParameter(RULE_CHAIN_ID, strRuleChainId); RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); @@ -267,9 +267,9 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain/metadata", method = RequestMethod.POST) @ResponseBody public RuleChainMetaData saveRuleChainMetaData( - @ApiParam(value = "A JSON value representing the rule chain metadata.") + @Parameter(description = "A JSON value representing the rule chain metadata.") @RequestBody RuleChainMetaData ruleChainMetaData, - @ApiParam(value = "Update related rule nodes.") + @Parameter(description = "Update related rule nodes.") @RequestParam(value = "updateRelated", required = false, defaultValue = "true") boolean updateRelated ) throws Exception { TenantId tenantId = getTenantId(); @@ -291,17 +291,17 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChains", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getRuleChains( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = RULE_CHAIN_TYPE_DESCRIPTION, allowableValues = RULE_CHAIN_TYPES_ALLOWABLE_VALUES) + @Parameter(description = RULE_CHAIN_TYPE_DESCRIPTION, schema = @Schema(allowableValues = {"CORE", "EDGE"})) @RequestParam(value = "type", required = false) String typeStr, - @ApiParam(value = RULE_CHAIN_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = RULE_CHAIN_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "root"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); @@ -319,7 +319,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain/{ruleChainId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) public void deleteRuleChain( - @ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) + @Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION) @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { checkParameter(RULE_CHAIN_ID, strRuleChainId); RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); @@ -334,7 +334,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleNode/{ruleNodeId}/debugIn", method = RequestMethod.GET) @ResponseBody public JsonNode getLatestRuleNodeDebugInput( - @ApiParam(value = RULE_NODE_ID_PARAM_DESCRIPTION) + @Parameter(description = RULE_NODE_ID_PARAM_DESCRIPTION) @PathVariable(RULE_NODE_ID) String strRuleNodeId) throws ThingsboardException { checkParameter(RULE_NODE_ID, strRuleNodeId); RuleNodeId ruleNodeId = new RuleNodeId(toUUID(strRuleNodeId)); @@ -369,9 +369,9 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChain/testScript", method = RequestMethod.POST) @ResponseBody public JsonNode testScript( - @ApiParam(value = "Script language: JS or TBEL") + @Parameter(description = "Script language: JS or TBEL") @RequestParam(required = false) ScriptLanguage scriptLang, - @ApiParam(value = "Test JS request. See API call description above.") + @Parameter(description = "Test JS request. See API call description above.") @RequestBody JsonNode inputParams) throws ThingsboardException, JsonProcessingException { String script = inputParams.get("script").asText(); String scriptType = inputParams.get("scriptType").asText(); @@ -443,7 +443,7 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChains/export", params = {"limit"}, method = RequestMethod.GET) @ResponseBody public RuleChainData exportRuleChains( - @ApiParam(value = "A limit of rule chains to export.", required = true) + @Parameter(description = "A limit of rule chains to export.", required = true) @RequestParam("limit") int limit) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = new PageLink(limit); @@ -455,9 +455,9 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/ruleChains/import", method = RequestMethod.POST) @ResponseBody public List importRuleChains( - @ApiParam(value = "A JSON value representing the rule chains.") + @Parameter(description = "A JSON value representing the rule chains.") @RequestBody RuleChainData ruleChainData, - @ApiParam(value = "Enables overwrite for existing rule chains with the same name.") + @Parameter(description = "Enables overwrite for existing rule chains with the same name.") @RequestParam(required = false, defaultValue = "false") boolean overwrite) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); List importResults = ruleChainService.importTenantRuleChains(tenantId, ruleChainData, overwrite); @@ -507,7 +507,7 @@ public class RuleChainController extends BaseController { EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once rule chain will be delivered to edge service, it's going to start processing messages locally. " + "\n\nOnly rule chain with type 'EDGE' can be assigned to edge." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.POST) @ResponseBody @@ -530,7 +530,7 @@ public class RuleChainController extends BaseController { "Second, remote edge service will receive an 'unassign' command to remove rule chain " + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once 'unassign' command will be delivered to edge service, it's going to remove rule chain locally." + TENANT_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.DELETE) @ResponseBody @@ -552,17 +552,17 @@ public class RuleChainController extends BaseController { @RequestMapping(value = "/edge/{edgeId}/ruleChains", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getEdgeRuleChains( - @ApiParam(value = EDGE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = EDGE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(EDGE_ID) String strEdgeId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = RULE_CHAIN_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = RULE_CHAIN_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = RULE_CHAIN_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "root"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter(EDGE_ID, strEdgeId); TenantId tenantId = getCurrentUser().getTenantId(); @@ -578,7 +578,7 @@ public class RuleChainController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/ruleChain/{ruleChainId}/edgeTemplateRoot", method = RequestMethod.POST) @ResponseBody - public RuleChain setEdgeTemplateRootRuleChain(@ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) + public RuleChain setEdgeTemplateRootRuleChain(@Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION) @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { checkParameter(RULE_CHAIN_ID, strRuleChainId); RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); @@ -592,7 +592,7 @@ public class RuleChainController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/ruleChain/{ruleChainId}/autoAssignToEdge", method = RequestMethod.POST) @ResponseBody - public RuleChain setAutoAssignToEdgeRuleChain(@ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) + public RuleChain setAutoAssignToEdgeRuleChain(@Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION) @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { checkParameter(RULE_CHAIN_ID, strRuleChainId); RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); @@ -606,7 +606,7 @@ public class RuleChainController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/ruleChain/{ruleChainId}/autoAssignToEdge", method = RequestMethod.DELETE) @ResponseBody - public RuleChain unsetAutoAssignToEdgeRuleChain(@ApiParam(value = RULE_CHAIN_ID_PARAM_DESCRIPTION) + public RuleChain unsetAutoAssignToEdgeRuleChain(@Parameter(description = RULE_CHAIN_ID_PARAM_DESCRIPTION) @PathVariable(RULE_CHAIN_ID) String strRuleChainId) throws ThingsboardException { checkParameter(RULE_CHAIN_ID, strRuleChainId); RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); diff --git a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java index 724cb59b73..07d8fa04d3 100644 --- a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java +++ b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java @@ -17,6 +17,8 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import io.swagger.v3.oas.annotations.Hidden; +import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -39,14 +41,12 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService; -import springfox.documentation.annotations.ApiIgnore; -import jakarta.annotation.PostConstruct; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -@ApiIgnore +@Hidden @RestController @TbCoreComponent @RequestMapping("/api") diff --git a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java index d94dc31fa1..387d31d40d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.ByteArrayResource; @@ -39,6 +41,7 @@ import org.thingsboard.server.common.data.lwm2m.LwM2mObject; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.resource.TbResourceService; import org.thingsboard.server.service.security.permission.Operation; @@ -48,16 +51,13 @@ import java.util.Base64; import java.util.List; import static org.thingsboard.server.controller.ControllerConstants.LWM2M_OBJECT_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.LWM2M_OBJECT_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_INFO_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.RESOURCE_TEXT_SEARCH_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH; @@ -79,7 +79,7 @@ public class TbResourceController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/resource/{resourceId}/download", method = RequestMethod.GET) @ResponseBody - public ResponseEntity downloadResource(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION) + public ResponseEntity downloadResource(@Parameter(description = RESOURCE_ID_PARAM_DESCRIPTION) @PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException { checkParameter(RESOURCE_ID, strResourceId); TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); @@ -97,11 +97,11 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get Resource Info (getResourceInfoById)", notes = "Fetch the Resource Info object based on the provided Resource Id. " + RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/resource/info/{resourceId}", method = RequestMethod.GET) @ResponseBody - public TbResourceInfo getResourceInfoById(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION) + public TbResourceInfo getResourceInfoById(@Parameter(description = RESOURCE_ID_PARAM_DESCRIPTION) @PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException { checkParameter(RESOURCE_ID, strResourceId); TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); @@ -111,11 +111,11 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get Resource (getResourceById)", notes = "Fetch the Resource object based on the provided Resource Id. " + RESOURCE_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/resource/{resourceId}", method = RequestMethod.GET) @ResponseBody - public TbResource getResourceById(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION) + public TbResource getResourceById(@Parameter(description = RESOURCE_ID_PARAM_DESCRIPTION) @PathVariable(RESOURCE_ID) String strResourceId) throws ThingsboardException { checkParameter(RESOURCE_ID, strResourceId); TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); @@ -130,12 +130,11 @@ public class TbResourceController extends BaseController { "\n\nResource combination of the title with the key is unique in the scope of tenant. " + "Remove 'id', 'tenantId' from the request body example (below) to create new Resource entity." + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json", - consumes = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/resource", method = RequestMethod.POST) @ResponseBody - public TbResource saveResource(@ApiParam(value = "A JSON value representing the Resource.") + public TbResource saveResource(@Parameter(description = "A JSON value representing the Resource.") @RequestBody TbResource resource) throws Exception { resource.setTenantId(getTenantId()); checkEntity(resource.getId(), resource, Resource.TB_RESOURCE); @@ -145,19 +144,19 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get Resource Infos (getResources)", notes = "Returns a page of Resource Info objects owned by tenant or sysadmin. " + PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/resource", method = RequestMethod.GET) @ResponseBody - public PageData getResources(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + public PageData getResources(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = RESOURCE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = RESOURCE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = RESOURCE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "title", "resourceType", "tenantId"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { @@ -170,19 +169,19 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjectsPage)", notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " + PAGE_DATA_PARAMETERS + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/resource/lwm2m/page", method = RequestMethod.GET) @ResponseBody - public List getLwm2mListObjectsPage(@ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + public List getLwm2mListObjectsPage(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = RESOURCE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = RESOURCE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = LWM2M_OBJECT_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"id", "name"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = new PageLink(pageSize, page, textSearch); return checkNotNull(resourceService.findLwM2mObjectPage(getTenantId(), sortProperty, sortOrder, pageLink)); @@ -191,15 +190,15 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjects)", notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " + "You can specify parameters to filter the results. " + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, - produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/resource/lwm2m", method = RequestMethod.GET) @ResponseBody - public List getLwm2mListObjects(@ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES, required = true) + public List getLwm2mListObjects(@Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"}, required = true)) @RequestParam String sortOrder, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = LWM2M_OBJECT_SORT_PROPERTY_ALLOWABLE_VALUES, required = true) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"id", "name"}, required = true)) @RequestParam String sortProperty, - @ApiParam(value = "LwM2M Object ids.", required = true) + @Parameter(description = "LwM2M Object ids.", required = true) @RequestParam(required = false) String[] objectIds) throws ThingsboardException { return checkNotNull(resourceService.findLwM2mObject(getTenantId(), sortOrder, sortProperty, objectIds)); } @@ -209,7 +208,7 @@ public class TbResourceController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/resource/{resourceId}", method = RequestMethod.DELETE) @ResponseBody - public void deleteResource(@ApiParam(value = RESOURCE_ID_PARAM_DESCRIPTION) + public void deleteResource(@Parameter(description = RESOURCE_ID_PARAM_DESCRIPTION) @PathVariable("resourceId") String strResourceId) throws ThingsboardException { checkParameter(RESOURCE_ID, strResourceId); TbResourceId resourceId = new TbResourceId(toUUID(strResourceId)); diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index 262cd38629..1e72d70cbb 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -24,10 +24,14 @@ import com.google.common.util.concurrent.MoreExecutors; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.annotation.Nullable; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -46,6 +50,7 @@ import org.springframework.web.context.request.async.DeferredResult; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.StringUtils; @@ -74,7 +79,7 @@ import org.thingsboard.server.common.data.kv.ReadTsKvQuery; import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; -import org.thingsboard.server.common.adaptor.JsonConverter; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.exception.InvalidParametersException; import org.thingsboard.server.exception.UncheckedApiException; @@ -85,9 +90,6 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.telemetry.AttributeData; import org.thingsboard.server.service.telemetry.TsData; -import jakarta.annotation.Nullable; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.PreDestroy; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; @@ -100,8 +102,6 @@ import java.util.stream.Collectors; import static org.thingsboard.server.controller.ControllerConstants.ATTRIBUTES_JSON_REQUEST_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ATTRIBUTES_KEYS_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES; -import static org.thingsboard.server.controller.ControllerConstants.ATTRIBUTES_SCOPE_ALLOWED_VALUES; import static org.thingsboard.server.controller.ControllerConstants.ATTRIBUTES_SCOPE_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.ATTRIBUTE_DATA_EXAMPLE; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID; @@ -126,7 +126,6 @@ import static org.thingsboard.server.controller.ControllerConstants.SAVE_ENTITY_ import static org.thingsboard.server.controller.ControllerConstants.SAVE_ENTITY_TIMESERIES_STATUS_OK; import static org.thingsboard.server.controller.ControllerConstants.SAVE_ENTITY_TIMESERIES_STATUS_UNAUTHORIZED; import static org.thingsboard.server.controller.ControllerConstants.SAVE_TIMESERIES_REQUEST_PAYLOAD; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.STRICT_DATA_TYPES_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TELEMETRY_JSON_REQUEST_DESCRIPTION; @@ -176,13 +175,13 @@ public class TelemetryController extends BaseController { "\n * CLIENT_SCOPE - supported for devices;" + "\n * SHARED_SCOPE - supported for devices. " + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes", method = RequestMethod.GET) @ResponseBody public DeferredResult getAttributeKeys( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr) throws ThingsboardException { + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr) throws ThingsboardException { return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, this::getAttributeKeysCallback); } @@ -192,16 +191,16 @@ public class TelemetryController extends BaseController { "\n * CLIENT_SCOPE - supported for devices;" + "\n * SHARED_SCOPE - supported for devices. " + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes/{scope}", method = RequestMethod.GET) @ResponseBody public DeferredResult getAttributeKeysByScope( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, required = true, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES) @PathVariable("scope") String scope) throws ThingsboardException { + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, required = true, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE", "CLIENT_SCOPE"})) @PathVariable("scope") String scope) throws ThingsboardException { return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, - (result, tenantId, entityId) -> getAttributeKeysCallback(result, tenantId, entityId, scope)); + (result, tenantId, entityId) -> getAttributeKeysCallback(result, tenantId, entityId, scope)); } @ApiOperation(value = "Get attributes (getAttributes)", @@ -211,17 +210,17 @@ public class TelemetryController extends BaseController { + ATTRIBUTE_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/attributes", method = RequestMethod.GET) @ResponseBody public DeferredResult getAttributes( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { - SecurityUser user = getCurrentUser(); + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = ATTRIBUTES_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { + SecurityUser user = getCurrentUser(); return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, - (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, null, keysStr)); + (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, null, keysStr)); } @@ -234,32 +233,32 @@ public class TelemetryController extends BaseController { + ATTRIBUTE_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/attributes/{scope}", method = RequestMethod.GET) @ResponseBody public DeferredResult getAttributesByScope( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope, - @ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE", "CLIENT_SCOPE"}, required = true)) @PathVariable("scope") String scope, + @Parameter(description = ATTRIBUTES_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr) throws ThingsboardException { SecurityUser user = getCurrentUser(); return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_ATTRIBUTES, entityType, entityIdStr, - (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, scope, keysStr)); + (result, tenantId, entityId) -> getAttributeValuesCallback(result, user, entityId, scope, keysStr)); } @ApiOperation(value = "Get time-series keys (getTimeseriesKeys)", notes = "Returns a set of unique time-series key names for the selected entity. " + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/timeseries", method = RequestMethod.GET) @ResponseBody public DeferredResult getTimeseriesKeys( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr) throws ThingsboardException { + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr) throws ThingsboardException { return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, - (result, tenantId, entityId) -> Futures.addCallback(tsService.findAllLatest(tenantId, entityId), getTsKeysToResponseCallback(result), MoreExecutors.directExecutor())); + (result, tenantId, entityId) -> Futures.addCallback(tsService.findAllLatest(tenantId, entityId), getTsKeysToResponseCallback(result), MoreExecutors.directExecutor())); } @ApiOperation(value = "Get latest time-series value (getLatestTimeseries)", @@ -274,15 +273,15 @@ public class TelemetryController extends BaseController { + LATEST_TS_STRICT_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET) @ResponseBody public DeferredResult getLatestTimeseries( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = TELEMETRY_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr, - @ApiParam(value = STRICT_DATA_TYPES_DESCRIPTION) + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = TELEMETRY_KEYS_DESCRIPTION) @RequestParam(name = "keys", required = false) String keysStr, + @Parameter(description = STRICT_DATA_TYPES_DESCRIPTION) @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException { SecurityUser user = getCurrentUser(); return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, @@ -298,30 +297,30 @@ public class TelemetryController extends BaseController { + TS_STRICT_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET, params = {"keys", "startTs", "endTs"}) @ResponseBody public DeferredResult getTimeseries( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = TELEMETRY_KEYS_BASE_DESCRIPTION, required = true) @RequestParam(name = "keys") String keys, - @ApiParam(value = "A long value representing the start timestamp of the time range in milliseconds, UTC.") + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = TELEMETRY_KEYS_BASE_DESCRIPTION, required = true) @RequestParam(name = "keys") String keys, + @Parameter(description = "A long value representing the start timestamp of the time range in milliseconds, UTC.") @RequestParam(name = "startTs") Long startTs, - @ApiParam(value = "A long value representing the end timestamp of the time range in milliseconds, UTC.") + @Parameter(description = "A long value representing the end timestamp of the time range in milliseconds, UTC.") @RequestParam(name = "endTs") Long endTs, - @ApiParam(value = "A long value representing the aggregation interval range in milliseconds.") + @Parameter(description = "A long value representing the aggregation interval range in milliseconds.") @RequestParam(name = "interval", defaultValue = "0") Long interval, - @ApiParam(value = "An integer value that represents a max number of timeseries data points to fetch." + - " This parameter is used only in the case if 'agg' parameter is set to 'NONE'.", defaultValue = "100") + @Parameter(description = "An integer value that represents a max number of timeseries data points to fetch." + + " This parameter is used only in the case if 'agg' parameter is set to 'NONE'.", schema = @Schema(defaultValue = "100")) @RequestParam(name = "limit", defaultValue = "100") Integer limit, - @ApiParam(value = "A string value representing the aggregation function. " + + @Parameter(description = "A string value representing the aggregation function. " + "If the interval is not specified, 'agg' parameter will use 'NONE' value.", - allowableValues = "MIN, MAX, AVG, SUM, COUNT, NONE") + schema = @Schema(allowableValues = "MIN, MAX, AVG, SUM, COUNT, NONE")) @RequestParam(name = "agg", defaultValue = "NONE") String aggStr, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(name = "orderBy", defaultValue = "DESC") String orderBy, - @ApiParam(value = STRICT_DATA_TYPES_DESCRIPTION) + @Parameter(description = STRICT_DATA_TYPES_DESCRIPTION) @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException { return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, (result, tenantId, entityId) -> { @@ -338,23 +337,23 @@ public class TelemetryController extends BaseController { notes = "Creates or updates the device attributes based on device id and specified attribute scope. " + SAVE_ATTRIBUTES_REQUEST_PAYLOAD + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @ApiResponses(value = { - @ApiResponse(code = 200, message = SAVE_ATTIRIBUTES_STATUS_OK + + @ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + "Platform creates an audit log event about device attributes updates with action type 'ATTRIBUTES_UPDATED', " + "and also sends event msg to the rule engine with msg type 'ATTRIBUTES_UPDATED'."), - @ApiResponse(code = 400, message = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), - @ApiResponse(code = 401, message = "User is not authorized to save device attributes for selected device. Most likely, User belongs to different Customer or Tenant."), - @ApiResponse(code = 500, message = "The exception was thrown during processing the request. " + + @ApiResponse(responseCode = "400", description = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), + @ApiResponse(responseCode = "401", description = "User is not authorized to save device attributes for selected device. Most likely, User belongs to different Customer or Tenant."), + @ApiResponse(responseCode = "500", description = "The exception was thrown during processing the request. " + "Platform creates an audit log event about device attributes updates with action type 'ATTRIBUTES_UPDATED' that includes an error stacktrace."), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{deviceId}/{scope}", method = RequestMethod.POST) @ResponseBody public DeferredResult saveDeviceAttributes( - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("deviceId") String deviceIdStr, - @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope, - @ApiParam(value = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("deviceId") String deviceIdStr, + @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, required = true)) @PathVariable("scope") String scope, + @Parameter(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); return saveAttributes(getTenantId(), entityId, scope, request); } @@ -364,21 +363,21 @@ public class TelemetryController extends BaseController { ENTITY_SAVE_ATTRIBUTE_SCOPES + SAVE_ATTRIBUTES_REQUEST_PAYLOAD + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @ApiResponses(value = { - @ApiResponse(code = 200, message = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), - @ApiResponse(code = 400, message = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), - @ApiResponse(code = 401, message = SAVE_ENTITY_ATTRIBUTES_STATUS_UNAUTHORIZED), - @ApiResponse(code = 500, message = SAVE_ENTITY_ATTRIBUTES_STATUS_INTERNAL_SERVER_ERROR), + @ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), + @ApiResponse(responseCode = "400", description = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), + @ApiResponse(responseCode = "401", description = SAVE_ENTITY_ATTRIBUTES_STATUS_UNAUTHORIZED), + @ApiResponse(responseCode = "500", description = SAVE_ENTITY_ATTRIBUTES_STATUS_INTERNAL_SERVER_ERROR), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/{scope}", method = RequestMethod.POST) @ResponseBody public DeferredResult saveEntityAttributesV1( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES) @PathVariable("scope") String scope, - @ApiParam(value = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"})) @PathVariable("scope")String scope, + @Parameter(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody JsonNode request) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveAttributes(getTenantId(), entityId, scope, request); } @@ -388,21 +387,21 @@ public class TelemetryController extends BaseController { ENTITY_SAVE_ATTRIBUTE_SCOPES + SAVE_ATTRIBUTES_REQUEST_PAYLOAD + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @ApiResponses(value = { - @ApiResponse(code = 200, message = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), - @ApiResponse(code = 400, message = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), - @ApiResponse(code = 401, message = SAVE_ENTITY_ATTRIBUTES_STATUS_UNAUTHORIZED), - @ApiResponse(code = 500, message = SAVE_ENTITY_ATTRIBUTES_STATUS_INTERNAL_SERVER_ERROR), + @ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), + @ApiResponse(responseCode = "400", description = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), + @ApiResponse(responseCode = "401", description = SAVE_ENTITY_ATTRIBUTES_STATUS_UNAUTHORIZED), + @ApiResponse(responseCode = "500", description = SAVE_ENTITY_ATTRIBUTES_STATUS_INTERNAL_SERVER_ERROR), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/attributes/{scope}", method = RequestMethod.POST) @ResponseBody public DeferredResult saveEntityAttributesV2( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SAVE_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope, - @ApiParam(value = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, required = true)) @PathVariable("scope")String scope, + @Parameter(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody JsonNode request) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveAttributes(getTenantId(), entityId, scope, request); } @@ -413,21 +412,21 @@ public class TelemetryController extends BaseController { SAVE_TIMESERIES_REQUEST_PAYLOAD + "\n\n The scope parameter is not used in the API call implementation but should be specified whatever value because it is used as a path variable. " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @ApiResponses(value = { - @ApiResponse(code = 200, message = SAVE_ENTITY_TIMESERIES_STATUS_OK), - @ApiResponse(code = 400, message = INVALID_STRUCTURE_OF_THE_REQUEST), - @ApiResponse(code = 401, message = SAVE_ENTITY_TIMESERIES_STATUS_UNAUTHORIZED), - @ApiResponse(code = 500, message = SAVE_ENTITY_TIMESERIES_STATUS_INTERNAL_SERVER_ERROR), + @ApiResponse(responseCode = "200", description = SAVE_ENTITY_TIMESERIES_STATUS_OK), + @ApiResponse(responseCode = "400", description = INVALID_STRUCTURE_OF_THE_REQUEST), + @ApiResponse(responseCode = "401", description = SAVE_ENTITY_TIMESERIES_STATUS_UNAUTHORIZED), + @ApiResponse(responseCode = "500", description = SAVE_ENTITY_TIMESERIES_STATUS_INTERNAL_SERVER_ERROR), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/timeseries/{scope}", method = RequestMethod.POST) @ResponseBody public DeferredResult saveEntityTelemetry( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = TELEMETRY_SCOPE_DESCRIPTION, required = true, allowableValues = "ANY") @PathVariable("scope") String scope, - @ApiParam(value = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody String requestBody) throws ThingsboardException { + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = TELEMETRY_SCOPE_DESCRIPTION, required = true, schema = @Schema(allowableValues = "ANY")) @PathVariable("scope")String scope, + @Parameter(description = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody String requestBody) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveTelemetry(getTenantId(), entityId, requestBody, 0L); } @@ -438,22 +437,22 @@ public class TelemetryController extends BaseController { "\n\n The scope parameter is not used in the API call implementation but should be specified whatever value because it is used as a path variable. " + "\n\nThe ttl parameter takes affect only in case of Cassandra DB." + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @ApiResponses(value = { - @ApiResponse(code = 200, message = SAVE_ENTITY_TIMESERIES_STATUS_OK), - @ApiResponse(code = 400, message = INVALID_STRUCTURE_OF_THE_REQUEST), - @ApiResponse(code = 401, message = SAVE_ENTITY_TIMESERIES_STATUS_UNAUTHORIZED), - @ApiResponse(code = 500, message = SAVE_ENTITY_TIMESERIES_STATUS_INTERNAL_SERVER_ERROR), + @ApiResponse(responseCode = "200", description = SAVE_ENTITY_TIMESERIES_STATUS_OK), + @ApiResponse(responseCode = "400", description = INVALID_STRUCTURE_OF_THE_REQUEST), + @ApiResponse(responseCode = "401", description = SAVE_ENTITY_TIMESERIES_STATUS_UNAUTHORIZED), + @ApiResponse(responseCode = "500", description = SAVE_ENTITY_TIMESERIES_STATUS_INTERNAL_SERVER_ERROR), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/timeseries/{scope}/{ttl}", method = RequestMethod.POST) @ResponseBody public DeferredResult saveEntityTelemetryWithTTL( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = TELEMETRY_SCOPE_DESCRIPTION, required = true, allowableValues = "ANY") @PathVariable("scope") String scope, - @ApiParam(value = "A long value representing TTL (Time to Live) parameter.", required = true) @PathVariable("ttl") Long ttl, - @ApiParam(value = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody String requestBody) throws ThingsboardException { + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = TELEMETRY_SCOPE_DESCRIPTION, required = true, schema = @Schema(allowableValues = "ANY")) @PathVariable("scope")String scope, + @Parameter(description = "A long value representing TTL (Time to Live) parameter.", required = true)@PathVariable("ttl")Long ttl, + @Parameter(description = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody String requestBody) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveTelemetry(getTenantId(), entityId, requestBody, ttl); } @@ -464,29 +463,29 @@ public class TelemetryController extends BaseController { " Use 'startTs' and 'endTs' to specify time-range instead. " + " Use 'rewriteLatestIfDeleted' to rewrite latest value (stored in separate table for performance) after deletion of the time range. " + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @ApiResponses(value = { - @ApiResponse(code = 200, message = "Timeseries for the selected keys in the request was removed. " + + @ApiResponse(responseCode = "200", description = "Timeseries for the selected keys in the request was removed. " + "Platform creates an audit log event about entity timeseries removal with action type 'TIMESERIES_DELETED'."), - @ApiResponse(code = 400, message = "Platform returns a bad request in case if keys list is empty or start and end timestamp values is empty when deleteAllDataForKeys is set to false."), - @ApiResponse(code = 401, message = "User is not authorized to delete entity timeseries for selected entity. Most likely, User belongs to different Customer or Tenant."), - @ApiResponse(code = 500, message = "The exception was thrown during processing the request. " + + @ApiResponse(responseCode = "400", description = "Platform returns a bad request in case if keys list is empty or start and end timestamp values is empty when deleteAllDataForKeys is set to false."), + @ApiResponse(responseCode = "401", description = "User is not authorized to delete entity timeseries for selected entity. Most likely, User belongs to different Customer or Tenant."), + @ApiResponse(responseCode = "500", description = "The exception was thrown during processing the request. " + "Platform creates an audit log event about entity timeseries removal with action type 'TIMESERIES_DELETED' that includes an error stacktrace."), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/timeseries/delete", method = RequestMethod.DELETE) @ResponseBody public DeferredResult deleteEntityTimeseries( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = TELEMETRY_KEYS_DESCRIPTION, required = true) @RequestParam(name = "keys") String keysStr, - @ApiParam(value = "A boolean value to specify if should be deleted all data for selected keys or only data that are in the selected time range.") + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = TELEMETRY_KEYS_DESCRIPTION, required = true) @RequestParam(name = "keys") String keysStr, + @Parameter(description = "A boolean value to specify if should be deleted all data for selected keys or only data that are in the selected time range.") @RequestParam(name = "deleteAllDataForKeys", defaultValue = "false") boolean deleteAllDataForKeys, - @ApiParam(value = "A long value representing the start timestamp of removal time range in milliseconds.") + @Parameter(description = "A long value representing the start timestamp of removal time range in milliseconds.") @RequestParam(name = "startTs", required = false) Long startTs, - @ApiParam(value = "A long value representing the end timestamp of removal time range in milliseconds.") + @Parameter(description = "A long value representing the end timestamp of removal time range in milliseconds.") @RequestParam(name = "endTs", required = false) Long endTs, - @ApiParam(value = "If the parameter is set to true, the latest telemetry will be rewritten in case that current latest value was removed, otherwise, in case that parameter is set to false the new latest value will not set.") + @Parameter(description = "If the parameter is set to true, the latest telemetry will be rewritten in case that current latest value was removed, otherwise, in case that parameter is set to false the new latest value will not set.") @RequestParam(name = "rewriteLatestIfDeleted", defaultValue = "false") boolean rewriteLatestIfDeleted) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return deleteTimeseries(entityId, keysStr, deleteAllDataForKeys, startTs, endTs, rewriteLatestIfDeleted); @@ -538,22 +537,22 @@ public class TelemetryController extends BaseController { @ApiOperation(value = "Delete device attributes (deleteDeviceAttributes)", notes = "Delete device attributes using provided Device Id, scope and a list of keys. " + "Referencing a non-existing Device Id will cause an error" + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @ApiResponses(value = { - @ApiResponse(code = 200, message = "Device attributes was removed for the selected keys in the request. " + + @ApiResponse(responseCode = "200", description = "Device attributes was removed for the selected keys in the request. " + "Platform creates an audit log event about device attributes removal with action type 'ATTRIBUTES_DELETED'."), - @ApiResponse(code = 400, message = "Platform returns a bad request in case if keys or scope are not specified."), - @ApiResponse(code = 401, message = "User is not authorized to delete device attributes for selected entity. Most likely, User belongs to different Customer or Tenant."), - @ApiResponse(code = 500, message = "The exception was thrown during processing the request. " + + @ApiResponse(responseCode = "400", description = "Platform returns a bad request in case if keys or scope are not specified."), + @ApiResponse(responseCode = "401", description = "User is not authorized to delete device attributes for selected entity. Most likely, User belongs to different Customer or Tenant."), + @ApiResponse(responseCode = "500", description = "The exception was thrown during processing the request. " + "Platform creates an audit log event about device attributes removal with action type 'ATTRIBUTES_DELETED' that includes an error stacktrace."), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{deviceId}/{scope}", method = RequestMethod.DELETE) @ResponseBody public DeferredResult deleteDeviceAttributes( - @ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(DEVICE_ID) String deviceIdStr, - @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES, required = true) @PathVariable("scope") String scope, - @ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION, required = true) @RequestParam(name = "keys") String keysStr) throws ThingsboardException { + @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable(DEVICE_ID) String deviceIdStr, + @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE", "CLIENT_SCOPE"}, required = true)) @PathVariable("scope")String scope, + @Parameter(description = ATTRIBUTES_KEYS_DESCRIPTION, required = true)@RequestParam(name = "keys")String keysStr) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); return deleteAttributes(entityId, scope, keysStr); } @@ -561,23 +560,23 @@ public class TelemetryController extends BaseController { @ApiOperation(value = "Delete entity attributes (deleteEntityAttributes)", notes = "Delete entity attributes using provided Entity Id, scope and a list of keys. " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @ApiResponses(value = { - @ApiResponse(code = 200, message = "Entity attributes was removed for the selected keys in the request. " + + @ApiResponse(responseCode = "200", description = "Entity attributes was removed for the selected keys in the request. " + "Platform creates an audit log event about entity attributes removal with action type 'ATTRIBUTES_DELETED'."), - @ApiResponse(code = 400, message = "Platform returns a bad request in case if keys or scope are not specified."), - @ApiResponse(code = 401, message = "User is not authorized to delete entity attributes for selected entity. Most likely, User belongs to different Customer or Tenant."), - @ApiResponse(code = 500, message = "The exception was thrown during processing the request. " + + @ApiResponse(responseCode = "400", description = "Platform returns a bad request in case if keys or scope are not specified."), + @ApiResponse(responseCode = "401", description = "User is not authorized to delete entity attributes for selected entity. Most likely, User belongs to different Customer or Tenant."), + @ApiResponse(responseCode = "500", description = "The exception was thrown during processing the request. " + "Platform creates an audit log event about entity attributes removal with action type 'ATTRIBUTES_DELETED' that includes an error stacktrace."), }) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/{scope}", method = RequestMethod.DELETE) @ResponseBody public DeferredResult deleteEntityAttributes( - @ApiParam(value = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, defaultValue = "DEVICE") @PathVariable("entityType") String entityType, - @ApiParam(value = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, - @ApiParam(value = ATTRIBUTES_SCOPE_DESCRIPTION, required = true, allowableValues = ATTRIBUTES_SCOPE_ALLOWED_VALUES) @PathVariable("scope") String scope, - @ApiParam(value = ATTRIBUTES_KEYS_DESCRIPTION, required = true) @RequestParam(name = "keys") String keysStr) throws ThingsboardException { + @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, + @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, + @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, required = true, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE", "CLIENT_SCOPE"})) @PathVariable("scope")String scope, + @Parameter(description = ATTRIBUTES_KEYS_DESCRIPTION, required = true)@RequestParam(name = "keys")String keysStr) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return deleteAttributes(entityId, scope, keysStr); } diff --git a/application/src/main/java/org/thingsboard/server/controller/TenantController.java b/application/src/main/java/org/thingsboard/server/controller/TenantController.java index 6574969e15..6fb58207bf 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TenantController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TenantController.java @@ -16,8 +16,8 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.tenant.TbTenantService; @@ -46,15 +47,12 @@ import static org.thingsboard.server.controller.ControllerConstants.HOME_DASHBOA import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID; import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.TENANT_INFO_SORT_PROPERTY_ALLOWABLE_VALUES; -import static org.thingsboard.server.controller.ControllerConstants.TENANT_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.TENANT_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; @@ -76,7 +74,7 @@ public class TenantController extends BaseController { @RequestMapping(value = "/tenant/{tenantId}", method = RequestMethod.GET) @ResponseBody public Tenant getTenantById( - @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION) + @Parameter(description = TENANT_ID_PARAM_DESCRIPTION) @PathVariable(TENANT_ID) String strTenantId) throws ThingsboardException { checkParameter(TENANT_ID, strTenantId); TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); @@ -94,7 +92,7 @@ public class TenantController extends BaseController { @RequestMapping(value = "/tenant/info/{tenantId}", method = RequestMethod.GET) @ResponseBody public TenantInfo getTenantInfoById( - @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION) + @Parameter(description = TENANT_ID_PARAM_DESCRIPTION) @PathVariable(TENANT_ID) String strTenantId) throws ThingsboardException { checkParameter(TENANT_ID, strTenantId); TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); @@ -112,7 +110,7 @@ public class TenantController extends BaseController { @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/tenant", method = RequestMethod.POST) @ResponseBody - public Tenant saveTenant(@ApiParam(value = "A JSON value representing the tenant.") + public Tenant saveTenant(@Parameter(description = "A JSON value representing the tenant.") @RequestBody Tenant tenant) throws Exception { checkEntity(tenant.getId(), tenant, Resource.TENANT); return tbTenantService.save(tenant); @@ -123,7 +121,7 @@ public class TenantController extends BaseController { @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/tenant/{tenantId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public void deleteTenant(@ApiParam(value = TENANT_ID_PARAM_DESCRIPTION) + public void deleteTenant(@Parameter(description = TENANT_ID_PARAM_DESCRIPTION) @PathVariable(TENANT_ID) String strTenantId) throws Exception { checkParameter(TENANT_ID, strTenantId); TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); @@ -136,15 +134,15 @@ public class TenantController extends BaseController { @RequestMapping(value = "/tenants", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenants( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = TENANT_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = TENANT_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = TENANT_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "title", "email", "country", "state", "city", "address", "address2", "zip", "phone", "email"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(tenantService.findTenants(pageLink)); @@ -156,15 +154,15 @@ public class TenantController extends BaseController { @RequestMapping(value = "/tenantInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantInfos( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = TENANT_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = TENANT_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = TENANT_INFO_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "tenantProfileName", "title", "email", "country", "state", "city", "address", "address2", "zip", "phone", "email"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder ) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); diff --git a/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java b/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java index a7fe973ec0..8f667ec184 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TenantProfileController.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.tenant.profile.TbTenantProfileService; import org.thingsboard.server.service.security.permission.Operation; @@ -50,13 +51,10 @@ import static org.thingsboard.server.controller.ControllerConstants.MARKDOWN_COD import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.TENANT_PROFILE_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.TENANT_PROFILE_INFO_SORT_PROPERTY_ALLOWABLE_VALUES; -import static org.thingsboard.server.controller.ControllerConstants.TENANT_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; @@ -77,7 +75,7 @@ public class TenantProfileController extends BaseController { @RequestMapping(value = "/tenantProfile/{tenantProfileId}", method = RequestMethod.GET) @ResponseBody public TenantProfile getTenantProfileById( - @ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = TENANT_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException { checkParameter("tenantProfileId", strTenantProfileId); TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId)); @@ -90,7 +88,7 @@ public class TenantProfileController extends BaseController { @RequestMapping(value = "/tenantProfileInfo/{tenantProfileId}", method = RequestMethod.GET) @ResponseBody public EntityInfo getTenantProfileInfoById( - @ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = TENANT_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException { checkParameter("tenantProfileId", strTenantProfileId); TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId)); @@ -162,7 +160,7 @@ public class TenantProfileController extends BaseController { @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/tenantProfile", method = RequestMethod.POST) @ResponseBody - public TenantProfile saveTenantProfile(@ApiParam(value = "A JSON value representing the tenant profile.") + public TenantProfile saveTenantProfile(@Parameter(description = "A JSON value representing the tenant profile.") @RequestBody TenantProfile tenantProfile) throws ThingsboardException { TenantProfile oldProfile; if (tenantProfile.getId() == null) { @@ -180,7 +178,7 @@ public class TenantProfileController extends BaseController { @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/tenantProfile/{tenantProfileId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) - public void deleteTenantProfile(@ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION) + public void deleteTenantProfile(@Parameter(description = TENANT_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException { checkParameter("tenantProfileId", strTenantProfileId); TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId)); @@ -194,7 +192,7 @@ public class TenantProfileController extends BaseController { @RequestMapping(value = "/tenantProfile/{tenantProfileId}/default", method = RequestMethod.POST) @ResponseBody public TenantProfile setDefaultTenantProfile( - @ApiParam(value = TENANT_PROFILE_ID_PARAM_DESCRIPTION) + @Parameter(description = TENANT_PROFILE_ID_PARAM_DESCRIPTION) @PathVariable("tenantProfileId") String strTenantProfileId) throws ThingsboardException { checkParameter("tenantProfileId", strTenantProfileId); TenantProfileId tenantProfileId = new TenantProfileId(toUUID(strTenantProfileId)); @@ -208,15 +206,15 @@ public class TenantProfileController extends BaseController { @RequestMapping(value = "/tenantProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantProfiles( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = TENANT_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "name", "description", "isDefault"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(tenantProfileService.findTenantProfiles(getTenantId(), pageLink)); @@ -228,15 +226,15 @@ public class TenantProfileController extends BaseController { @RequestMapping(value = "/tenantProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantProfileInfos( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = TENANT_PROFILE_INFO_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"id", "name"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); return checkNotNull(tenantProfileService.findTenantProfileInfos(getTenantId(), pageLink)); diff --git a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java index a809f5280c..f674ed0ca8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthConfigController.java @@ -15,8 +15,9 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; import lombok.Data; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; @@ -34,12 +35,12 @@ import org.thingsboard.server.common.data.security.model.mfa.account.AccountTwoF import org.thingsboard.server.common.data.security.model.mfa.account.TwoFaAccountConfig; import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderConfig; import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.mfa.TwoFactorAuthService; import org.thingsboard.server.service.security.auth.mfa.config.TwoFaConfigManager; import org.thingsboard.server.service.security.model.SecurityUser; -import jakarta.validation.Valid; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -99,7 +100,7 @@ public class TwoFactorAuthConfigController extends BaseController { ControllerConstants.AVAILABLE_FOR_ANY_AUTHORIZED_USER) @PostMapping("/account/config/generate") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - public TwoFaAccountConfig generateTwoFaAccountConfig(@ApiParam(value = "2FA provider type to generate new account config for", defaultValue = "TOTP", required = true) + public TwoFaAccountConfig generateTwoFaAccountConfig(@Parameter(description = "2FA provider type to generate new account config for", schema = @Schema(defaultValue = "TOTP", required = true)) @RequestParam TwoFaProviderType providerType) throws Exception { SecurityUser user = getCurrentUser(); return twoFactorAuthService.generateNewAccountConfig(user, providerType); @@ -258,7 +259,7 @@ public class TwoFactorAuthConfigController extends BaseController { ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @PostMapping("/settings") @PreAuthorize("hasAnyAuthority('SYS_ADMIN')") - public PlatformTwoFaSettings savePlatformTwoFaSettings(@ApiParam(value = "Settings value", required = true) + public PlatformTwoFaSettings savePlatformTwoFaSettings(@Parameter(description = "Settings value", required = true) @RequestBody PlatformTwoFaSettings twoFaSettings) throws ThingsboardException { return twoFaConfigManager.savePlatformTwoFaSettings(getTenantId(), twoFaSettings); } diff --git a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthController.java b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthController.java index ee1db6868a..1478e21c76 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TwoFactorAuthController.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; +import jakarta.servlet.http.HttpServletRequest; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.security.model.mfa.PlatformTwoFaSettin import org.thingsboard.server.common.data.security.model.mfa.account.EmailTwoFaAccountConfig; import org.thingsboard.server.common.data.security.model.mfa.account.SmsTwoFaAccountConfig; import org.thingsboard.server.common.data.security.model.mfa.provider.TwoFaProviderType; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.mfa.TwoFactorAuthService; @@ -44,7 +45,6 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.system.SystemSecurityService; -import jakarta.servlet.http.HttpServletRequest; import java.util.Collections; import java.util.List; import java.util.Optional; diff --git a/application/src/main/java/org/thingsboard/server/controller/UiSettingsController.java b/application/src/main/java/org/thingsboard/server/controller/UiSettingsController.java index a40d3b85af..11bd0e8364 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UiSettingsController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UiSettingsController.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.RequestMapping; @@ -23,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.thingsboard.server.common.data.exception.ThingsboardException; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; @RestController diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 5bf6a86307..b05d5feb83 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -17,8 +17,9 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -64,6 +65,7 @@ import org.thingsboard.server.common.data.settings.UserDashboardAction; import org.thingsboard.server.common.data.settings.UserDashboardsInfo; import org.thingsboard.server.common.data.settings.UserSettings; import org.thingsboard.server.common.data.settings.UserSettingsType; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.entity.EntityService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.user.TbUserService; @@ -75,7 +77,6 @@ import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import org.thingsboard.server.service.security.system.SystemSecurityService; -import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -92,7 +93,6 @@ import static org.thingsboard.server.controller.ControllerConstants.HOME_DASHBOA import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_AUTHORITY_PARAGRAPH; @@ -102,7 +102,6 @@ import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID; import static org.thingsboard.server.controller.ControllerConstants.TENANT_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.USER_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.USER_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.USER_TEXT_SEARCH_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; @@ -141,7 +140,7 @@ public class UserController extends BaseController { @RequestMapping(value = "/user/{userId}", method = RequestMethod.GET) @ResponseBody public User getUserById( - @ApiParam(value = USER_ID_PARAM_DESCRIPTION) + @Parameter(description = USER_ID_PARAM_DESCRIPTION) @PathVariable(USER_ID) String strUserId) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); @@ -177,7 +176,7 @@ public class UserController extends BaseController { @RequestMapping(value = "/user/{userId}/token", method = RequestMethod.GET) @ResponseBody public JwtPair getUserToken( - @ApiParam(value = USER_ID_PARAM_DESCRIPTION) + @Parameter(description = USER_ID_PARAM_DESCRIPTION) @PathVariable(USER_ID) String strUserId) throws ThingsboardException { checkParameter(USER_ID, strUserId); if (!userTokenAccessEnabled) { @@ -205,9 +204,9 @@ public class UserController extends BaseController { @RequestMapping(value = "/user", method = RequestMethod.POST) @ResponseBody public User saveUser( - @ApiParam(value = "A JSON value representing the User.", required = true) + @Parameter(description = "A JSON value representing the User.", required = true) @RequestBody User user, - @ApiParam(value = "Send activation email (or use activation link)", defaultValue = "true") + @Parameter(description = "Send activation email (or use activation link)" , schema = @Schema(defaultValue = "true")) @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, HttpServletRequest request) throws ThingsboardException { if (!Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { user.setTenantId(getCurrentUser().getTenantId()); @@ -222,7 +221,7 @@ public class UserController extends BaseController { @RequestMapping(value = "/user/sendActivationMail", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) public void sendActivationEmail( - @ApiParam(value = "Email of the user", required = true) + @Parameter(description = "Email of the user", required = true) @RequestParam(value = "email") String email, HttpServletRequest request) throws ThingsboardException { User user = checkNotNull(userService.findUserByEmail(getCurrentUser().getTenantId(), email)); @@ -248,7 +247,7 @@ public class UserController extends BaseController { @RequestMapping(value = "/user/{userId}/activationLink", method = RequestMethod.GET, produces = "text/plain") @ResponseBody public String getActivationLink( - @ApiParam(value = USER_ID_PARAM_DESCRIPTION) + @Parameter(description = USER_ID_PARAM_DESCRIPTION) @PathVariable(USER_ID) String strUserId, HttpServletRequest request) throws ThingsboardException { checkParameter(USER_ID, strUserId); @@ -273,7 +272,7 @@ public class UserController extends BaseController { @RequestMapping(value = "/user/{userId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) public void deleteUser( - @ApiParam(value = USER_ID_PARAM_DESCRIPTION) + @Parameter(description = USER_ID_PARAM_DESCRIPTION) @PathVariable(USER_ID) String strUserId) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); @@ -291,15 +290,15 @@ public class UserController extends BaseController { @RequestMapping(value = "/users", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getUsers( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = USER_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = USER_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = USER_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "firstName", "lastName", "email"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); SecurityUser currentUser = getCurrentUser(); @@ -317,15 +316,15 @@ public class UserController extends BaseController { @RequestMapping(value = "/users/info", method = RequestMethod.GET) @ResponseBody public PageData findUsersByQuery( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = USER_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = USER_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = USER_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "firstName", "lastName", "email"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { SecurityUser securityUser = getCurrentUser(); @@ -354,17 +353,17 @@ public class UserController extends BaseController { @RequestMapping(value = "/tenant/{tenantId}/users", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getTenantAdmins( - @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = TENANT_ID_PARAM_DESCRIPTION, required = true) @PathVariable(TENANT_ID) String strTenantId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = USER_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = USER_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = USER_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "firstName", "lastName", "email"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("tenantId", strTenantId); TenantId tenantId = TenantId.fromUUID(toUUID(strTenantId)); @@ -378,17 +377,17 @@ public class UserController extends BaseController { @RequestMapping(value = "/customer/{customerId}/users", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getCustomerUsers( - @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = CUSTOMER_ID_PARAM_DESCRIPTION, required = true) @PathVariable(CUSTOMER_ID) String strCustomerId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = USER_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = USER_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = USER_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "firstName", "lastName", "email"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { checkParameter("customerId", strCustomerId); CustomerId customerId = new CustomerId(toUUID(strCustomerId)); @@ -404,9 +403,9 @@ public class UserController extends BaseController { @RequestMapping(value = "/user/{userId}/userCredentialsEnabled", method = RequestMethod.POST) @ResponseBody public void setUserCredentialsEnabled( - @ApiParam(value = USER_ID_PARAM_DESCRIPTION) + @Parameter(description = USER_ID_PARAM_DESCRIPTION) @PathVariable(USER_ID) String strUserId, - @ApiParam(value = "Enable (\"true\") or disable (\"false\") the credentials.", defaultValue = "true") + @Parameter(description = "Enable (\"true\") or disable (\"false\") the credentials." , schema = @Schema(defaultValue = "true")) @RequestParam(required = false, defaultValue = "true") boolean userCredentialsEnabled) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); @@ -427,17 +426,17 @@ public class UserController extends BaseController { @RequestMapping(value = "/users/assign/{alarmId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getUsersForAssign( - @ApiParam(value = ALARM_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = ALARM_ID_PARAM_DESCRIPTION, required = true) @PathVariable("alarmId") String strAlarmId, - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = USER_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = USER_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = USER_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "firstName", "lastName", "email"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { try { checkParameter("alarmId", strAlarmId); @@ -508,7 +507,7 @@ public class UserController extends BaseController { "Example: to delete B and C element in { \"A\": {\"B\": 5}, \"C\": 15} send A.B,C in jsonPaths request parameter") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/user/settings/{paths}", method = RequestMethod.DELETE) - public void deleteUserSettings(@ApiParam(value = PATHS) + public void deleteUserSettings(@Parameter(description = PATHS) @PathVariable(PATHS) String paths) throws ThingsboardException { checkParameter(USER_ID, paths); @@ -522,7 +521,7 @@ public class UserController extends BaseController { "{A:5, B:{C:10, D:30}}. The same could be achieved by putting {B.D:30}") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PutMapping(value = "/user/settings/{type}") - public void putUserSettings(@ApiParam(value = "Settings type, case insensitive, one of: \"general\", \"quick_links\", \"doc_links\" or \"dashboards\".") + public void putUserSettings(@Parameter(description = "Settings type, case insensitive, one of: \"general\", \"quick_links\", \"doc_links\" or \"dashboards\".") @PathVariable("type") String strType, @RequestBody JsonNode settings) throws ThingsboardException { SecurityUser currentUser = getCurrentUser(); UserSettingsType type = checkEnumParameter("Settings type", strType, UserSettingsType::valueOf); @@ -534,7 +533,7 @@ public class UserController extends BaseController { notes = "Fetch the User settings based on authorized user. ") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/user/settings/{type}") - public JsonNode getUserSettings(@ApiParam(value = "Settings type, case insensitive, one of: \"general\", \"quick_links\", \"doc_links\" or \"dashboards\".") + public JsonNode getUserSettings(@Parameter(description = "Settings type, case insensitive, one of: \"general\", \"quick_links\", \"doc_links\" or \"dashboards\".") @PathVariable("type") String strType) throws ThingsboardException { SecurityUser currentUser = getCurrentUser(); UserSettingsType type = checkEnumParameter("Settings type", strType, UserSettingsType::valueOf); @@ -548,9 +547,9 @@ public class UserController extends BaseController { "Example: to delete B and C element in { \"A\": {\"B\": 5}, \"C\": 15} send A.B,C in jsonPaths request parameter") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/user/settings/{type}/{paths}", method = RequestMethod.DELETE) - public void deleteUserSettings(@ApiParam(value = PATHS) + public void deleteUserSettings(@Parameter(description = PATHS) @PathVariable(PATHS) String paths, - @ApiParam(value = "Settings type, case insensitive, one of: \"general\", \"quick_links\", \"doc_links\" or \"dashboards\".") + @Parameter(description = "Settings type, case insensitive, one of: \"general\", \"quick_links\", \"doc_links\" or \"dashboards\".") @PathVariable("type") String strType) throws ThingsboardException { checkParameter(USER_ID, paths); UserSettingsType type = checkEnumParameter("Settings type", strType, UserSettingsType::valueOf); @@ -574,9 +573,9 @@ public class UserController extends BaseController { @RequestMapping(value = "/user/dashboards/{dashboardId}/{action}", method = RequestMethod.GET) @ResponseBody public UserDashboardsInfo reportUserDashboardAction( - @ApiParam(value = DASHBOARD_ID_PARAM_DESCRIPTION) + @Parameter(description = DASHBOARD_ID_PARAM_DESCRIPTION) @PathVariable(DashboardController.DASHBOARD_ID) String strDashboardId, - @ApiParam(value = "Dashboard action, one of: \"visit\", \"star\" or \"unstar\".") + @Parameter(description = "Dashboard action, one of: \"visit\", \"star\" or \"unstar\".") @PathVariable("action") String strAction) throws ThingsboardException { checkParameter(DashboardController.DASHBOARD_ID, strDashboardId); checkParameter("action", strAction); diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java index d1ecd0441a..9f71890e70 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -37,6 +36,7 @@ import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetTypeDetails; import org.thingsboard.server.common.data.widget.WidgetTypeInfo; import org.thingsboard.server.common.data.widget.WidgetsBundle; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.permission.Operation; @@ -67,7 +67,7 @@ public class WidgetTypeController extends AutoCommitController { @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.GET) @ResponseBody public WidgetTypeDetails getWidgetTypeById( - @ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("widgetTypeId") String strWidgetTypeId) throws ThingsboardException { checkParameter("widgetTypeId", strWidgetTypeId); WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId)); @@ -88,7 +88,7 @@ public class WidgetTypeController extends AutoCommitController { @RequestMapping(value = "/widgetType", method = RequestMethod.POST) @ResponseBody public WidgetTypeDetails saveWidgetType( - @ApiParam(value = "A JSON value representing the Widget Type Details.", required = true) + @Parameter(description = "A JSON value representing the Widget Type Details.", required = true) @RequestBody WidgetTypeDetails widgetTypeDetails) throws Exception { var currentUser = getCurrentUser(); if (Authority.SYS_ADMIN.equals(currentUser.getAuthority())) { @@ -119,7 +119,7 @@ public class WidgetTypeController extends AutoCommitController { @RequestMapping(value = "/widgetType/{widgetTypeId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) public void deleteWidgetType( - @ApiParam(value = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = WIDGET_TYPE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("widgetTypeId") String strWidgetTypeId) throws Exception { checkParameter("widgetTypeId", strWidgetTypeId); var currentUser = getCurrentUser(); @@ -143,9 +143,9 @@ public class WidgetTypeController extends AutoCommitController { @RequestMapping(value = "/widgetTypes", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) @ResponseBody public List getBundleWidgetTypes( - @ApiParam(value = "System or Tenant", required = true) + @Parameter(description = "System or Tenant", required = true) @RequestParam boolean isSystem, - @ApiParam(value = "Widget Bundle alias", required = true) + @Parameter(description = "Widget Bundle alias", required = true) @RequestParam String bundleAlias) throws ThingsboardException { TenantId tenantId; if (isSystem) { @@ -162,9 +162,9 @@ public class WidgetTypeController extends AutoCommitController { @RequestMapping(value = "/widgetTypesDetails", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) @ResponseBody public List getBundleWidgetTypesDetails( - @ApiParam(value = "System or Tenant", required = true) + @Parameter(description = "System or Tenant", required = true) @RequestParam boolean isSystem, - @ApiParam(value = "Widget Bundle alias", required = true) + @Parameter(description = "Widget Bundle alias", required = true) @RequestParam String bundleAlias) throws ThingsboardException { TenantId tenantId; if (isSystem) { @@ -181,9 +181,9 @@ public class WidgetTypeController extends AutoCommitController { @RequestMapping(value = "/widgetTypesInfos", params = {"isSystem", "bundleAlias"}, method = RequestMethod.GET) @ResponseBody public List getBundleWidgetTypesInfos( - @ApiParam(value = "System or Tenant", required = true) + @Parameter(description = "System or Tenant", required = true) @RequestParam boolean isSystem, - @ApiParam(value = "Widget Bundle alias", required = true) + @Parameter(description = "Widget Bundle alias", required = true) @RequestParam String bundleAlias) throws ThingsboardException { TenantId tenantId; if (isSystem) { @@ -200,11 +200,11 @@ public class WidgetTypeController extends AutoCommitController { @RequestMapping(value = "/widgetType", params = {"isSystem", "bundleAlias", "alias"}, method = RequestMethod.GET) @ResponseBody public WidgetType getWidgetType( - @ApiParam(value = "System or Tenant", required = true) + @Parameter(description = "System or Tenant", required = true) @RequestParam boolean isSystem, - @ApiParam(value = "Widget Bundle alias", required = true) + @Parameter(description = "Widget Bundle alias", required = true) @RequestParam String bundleAlias, - @ApiParam(value = "Widget Type alias", required = true) + @Parameter(description = "Widget Type alias", required = true) @RequestParam String alias) throws ThingsboardException { TenantId tenantId; if (isSystem) { diff --git a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java index 737e6d54d5..9e36015ee1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java +++ b/application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java @@ -15,8 +15,8 @@ */ package org.thingsboard.server.controller; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.widget.WidgetsBundle; +import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.widgets.bundle.TbWidgetsBundleService; import org.thingsboard.server.service.security.permission.Operation; @@ -46,13 +47,11 @@ import static org.thingsboard.server.controller.ControllerConstants.AVAILABLE_FO import static org.thingsboard.server.controller.ControllerConstants.PAGE_DATA_PARAMETERS; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.UUID_WIKI_LINK; import static org.thingsboard.server.controller.ControllerConstants.WIDGET_BUNDLE_ID_PARAM_DESCRIPTION; -import static org.thingsboard.server.controller.ControllerConstants.WIDGET_BUNDLE_SORT_PROPERTY_ALLOWABLE_VALUES; import static org.thingsboard.server.controller.ControllerConstants.WIDGET_BUNDLE_TEXT_SEARCH_DESCRIPTION; @RestController @@ -71,7 +70,7 @@ public class WidgetsBundleController extends BaseController { @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.GET) @ResponseBody public WidgetsBundle getWidgetsBundleById( - @ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException { checkParameter("widgetsBundleId", strWidgetsBundleId); WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); @@ -92,7 +91,7 @@ public class WidgetsBundleController extends BaseController { @RequestMapping(value = "/widgetsBundle", method = RequestMethod.POST) @ResponseBody public WidgetsBundle saveWidgetsBundle( - @ApiParam(value = "A JSON value representing the Widget Bundle.", required = true) + @Parameter(description = "A JSON value representing the Widget Bundle.", required = true) @RequestBody WidgetsBundle widgetsBundle) throws Exception { var currentUser = getCurrentUser(); if (Authority.SYS_ADMIN.equals(currentUser.getAuthority())) { @@ -112,7 +111,7 @@ public class WidgetsBundleController extends BaseController { @RequestMapping(value = "/widgetsBundle/{widgetsBundleId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) public void deleteWidgetsBundle( - @ApiParam(value = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true) + @Parameter(description = WIDGET_BUNDLE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("widgetsBundleId") String strWidgetsBundleId) throws ThingsboardException { checkParameter("widgetsBundleId", strWidgetsBundleId); WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId)); @@ -127,15 +126,15 @@ public class WidgetsBundleController extends BaseController { @RequestMapping(value = "/widgetsBundles", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody public PageData getWidgetsBundles( - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true) + @Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @RequestParam int pageSize, - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true) + @Parameter(description = PAGE_NUMBER_DESCRIPTION, required = true) @RequestParam int page, - @ApiParam(value = WIDGET_BUNDLE_TEXT_SEARCH_DESCRIPTION) + @Parameter(description = WIDGET_BUNDLE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = WIDGET_BUNDLE_SORT_PROPERTY_ALLOWABLE_VALUES) + @Parameter(description = SORT_PROPERTY_DESCRIPTION, schema = @Schema(allowableValues = {"createdTime", "title", "tenantId"})) @RequestParam(required = false) String sortProperty, - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES) + @Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"})) @RequestParam(required = false) String sortOrder) throws ThingsboardException { PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); if (Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { diff --git a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java index 73d763af34..c436461c65 100644 --- a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java +++ b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java @@ -15,6 +15,10 @@ */ package org.thingsboard.server.controller.plugin; +import jakarta.websocket.RemoteEndpoint; +import jakarta.websocket.SendHandler; +import jakarta.websocket.SendResult; +import jakarta.websocket.Session; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.BeanCreationNotAllowedException; import org.springframework.beans.factory.annotation.Autowired; @@ -47,10 +51,6 @@ import org.thingsboard.server.service.ws.WebSocketService; import org.thingsboard.server.service.ws.WebSocketSessionRef; import org.thingsboard.server.service.ws.WebSocketSessionType; -import jakarta.websocket.RemoteEndpoint; -import jakarta.websocket.SendHandler; -import jakarta.websocket.SendResult; -import jakarta.websocket.Session; import java.io.IOException; import java.net.URI; import java.security.InvalidParameterException; diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardCredentialsExpiredResponse.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardCredentialsExpiredResponse.java index 46e7205824..a055d4c94a 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardCredentialsExpiredResponse.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardCredentialsExpiredResponse.java @@ -15,12 +15,11 @@ */ package org.thingsboard.server.exception; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.http.HttpStatus; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; -@ApiModel +@Schema public class ThingsboardCredentialsExpiredResponse extends ThingsboardErrorResponse { private final String resetToken; @@ -34,7 +33,7 @@ public class ThingsboardCredentialsExpiredResponse extends ThingsboardErrorRespo return new ThingsboardCredentialsExpiredResponse(message, resetToken); } - @ApiModelProperty(position = 5, value = "Password reset token", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Password reset token", accessMode = Schema.AccessMode.READ_ONLY) public String getResetToken() { return resetToken; } diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java index 73cc5b0902..e1a76bbcac 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java @@ -15,14 +15,13 @@ */ package org.thingsboard.server.exception; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.http.HttpStatus; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import java.util.Date; -@ApiModel +@Schema public class ThingsboardErrorResponse { // HTTP Response Status Code private final HttpStatus status; @@ -46,17 +45,17 @@ public class ThingsboardErrorResponse { return new ThingsboardErrorResponse(message, errorCode, status); } - @ApiModelProperty(position = 1, value = "HTTP Response Status Code", example = "401", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "HTTP Response Status Code", example = "401", accessMode = Schema.AccessMode.READ_ONLY) public Integer getStatus() { return status.value(); } - @ApiModelProperty(position = 2, value = "Error message", example = "Authentication failed", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Error message", example = "Authentication failed", accessMode = Schema.AccessMode.READ_ONLY) public String getMessage() { return message; } - @ApiModelProperty(position = 3, value = "Platform error code:" + + @Schema(description = "Platform error code:" + "\n* `2` - General error (HTTP: 500 - Internal Server Error)" + "\n\n* `10` - Authentication failed (HTTP: 401 - Unauthorized)" + "\n\n* `11` - JWT token expired (HTTP: 401 - Unauthorized)" + @@ -68,13 +67,13 @@ public class ThingsboardErrorResponse { "\n\n* `33` - Too many requests (HTTP: 429 - Too Many Requests)" + "\n\n* `34` - Too many updates (Too many updates over Websocket session)" + "\n\n* `40` - Subscription violation (HTTP: 403 - Forbidden)", - example = "10", dataType = "integer", - accessMode = ApiModelProperty.AccessMode.READ_ONLY) + example = "10", type = "integer", + accessMode = Schema.AccessMode.READ_ONLY) public ThingsboardErrorCode getErrorCode() { return errorCode; } - @ApiModelProperty(position = 4, value = "Timestamp", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp", accessMode = Schema.AccessMode.READ_ONLY) public Date getTimestamp() { return timestamp; } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/LoginRequest.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/LoginRequest.java index 78cf6b1f98..6065466a62 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/LoginRequest.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/LoginRequest.java @@ -17,10 +17,9 @@ package org.thingsboard.server.service.security.auth.rest; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; -@ApiModel +@Schema public class LoginRequest { private String username; @@ -33,12 +32,12 @@ public class LoginRequest { this.password = password; } - @ApiModelProperty(position = 1, required = true, value = "User email", example = "tenant@thingsboard.org") + @Schema(required = true, description = "User email", example = "tenant@thingsboard.org") public String getUsername() { return username; } - @ApiModelProperty(position = 2, required = true, value = "User password", example = "tenant") + @Schema(required = true, description = "User password", example = "tenant") public String getPassword() { return password; } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/LoginResponse.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/LoginResponse.java index 8fdd443fe8..91113a4caa 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/LoginResponse.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/LoginResponse.java @@ -15,19 +15,18 @@ */ package org.thingsboard.server.service.security.auth.rest; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class LoginResponse { - @ApiModelProperty(position = 1, required = true, value = "JWT token", + @Schema(required = true, description = "JWT token", example = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZW5hbnRAdGhpbmdzYm9hcmQub3JnIi...") private String token; - @ApiModelProperty(position = 2, required = true, value = "Refresh token", + @Schema(required = true, description = "Refresh token", example = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZW5hbnRAdGhpbmdzYm9hcmQub3JnIi...") private String refreshToken; diff --git a/application/src/main/java/org/thingsboard/server/service/security/model/ActivateUserRequest.java b/application/src/main/java/org/thingsboard/server/service/security/model/ActivateUserRequest.java index aff95ea246..a3f6057d61 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/model/ActivateUserRequest.java +++ b/application/src/main/java/org/thingsboard/server/service/security/model/ActivateUserRequest.java @@ -15,16 +15,15 @@ */ package org.thingsboard.server.service.security.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class ActivateUserRequest { - @ApiModelProperty(position = 1, value = "The activate token to verify", example = "AAB254FF67D..") + @Schema(description = "The activate token to verify", example = "AAB254FF67D..") private String activateToken; - @ApiModelProperty(position = 2, value = "The new password to set", example = "secret") + @Schema(description = "The new password to set", example = "secret") private String password; } diff --git a/application/src/main/java/org/thingsboard/server/service/security/model/ChangePasswordRequest.java b/application/src/main/java/org/thingsboard/server/service/security/model/ChangePasswordRequest.java index 4b21acef5e..0596f8f43a 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/model/ChangePasswordRequest.java +++ b/application/src/main/java/org/thingsboard/server/service/security/model/ChangePasswordRequest.java @@ -15,17 +15,16 @@ */ package org.thingsboard.server.service.security.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class ChangePasswordRequest { - @ApiModelProperty(position = 1, value = "The old password", example = "OldPassword") + @Schema(description = "The old password", example = "OldPassword") private String currentPassword; - @ApiModelProperty(position = 1, value = "The new password", example = "NewPassword") + @Schema(description = "The new password", example = "NewPassword") private String newPassword; } diff --git a/application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordEmailRequest.java b/application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordEmailRequest.java index 93f9541986..fb4832a264 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordEmailRequest.java +++ b/application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordEmailRequest.java @@ -15,14 +15,13 @@ */ package org.thingsboard.server.service.security.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class ResetPasswordEmailRequest { - @ApiModelProperty(position = 1, value = "The email of the user", example = "user@example.com") + @Schema(description = "The email of the user", example = "user@example.com") private String email; } diff --git a/application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordRequest.java b/application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordRequest.java index 3869da9b02..6afeff730b 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordRequest.java +++ b/application/src/main/java/org/thingsboard/server/service/security/model/ResetPasswordRequest.java @@ -15,16 +15,15 @@ */ package org.thingsboard.server.service.security.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class ResetPasswordRequest { - @ApiModelProperty(position = 1, value = "The reset token to verify", example = "AAB254FF67D..") + @Schema(description = "The reset token to verify", example = "AAB254FF67D..") private String resetToken; - @ApiModelProperty(position = 2, value = "The new password to set", example = "secret") + @Schema(description = "The new password to set", example = "secret") private String password; } diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/AttributeData.java b/application/src/main/java/org/thingsboard/server/service/telemetry/AttributeData.java index b7c7b281ca..58a56e05c1 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/AttributeData.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/AttributeData.java @@ -15,10 +15,9 @@ */ package org.thingsboard.server.service.telemetry; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; -@ApiModel +@Schema public class AttributeData implements Comparable{ private final long lastUpdateTs; @@ -32,17 +31,17 @@ public class AttributeData implements Comparable{ this.value = value; } - @ApiModelProperty(position = 1, value = "Timestamp last updated attribute, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp last updated attribute, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) public long getLastUpdateTs() { return lastUpdateTs; } - @ApiModelProperty(position = 2, value = "String representing attribute key", example = "active", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "String representing attribute key", example = "active", accessMode = Schema.AccessMode.READ_ONLY) public String getKey() { return key; } - @ApiModelProperty(position = 3, value = "Object representing value of attribute key", example = "false", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Object representing value of attribute key", example = "false", accessMode = Schema.AccessMode.READ_ONLY) public Object getValue() { return value; } diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/TsData.java b/application/src/main/java/org/thingsboard/server/service/telemetry/TsData.java index d0af1080d3..d0f07ac094 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/TsData.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/TsData.java @@ -15,10 +15,9 @@ */ package org.thingsboard.server.service.telemetry; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; -@ApiModel +@Schema public class TsData implements Comparable{ private final long ts; @@ -30,12 +29,12 @@ public class TsData implements Comparable{ this.value = value; } - @ApiModelProperty(position = 1, value = "Timestamp last updated timeseries, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp last updated timeseries, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) public long getTs() { return ts; } - @ApiModelProperty(position = 2, value = "Object representing value of timeseries key", example = "20", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Object representing value of timeseries key", example = "20", accessMode = Schema.AccessMode.READ_ONLY) public Object getValue() { return value; } diff --git a/application/src/main/java/org/thingsboard/server/springfox/SpringfoxHandlerProviderBeanPostProcessor.java b/application/src/main/java/org/thingsboard/server/springfox/SpringfoxHandlerProviderBeanPostProcessor.java deleted file mode 100644 index 6a222870b0..0000000000 --- a/application/src/main/java/org/thingsboard/server/springfox/SpringfoxHandlerProviderBeanPostProcessor.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright © 2016-2023 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.springfox; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.stereotype.Component; -import org.springframework.util.ReflectionUtils; -import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; -import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider; - -import java.lang.reflect.Field; -import java.util.List; -import java.util.stream.Collectors; - -@Component -//TODO: remove after fixing issue https://github.com/springfox/springfox/issues/3462 or after migration from springfox to springdoc -public class SpringfoxHandlerProviderBeanPostProcessor implements BeanPostProcessor { - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof WebMvcRequestHandlerProvider) { - customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); - } - return bean; - } - - private void customizeSpringfoxHandlerMappings(List mappings) { - List copy = mappings.stream() - .filter(mapping -> mapping.getPatternParser() == null) - .collect(Collectors.toList()); - mappings.clear(); - mappings.addAll(copy); - } - - @SuppressWarnings("unchecked") - private List getHandlerMappings(Object bean) { - try { - Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); - field.setAccessible(true); - return (List) field.get(bean); - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new IllegalStateException(e); - } - } -} diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 6e68e1066f..7473121866 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -988,10 +988,12 @@ edges: state: persistToTelemetry: "${EDGES_PERSIST_STATE_TO_TELEMETRY:false}" +springdoc: + api-docs.enabled: "${SWAGGER_ENABLED:true}" + default-produces-media-type: "${SWAGGER_DEFAULT_PRODUCES_MEDIA_TYPE:application/json}" + swagger: - enabled: "${SWAGGER_ENABLED:true}" - api_path_regex: "${SWAGGER_API_PATH_REGEX:/api/.*}" - security_path_regex: "${SWAGGER_SECURITY_PATH_REGEX:/api/.*}" + api_path: "${SWAGGER_API_PATH:/api/**}" non_security_path_regex: "${SWAGGER_NON_SECURITY_PATH_REGEX:/api/(?:noauth|v1)/.*}" title: "${SWAGGER_TITLE:ThingsBoard REST API}" description: "${SWAGGER_DESCRIPTION: ThingsBoard open-source IoT platform REST API documentation.}" diff --git a/common/data/pom.xml b/common/data/pom.xml index cf528b9bbd..9aa6aed2c0 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -105,8 +105,8 @@ commons-codec - io.swagger - swagger-annotations + io.swagger.core.v3 + swagger-annotations-jakarta com.google.protobuf diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/AdminSettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/AdminSettings.java index c1f296c26c..a70d235bd5 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/AdminSettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/AdminSettings.java @@ -16,14 +16,13 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.id.AdminSettingsId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema public class AdminSettings extends BaseData implements HasTenantId { private static final long serialVersionUID = -7670322981725511892L; @@ -50,19 +49,19 @@ public class AdminSettings extends BaseData implements HasTenan this.jsonValue = adminSettings.getJsonValue(); } - @ApiModelProperty(position = 1, value = "The Id of the Administration Settings, auto-generated, UUID") + @Schema(description = "The Id of the Administration Settings, auto-generated, UUID") @Override public AdminSettingsId getId() { return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the settings creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the settings creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) public TenantId getTenantId() { return tenantId; } @@ -71,7 +70,7 @@ public class AdminSettings extends BaseData implements HasTenan this.tenantId = tenantId; } - @ApiModelProperty(position = 4, value = "The Administration Settings key, (e.g. 'general' or 'mail')", example = "mail") + @Schema(description = "The Administration Settings key, (e.g. 'general' or 'mail')", example = "mail") public String getKey() { return key; } @@ -80,7 +79,7 @@ public class AdminSettings extends BaseData implements HasTenan this.key = key; } - @ApiModelProperty(position = 5, value = "JSON representation of the Administration Settings value") + @Schema(description = "JSON representation of the Administration Settings value") public JsonNode getJsonValue() { return jsonValue; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java b/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java index 636ab0de38..6f9d6e4360 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java @@ -19,7 +19,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty.Access; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -35,9 +36,9 @@ public class Customer extends ContactBased implements HasTenantId, E @NoXss @Length(fieldName = "title") - @ApiModelProperty(position = 3, value = "Title of the customer", example = "Company A") + @Schema(description = "Title of the customer", example = "Company A") private String title; - @ApiModelProperty(position = 5, required = true, value = "JSON object with Tenant Id") + @Schema(required = true, description = "JSON object with Tenant Id") private TenantId tenantId; @Getter @Setter @@ -74,7 +75,7 @@ public class Customer extends ContactBased implements HasTenantId, E this.title = title; } - @ApiModelProperty(position = 1, value = "JSON object with the customer Id. " + + @Schema(description = "JSON object with the customer Id. " + "Specify this field to update the customer. " + "Referencing non-existing customer Id will cause error. " + "Omit this field to create new customer." ) @@ -83,61 +84,61 @@ public class Customer extends ContactBased implements HasTenantId, E return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the customer creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the customer creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 6, required = true, value = "Country", example = "US") + @Schema(required = true, description = "Country", example = "US") @Override public String getCountry() { return super.getCountry(); } - @ApiModelProperty(position = 7, required = true, value = "State", example = "NY") + @Schema(required = true, description = "State", example = "NY") @Override public String getState() { return super.getState(); } - @ApiModelProperty(position = 8, required = true, value = "City", example = "New York") + @Schema(required = true, description = "City", example = "New York") @Override public String getCity() { return super.getCity(); } - @ApiModelProperty(position = 9, required = true, value = "Address Line 1", example = "42 Broadway Suite 12-400") + @Schema(required = true, description = "Address Line 1", example = "42 Broadway Suite 12-400") @Override public String getAddress() { return super.getAddress(); } - @ApiModelProperty(position = 10, required = true, value = "Address Line 2", example = "") + @Schema(required = true, description = "Address Line 2", example = "") @Override public String getAddress2() { return super.getAddress2(); } - @ApiModelProperty(position = 11, required = true, value = "Zip code", example = "10004") + @Schema(required = true, description = "Zip code", example = "10004") @Override public String getZip() { return super.getZip(); } - @ApiModelProperty(position = 12, required = true, value = "Phone number", example = "+1(415)777-7777") + @Schema(required = true, description = "Phone number", example = "+1(415)777-7777") @Override public String getPhone() { return super.getPhone(); } - @ApiModelProperty(position = 13, required = true, value = "Email", example = "example@company.com") + @Schema(required = true, description = "Email", example = "example@company.com") @Override public String getEmail() { return super.getEmail(); } - @ApiModelProperty(position = 14, value = "Additional parameters of the device", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "Additional parameters of the device",implementation = com.fasterxml.jackson.databind.JsonNode.class) @Override public JsonNode getAdditionalInfo() { return super.getAdditionalInfo(); @@ -159,7 +160,7 @@ public class Customer extends ContactBased implements HasTenantId, E @Override @JsonProperty(access = Access.READ_ONLY) - @ApiModelProperty(position = 4, value = "Name of the customer. Read-only, duplicated from title for backward compatibility", example = "Company A", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Name of the customer. Read-only, duplicated from title for backward compatibility", example = "Company A", accessMode = Schema.AccessMode.READ_ONLY) public String getName() { return title; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Dashboard.java b/common/data/src/main/java/org/thingsboard/server/common/data/Dashboard.java index 10496aaaa2..f0e09a1128 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/Dashboard.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Dashboard.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.Streams; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -59,10 +59,10 @@ public class Dashboard extends DashboardInfo implements ExportableEntity implements HasName, HasTenantId, HasTitle { private TenantId tenantId; @@ -61,7 +60,7 @@ public class DashboardInfo extends BaseData implements HasName, Has this.mobileOrder = dashboardInfo.getMobileOrder(); } - @ApiModelProperty(position = 1, value = "JSON object with the dashboard Id. " + + @Schema(description = "JSON object with the dashboard Id. " + "Specify existing dashboard Id to update the dashboard. " + "Referencing non-existing dashboard id will cause error. " + "Omit this field to create new dashboard.") @@ -70,13 +69,13 @@ public class DashboardInfo extends BaseData implements HasName, Has return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the dashboard creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the dashboard creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id. Tenant Id of the dashboard can't be changed.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id. Tenant Id of the dashboard can't be changed.", accessMode = Schema.AccessMode.READ_ONLY) public TenantId getTenantId() { return tenantId; } @@ -85,7 +84,7 @@ public class DashboardInfo extends BaseData implements HasName, Has this.tenantId = tenantId; } - @ApiModelProperty(position = 4, value = "Title of the dashboard.") + @Schema(description = "Title of the dashboard.") public String getTitle() { return title; } @@ -94,7 +93,7 @@ public class DashboardInfo extends BaseData implements HasName, Has this.title = title; } - @ApiModelProperty(position = 8, value = "Thumbnail picture for rendering of the dashboards in a grid view on mobile devices.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Thumbnail picture for rendering of the dashboards in a grid view on mobile devices.", accessMode = Schema.AccessMode.READ_ONLY) public String getImage() { return image; } @@ -103,7 +102,7 @@ public class DashboardInfo extends BaseData implements HasName, Has this.image = image; } - @ApiModelProperty(position = 5, value = "List of assigned customers with their info.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "List of assigned customers with their info.", accessMode = Schema.AccessMode.READ_ONLY) public Set getAssignedCustomers() { return assignedCustomers; } @@ -112,7 +111,7 @@ public class DashboardInfo extends BaseData implements HasName, Has this.assignedCustomers = assignedCustomers; } - @ApiModelProperty(position = 6, value = "Hide dashboard from mobile devices. Useful if the dashboard is not designed for small screens.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Hide dashboard from mobile devices. Useful if the dashboard is not designed for small screens.", accessMode = Schema.AccessMode.READ_ONLY) public boolean isMobileHide() { return mobileHide; } @@ -121,7 +120,7 @@ public class DashboardInfo extends BaseData implements HasName, Has this.mobileHide = mobileHide; } - @ApiModelProperty(position = 7, value = "Order on mobile devices. Useful to adjust sorting of the dashboards for mobile applications", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Order on mobile devices. Useful to adjust sorting of the dashboards for mobile applications", accessMode = Schema.AccessMode.READ_ONLY) public Integer getMobileOrder() { return mobileOrder; } @@ -179,7 +178,7 @@ public class DashboardInfo extends BaseData implements HasName, Has } } - @ApiModelProperty(position = 4, value = "Same as title of the dashboard. Read-only field. Update the 'title' to change the 'name' of the dashboard.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Same as title of the dashboard. Read-only field. Update the 'title' to change the 'name' of the dashboard.", accessMode = Schema.AccessMode.READ_ONLY) @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Device.java b/common/data/src/main/java/org/thingsboard/server/common/data/Device.java index 45e4244bcb..c8cb6384e2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/Device.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Device.java @@ -18,8 +18,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -37,7 +36,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Optional; -@ApiModel +@Schema @EqualsAndHashCode(callSuper = true) @Slf4j public class Device extends BaseDataWithAdditionalInfo implements HasLabel, HasTenantId, HasCustomerId, HasOtaPackage, ExportableEntity { @@ -103,7 +102,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL return this; } - @ApiModelProperty(position = 1, value = "JSON object with the Device Id. " + + @Schema(description = "JSON object with the Device Id. " + "Specify this field to update the Device. " + "Referencing non-existing Device Id will cause error. " + "Omit this field to create new Device." ) @@ -112,13 +111,13 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the device creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the device creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id. Use 'assignDeviceToTenant' to change the Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id. Use 'assignDeviceToTenant' to change the Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) public TenantId getTenantId() { return tenantId; } @@ -127,7 +126,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.tenantId = tenantId; } - @ApiModelProperty(position = 4, value = "JSON object with Customer Id. Use 'assignDeviceToCustomer' to change the Customer Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Customer Id. Use 'assignDeviceToCustomer' to change the Customer Id.", accessMode = Schema.AccessMode.READ_ONLY) public CustomerId getCustomerId() { return customerId; } @@ -136,7 +135,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.customerId = customerId; } - @ApiModelProperty(position = 5, required = true, value = "Unique Device Name in scope of Tenant", example = "A4B72CCDFF33") + @Schema(required = true, description = "Unique Device Name in scope of Tenant", example = "A4B72CCDFF33") @Override public String getName() { return name; @@ -146,7 +145,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.name = name; } - @ApiModelProperty(position = 6, required = true, value = "Device Profile Name", example = "Temperature Sensor") + @Schema(required = true, description = "Device Profile Name", example = "Temperature Sensor") public String getType() { return type; } @@ -155,7 +154,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.type = type; } - @ApiModelProperty(position = 7, required = true, value = "Label that may be used in widgets", example = "Room 234 Sensor") + @Schema(required = true, description = "Label that may be used in widgets", example = "Room 234 Sensor") public String getLabel() { return label; } @@ -164,7 +163,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.label = label; } - @ApiModelProperty(position = 8, required = true, value = "JSON object with Device Profile Id.") + @Schema(required = true, description = "JSON object with Device Profile Id.") public DeviceProfileId getDeviceProfileId() { return deviceProfileId; } @@ -173,7 +172,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.deviceProfileId = deviceProfileId; } - @ApiModelProperty(position = 9, value = "JSON object with content specific to type of transport in the device profile.") + @Schema(description = "JSON object with content specific to type of transport in the device profile.") public DeviceData getDeviceData() { if (deviceData != null) { return deviceData; @@ -201,7 +200,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL } } - @ApiModelProperty(position = 10, value = "JSON object with Ota Package Id.") + @Schema(description = "JSON object with Ota Package Id.") public OtaPackageId getFirmwareId() { return firmwareId; } @@ -210,7 +209,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.firmwareId = firmwareId; } - @ApiModelProperty(position = 11, value = "JSON object with Ota Package Id.") + @Schema(description = "JSON object with Ota Package Id.") public OtaPackageId getSoftwareId() { return softwareId; } @@ -219,7 +218,7 @@ public class Device extends BaseDataWithAdditionalInfo implements HasL this.softwareId = softwareId; } - @ApiModelProperty(position = 12, value = "Additional parameters of the device", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "Additional parameters of the device",implementation = com.fasterxml.jackson.databind.JsonNode.class) @Override public JsonNode getAdditionalInfo() { return super.getAdditionalInfo(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java index 3204cc217a..80cc3a1d24 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java @@ -15,26 +15,25 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.DeviceId; -@ApiModel +@Schema @Data @EqualsAndHashCode(callSuper = true) public class DeviceInfo extends Device { private static final long serialVersionUID = -3004579925090663691L; - @ApiModelProperty(position = 13, value = "Title of the Customer that owns the device.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Title of the Customer that owns the device.", accessMode = Schema.AccessMode.READ_ONLY) private String customerTitle; - @ApiModelProperty(position = 14, value = "Indicates special 'Public' Customer that is auto-generated to use the devices on public dashboards.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Indicates special 'Public' Customer that is auto-generated to use the devices on public dashboards.", accessMode = Schema.AccessMode.READ_ONLY) private boolean customerIsPublic; - @ApiModelProperty(position = 15, value = "Name of the corresponding Device Profile.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Name of the corresponding Device Profile.", accessMode = Schema.AccessMode.READ_ONLY) private String deviceProfileName; - @ApiModelProperty(position = 16, value = "Device active flag.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Device active flag.", accessMode = Schema.AccessMode.READ_ONLY) private boolean active; public DeviceInfo() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java index 2be110b258..090bafdb69 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java @@ -17,8 +17,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.JsonProcessingException; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -36,7 +35,7 @@ import jakarta.validation.Valid; import java.io.ByteArrayInputStream; import java.io.IOException; -@ApiModel +@Schema @Data @ToString(exclude = {"image", "profileDataBytes"}) @EqualsAndHashCode(callSuper = true) @@ -45,34 +44,34 @@ public class DeviceProfile extends BaseData implements HasName, private static final long serialVersionUID = 6998485460273302018L; - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id that owns the profile.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id that owns the profile.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; @NoXss @Length(fieldName = "name") - @ApiModelProperty(position = 4, value = "Unique Device Profile Name in scope of Tenant.", example = "Moisture Sensor") + @Schema(description = "Unique Device Profile Name in scope of Tenant.", example = "Moisture Sensor") private String name; @NoXss - @ApiModelProperty(position = 11, value = "Device Profile description. ") + @Schema(description = "Device Profile description. ") private String description; @Length(fieldName = "image", max = 1000000) - @ApiModelProperty(position = 12, value = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of device profiles in the grid view. ") + @Schema(description = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of device profiles in the grid view. ") private String image; private boolean isDefault; - @ApiModelProperty(position = 16, value = "Type of the profile. Always 'DEFAULT' for now. Reserved for future use.") + @Schema(description = "Type of the profile. Always 'DEFAULT' for now. Reserved for future use.") private DeviceProfileType type; - @ApiModelProperty(position = 14, value = "Type of the transport used to connect the device. Default transport supports HTTP, CoAP and MQTT.") + @Schema(description = "Type of the transport used to connect the device. Default transport supports HTTP, CoAP and MQTT.") private DeviceTransportType transportType; - @ApiModelProperty(position = 15, value = "Provisioning strategy.") + @Schema(description = "Provisioning strategy.") private DeviceProfileProvisionType provisionType; - @ApiModelProperty(position = 7, value = "Reference to the rule chain. " + + @Schema(description = "Reference to the rule chain. " + "If present, the specified rule chain will be used to process all messages related to device, including telemetry, attribute updates, etc. " + "Otherwise, the root rule chain will be used to process those messages.") private RuleChainId defaultRuleChainId; - @ApiModelProperty(position = 6, value = "Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to device details.") + @Schema(description = "Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to device details.") private DashboardId defaultDashboardId; @NoXss - @ApiModelProperty(position = 8, value = "Rule engine queue name. " + + @Schema(description = "Rule engine queue name. " + "If present, the specified queue will be used to store all unprocessed messages related to device, including telemetry, attribute updates, etc. " + "Otherwise, the 'Main' queue will be used to store those messages.") private String defaultQueueName; @@ -81,15 +80,15 @@ public class DeviceProfile extends BaseData implements HasName, @JsonIgnore private byte[] profileDataBytes; @NoXss - @ApiModelProperty(position = 13, value = "Unique provisioning key used by 'Device Provisioning' feature.") + @Schema(description = "Unique provisioning key used by 'Device Provisioning' feature.") private String provisionDeviceKey; - @ApiModelProperty(position = 9, value = "Reference to the firmware OTA package. If present, the specified package will be used as default device firmware. ") + @Schema(description = "Reference to the firmware OTA package. If present, the specified package will be used as default device firmware. ") private OtaPackageId firmwareId; - @ApiModelProperty(position = 10, value = "Reference to the software OTA package. If present, the specified package will be used as default device software. ") + @Schema(description = "Reference to the software OTA package. If present, the specified package will be used as default device software. ") private OtaPackageId softwareId; - @ApiModelProperty(position = 17, value = "Reference to the edge rule chain. " + + @Schema(description = "Reference to the edge rule chain. " + "If present, the specified edge rule chain will be used on the edge to process all messages related to device, including telemetry, attribute updates, etc. " + "Otherwise, the edge root rule chain will be used to process those messages.") private RuleChainId defaultEdgeRuleChainId; @@ -122,7 +121,7 @@ public class DeviceProfile extends BaseData implements HasName, this.externalId = deviceProfile.getExternalId(); } - @ApiModelProperty(position = 1, value = "JSON object with the device profile Id. " + + @Schema(description = "JSON object with the device profile Id. " + "Specify this field to update the device profile. " + "Referencing non-existing device profile Id will cause error. " + "Omit this field to create new device profile.") @@ -131,18 +130,18 @@ public class DeviceProfile extends BaseData implements HasName, return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the profile creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the profile creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 5, value = "Used to mark the default profile. Default profile is used when the device profile is not specified during device creation.") + @Schema(description = "Used to mark the default profile. Default profile is used when the device profile is not specified during device creation.") public boolean isDefault() { return isDefault; } - @ApiModelProperty(position = 16, value = "Complex JSON object that includes addition device profile configuration (transport, alarm rules, etc).") + @Schema(description = "Complex JSON object that includes addition device profile configuration (transport, alarm rules, etc).") public DeviceProfileData getProfileData() { if (profileData != null) { return profileData; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java index 295b9f6b99..93b094f901 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfileInfo.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.ToString; import lombok.Value; @@ -33,16 +33,16 @@ import java.util.UUID; @ToString(callSuper = true, exclude = "image") public class DeviceProfileInfo extends EntityInfo { - @ApiModelProperty(position = 3, value = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of device profiles in the grid view. ") + @Schema(description = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of device profiles in the grid view. ") private final String image; - @ApiModelProperty(position = 4, value = "Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to device details.") + @Schema(description = "Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to device details.") private final DashboardId defaultDashboardId; - @ApiModelProperty(position = 5, value = "Type of the profile. Always 'DEFAULT' for now. Reserved for future use.") + @Schema(description = "Type of the profile. Always 'DEFAULT' for now. Reserved for future use.") private final DeviceProfileType type; - @ApiModelProperty(position = 6, value = "Type of the transport used to connect the device. Default transport supports HTTP, CoAP and MQTT.") + @Schema(description = "Type of the transport used to connect the device. Default transport supports HTTP, CoAP and MQTT.") private final DeviceTransportType transportType; - @ApiModelProperty(position = 7, value = "Tenant id.") + @Schema(description = "Tenant id.") private final TenantId tenantId; @JsonCreator diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityInfo.java index 6a86a65d1f..d3109c68d6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityInfo.java @@ -17,8 +17,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; @@ -26,13 +25,13 @@ import org.thingsboard.server.common.data.id.HasId; import java.util.UUID; -@ApiModel +@Schema @Data public class EntityInfo implements HasId, HasName { - @ApiModelProperty(position = 1, value = "JSON object with the entity Id. ") + @Schema(description = "JSON object with the entity Id. ") private final EntityId id; - @ApiModelProperty(position = 2, value = "Entity Name") + @Schema(description = "Entity Name") private final String name; @JsonCreator diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java index c0e44baeb3..72c7346c9e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityView.java @@ -16,7 +16,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -40,23 +40,23 @@ public class EntityView extends BaseDataWithAdditionalInfo private static final long serialVersionUID = 5582010124562018986L; - @ApiModelProperty(position = 7, required = true, value = "JSON object with the referenced Entity Id (Device or Asset).") + @Schema(required = true, description = "JSON object with the referenced Entity Id (Device or Asset).") private EntityId entityId; private TenantId tenantId; private CustomerId customerId; @NoXss @Length(fieldName = "name") - @ApiModelProperty(position = 5, required = true, value = "Entity View name", example = "A4B72CCDFF33") + @Schema(required = true, description = "Entity View name", example = "A4B72CCDFF33") private String name; @NoXss @Length(fieldName = "type") - @ApiModelProperty(position = 6, required = true, value = "Device Profile Name", example = "Temperature Sensor") + @Schema(required = true, description = "Device Profile Name", example = "Temperature Sensor") private String type; - @ApiModelProperty(position = 8, required = true, value = "Set of telemetry and attribute keys to expose via Entity View.") + @Schema(required = true, description = "Set of telemetry and attribute keys to expose via Entity View.") private TelemetryEntityView keys; - @ApiModelProperty(position = 9, value = "Represents the start time of the interval that is used to limit access to target device telemetry. Customer will not be able to see entity telemetry that is outside the specified interval;") + @Schema(description = "Represents the start time of the interval that is used to limit access to target device telemetry. Customer will not be able to see entity telemetry that is outside the specified interval;") private long startTimeMs; - @ApiModelProperty(position = 10, value = "Represents the end time of the interval that is used to limit access to target device telemetry. Customer will not be able to see entity telemetry that is outside the specified interval;") + @Schema(description = "Represents the end time of the interval that is used to limit access to target device telemetry. Customer will not be able to see entity telemetry that is outside the specified interval;") private long endTimeMs; private EntityViewId externalId; @@ -82,7 +82,7 @@ public class EntityView extends BaseDataWithAdditionalInfo this.externalId = entityView.getExternalId(); } - @ApiModelProperty(position = 4, value = "JSON object with Customer Id. Use 'assignEntityViewToCustomer' to change the Customer Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Customer Id. Use 'assignEntityViewToCustomer' to change the Customer Id.", accessMode = Schema.AccessMode.READ_ONLY) @Override public CustomerId getCustomerId() { return customerId; @@ -93,13 +93,13 @@ public class EntityView extends BaseDataWithAdditionalInfo return name; } - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) @Override public TenantId getTenantId() { return tenantId; } - @ApiModelProperty(position = 1, value = "JSON object with the Entity View Id. " + + @Schema(description = "JSON object with the Entity View Id. " + "Specify this field to update the Entity View. " + "Referencing non-existing Entity View Id will cause error. " + "Omit this field to create new Entity View." ) @@ -108,13 +108,13 @@ public class EntityView extends BaseDataWithAdditionalInfo return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the Entity View creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the Entity View creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 11, value = "Additional parameters of the device", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "Additional parameters of the device",implementation = com.fasterxml.jackson.databind.JsonNode.class) @Override public JsonNode getAdditionalInfo() { return super.getAdditionalInfo(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityViewInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityViewInfo.java index 069ea3ae5d..ca3d26087f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityViewInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityViewInfo.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.EntityViewId; @@ -24,9 +24,9 @@ import org.thingsboard.server.common.data.id.EntityViewId; @EqualsAndHashCode(callSuper = true) public class EntityViewInfo extends EntityView { - @ApiModelProperty(position = 12, value = "Title of the Customer that owns the entity view.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Title of the Customer that owns the entity view.", accessMode = Schema.AccessMode.READ_ONLY) private String customerTitle; - @ApiModelProperty(position = 13, value = "Indicates special 'Public' Customer that is auto-generated to use the entity view on public dashboards.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Indicates special 'Public' Customer that is auto-generated to use the entity view on public dashboards.", accessMode = Schema.AccessMode.READ_ONLY) private boolean customerIsPublic; public EntityViewInfo() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java index 11491db4f9..d20438a5b3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EventInfo.java @@ -16,8 +16,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EventId; @@ -27,18 +26,18 @@ import org.thingsboard.server.common.data.id.TenantId; * @author Andrew Shvayka */ @Data -@ApiModel +@Schema public class EventInfo extends BaseData { - @ApiModelProperty(position = 1, value = "JSON object with Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; - @ApiModelProperty(position = 2, value = "Event type", example = "STATS") + @Schema(description = "Event type", example = "STATS") private String type; - @ApiModelProperty(position = 3, value = "string", example = "784f394c-42b6-435a-983c-b7beff2784f9") + @Schema(description = "string", example = "784f394c-42b6-435a-983c-b7beff2784f9") private String uid; - @ApiModelProperty(position = 4, value = "JSON object with Entity Id for which event is created.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Entity Id for which event is created.", accessMode = Schema.AccessMode.READ_ONLY) private EntityId entityId; - @ApiModelProperty(position = 5, value = "Event body.", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "Event body.",implementation = com.fasterxml.jackson.databind.JsonNode.class) private transient JsonNode body; public EventInfo() { @@ -53,7 +52,7 @@ public class EventInfo extends BaseData { super(event); } - @ApiModelProperty(position = 6, value = "Timestamp of the event creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the event creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ExportableEntity.java b/common/data/src/main/java/org/thingsboard/server/common/data/ExportableEntity.java index 4677cff29b..a2b21d2a86 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ExportableEntity.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ExportableEntity.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; @@ -24,7 +24,7 @@ public interface ExportableEntity extends HasId, HasName void setId(I id); - @ApiModelProperty(position = 100, value = "JSON object with External Id from the VCS", accessMode = ApiModelProperty.AccessMode.READ_ONLY, hidden = true) + @Schema(description = "JSON object with External Id from the VCS", accessMode = Schema.AccessMode.READ_ONLY, hidden = true) I getExternalId(); void setExternalId(I externalId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java b/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java index 6dfbfaa4ed..8971eb9f78 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboard.java @@ -15,17 +15,16 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class HomeDashboard extends Dashboard { public static final String HIDE_DASHBOARD_TOOLBAR_DESCRIPTION = "Hide dashboard toolbar flag. Useful for rendering dashboards on mobile."; - @ApiModelProperty(position = 10, value = HIDE_DASHBOARD_TOOLBAR_DESCRIPTION) + @Schema(description = HIDE_DASHBOARD_TOOLBAR_DESCRIPTION) private boolean hideDashboardToolbar; public HomeDashboard(Dashboard dashboard, boolean hideDashboardToolbar) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboardInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboardInfo.java index ae694fd61a..173b88259c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboardInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/HomeDashboardInfo.java @@ -15,18 +15,17 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import org.thingsboard.server.common.data.id.DashboardId; -@ApiModel +@Schema @Data @AllArgsConstructor public class HomeDashboardInfo { - @ApiModelProperty(position = 1, value = "JSON object with the dashboard Id.") + @Schema(description = "JSON object with the dashboard Id.") private DashboardId dashboardId; - @ApiModelProperty(position = 1, value = HomeDashboard.HIDE_DASHBOARD_TOOLBAR_DESCRIPTION) + @Schema(description = HomeDashboard.HIDE_DASHBOARD_TOOLBAR_DESCRIPTION) private boolean hideDashboardToolbar; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/OtaPackage.java b/common/data/src/main/java/org/thingsboard/server/common/data/OtaPackage.java index d3aaddf3af..d7f4f20e02 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/OtaPackage.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/OtaPackage.java @@ -15,22 +15,21 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.OtaPackageId; import java.nio.ByteBuffer; -@ApiModel +@Schema @Data @EqualsAndHashCode(callSuper = true) public class OtaPackage extends OtaPackageInfo { private static final long serialVersionUID = 3091601761339422546L; - @ApiModelProperty(position = 16, value = "OTA Package data.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package data.", accessMode = Schema.AccessMode.READ_ONLY) private transient ByteBuffer data; public OtaPackage() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/OtaPackageInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/OtaPackageInfo.java index ab84724117..aa43567adc 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/OtaPackageInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/OtaPackageInfo.java @@ -17,8 +17,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -30,7 +29,7 @@ import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @Slf4j @Data @EqualsAndHashCode(callSuper = true) @@ -38,44 +37,44 @@ public class OtaPackageInfo extends BaseDataWithAdditionalInfo imp private static final long serialVersionUID = 3168391583570815419L; - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id. Tenant Id of the ota package can't be changed.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id. Tenant Id of the ota package can't be changed.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; - @ApiModelProperty(position = 4, value = "JSON object with Device Profile Id. Device Profile Id of the ota package can't be changed.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Device Profile Id. Device Profile Id of the ota package can't be changed.", accessMode = Schema.AccessMode.READ_ONLY) private DeviceProfileId deviceProfileId; - @ApiModelProperty(position = 5, value = "OTA Package type.", example = "FIRMWARE", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package type.", example = "FIRMWARE", accessMode = Schema.AccessMode.READ_ONLY) private OtaPackageType type; @Length(fieldName = "title") @NoXss - @ApiModelProperty(position = 6, value = "OTA Package title.", example = "fw", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package title.", example = "fw", accessMode = Schema.AccessMode.READ_ONLY) private String title; @Length(fieldName = "version") @NoXss - @ApiModelProperty(position = 7, value = "OTA Package version.", example = "1.0", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package version.", example = "1.0", accessMode = Schema.AccessMode.READ_ONLY) private String version; @Length(fieldName = "tag") @NoXss - @ApiModelProperty(position = 8, value = "OTA Package tag.", example = "fw_1.0", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package tag.", example = "fw_1.0", accessMode = Schema.AccessMode.READ_ONLY) private String tag; @Length(fieldName = "url") @NoXss - @ApiModelProperty(position = 9, value = "OTA Package url.", example = "http://thingsboard.org/fw/1", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package url.", example = "http://thingsboard.org/fw/1", accessMode = Schema.AccessMode.READ_ONLY) private String url; - @ApiModelProperty(position = 10, value = "Indicates OTA Package 'has data'. Field is returned from DB ('true' if data exists or url is set). If OTA Package 'has data' is 'false' we can not assign the OTA Package to the Device or Device Profile.", example = "true", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Indicates OTA Package 'has data'. Field is returned from DB ('true' if data exists or url is set). If OTA Package 'has data' is 'false' we can not assign the OTA Package to the Device or Device Profile.", example = "true", accessMode = Schema.AccessMode.READ_ONLY) private boolean hasData; @Length(fieldName = "file name") @NoXss - @ApiModelProperty(position = 11, value = "OTA Package file name.", example = "fw_1.0", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package file name.", example = "fw_1.0", accessMode = Schema.AccessMode.READ_ONLY) private String fileName; @NoXss @Length(fieldName = "contentType") - @ApiModelProperty(position = 12, value = "OTA Package content type.", example = "APPLICATION_OCTET_STREAM", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package content type.", example = "APPLICATION_OCTET_STREAM", accessMode = Schema.AccessMode.READ_ONLY) private String contentType; - @ApiModelProperty(position = 13, value = "OTA Package checksum algorithm.", example = "CRC32", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package checksum algorithm.", example = "CRC32", accessMode = Schema.AccessMode.READ_ONLY) private ChecksumAlgorithm checksumAlgorithm; @Length(fieldName = "checksum", max = 1020) - @ApiModelProperty(position = 14, value = "OTA Package checksum.", example = "0xd87f7e0c", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package checksum.", example = "0xd87f7e0c", accessMode = Schema.AccessMode.READ_ONLY) private String checksum; - @ApiModelProperty(position = 15, value = "OTA Package data size.", example = "8", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "OTA Package data size.", example = "8", accessMode = Schema.AccessMode.READ_ONLY) private Long dataSize; public OtaPackageInfo() { @@ -103,7 +102,7 @@ public class OtaPackageInfo extends BaseDataWithAdditionalInfo imp this.dataSize = otaPackageInfo.getDataSize(); } - @ApiModelProperty(position = 1, value = "JSON object with the ota package Id. " + + @Schema(description = "JSON object with the ota package Id. " + "Specify existing ota package Id to update the ota package. " + "Referencing non-existing ota package id will cause error. " + "Omit this field to create new ota package.") @@ -112,7 +111,7 @@ public class OtaPackageInfo extends BaseDataWithAdditionalInfo imp return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the ota package creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the ota package creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); @@ -129,7 +128,7 @@ public class OtaPackageInfo extends BaseDataWithAdditionalInfo imp return StringUtils.isNotEmpty(url); } - @ApiModelProperty(position = 17, value = "OTA Package description.", example = "Description for the OTA Package fw_1.0") + @Schema(description = "OTA Package description.", example = "Description for the OTA Package fw_1.0") @Override public JsonNode getAdditionalInfo() { return super.getAdditionalInfo(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/SaveDeviceWithCredentialsRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/SaveDeviceWithCredentialsRequest.java index f8c74a5155..7714be385b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/SaveDeviceWithCredentialsRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/SaveDeviceWithCredentialsRequest.java @@ -15,18 +15,17 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.security.DeviceCredentials; -@ApiModel +@Schema @Data public class SaveDeviceWithCredentialsRequest { - @ApiModelProperty(position = 1, value = "The JSON with device entity.", required = true) + @Schema(description = "The JSON with device entity.", required = true) private final Device device; - @ApiModelProperty(position = 2, value = "The JSON with credentials entity.", required = true) + @Schema(description = "The JSON with credentials entity.", required = true) private final DeviceCredentials credentials; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/SaveOtaPackageInfoRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/SaveOtaPackageInfoRequest.java index 8a54de65fa..4c85c44d94 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/SaveOtaPackageInfoRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/SaveOtaPackageInfoRequest.java @@ -15,18 +15,17 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; -@ApiModel +@Schema @Data @EqualsAndHashCode(callSuper = true) @NoArgsConstructor public class SaveOtaPackageInfoRequest extends OtaPackageInfo { - @ApiModelProperty(position = 16, value = "Indicates OTA Package uses url. Should be 'true' if uses url or 'false' if will be used data.", example = "true", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Indicates OTA Package uses url. Should be 'true' if uses url or 'false' if will be used data.", example = "true", accessMode = Schema.AccessMode.READ_ONLY) boolean usesUrl; public SaveOtaPackageInfoRequest(OtaPackageInfo otaPackageInfo, boolean usesUrl) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ShortCustomerInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/ShortCustomerInfo.java index 237a4d9a22..180180f569 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ShortCustomerInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ShortCustomerInfo.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @@ -27,20 +26,20 @@ import org.thingsboard.server.common.data.validation.NoXss; * Created by igor on 2/27/18. */ -@ApiModel +@Schema @AllArgsConstructor public class ShortCustomerInfo { - @ApiModelProperty(position = 1, value = "JSON object with the customer Id.") + @Schema(description = "JSON object with the customer Id.") @Getter @Setter private CustomerId customerId; - @ApiModelProperty(position = 2, value = "Title of the customer.") + @Schema(description = "Title of the customer.") @Getter @Setter @NoXss private String title; - @ApiModelProperty(position = 3, value = "Indicates special 'Public' customer used to embed dashboards on public websites.") + @Schema(description = "Indicates special 'Public' customer used to embed dashboards on public websites.") @Getter @Setter private boolean isPublic; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfo.java index ea46c91239..93ff39ef7a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfo.java @@ -15,15 +15,15 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; @Data public class SystemInfo { - @ApiModelProperty(position = 1, value = "Is monolith.") + @Schema(description = "Is monolith.") private boolean isMonolith; - @ApiModelProperty(position = 2, value = "System data.") + @Schema(description = "System data.") private List systemData; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfoData.java b/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfoData.java index 5ae53565cf..1db6a5002a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfoData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/SystemInfoData.java @@ -15,26 +15,26 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data public class SystemInfoData { - @ApiModelProperty(position = 1, value = "Service Id.") + @Schema(description = "Service Id.") private String serviceId; - @ApiModelProperty(position = 2, value = "Service type.") + @Schema(description = "Service type.") private String serviceType; - @ApiModelProperty(position = 3, value = "CPU usage, in percent.") + @Schema(description = "CPU usage, in percent.") private Long cpuUsage; - @ApiModelProperty(position = 4, value = "Total CPU usage.") + @Schema(description = "Total CPU usage.") private Long cpuCount; - @ApiModelProperty(position = 5, value = "Memory usage, in percent.") + @Schema(description = "Memory usage, in percent.") private Long memoryUsage; - @ApiModelProperty(position = 6, value = "Total memory in bytes.") + @Schema(description = "Total memory in bytes.") private Long totalMemory; - @ApiModelProperty(position = 7, value = "Disk usage, in percent.") + @Schema(description = "Disk usage, in percent.") private Long discUsage; - @ApiModelProperty(position = 8, value = "Total disc space in bytes.") + @Schema(description = "Total disc space in bytes.") private Long totalDiscSpace; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TbResource.java b/common/data/src/main/java/org/thingsboard/server/common/data/TbResource.java index 91bb7ba383..c6aa878948 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TbResource.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/TbResource.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -32,10 +32,10 @@ public class TbResource extends TbResourceInfo { @NoXss @Length(fieldName = "file name") - @ApiModelProperty(position = 8, value = "Resource file name.", example = "19.xml", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Resource file name.", example = "19.xml", accessMode = Schema.AccessMode.READ_ONLY) private String fileName; - @ApiModelProperty(position = 9, value = "Resource data.", example = "77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLQpGSUxFIElORk9STUFUSU9OCgpPTUEgUGVybWFuZW50IERvY3VtZW50CiAgIEZpbGU6IE9NQS1TVVAtTHdNMk1fQmluYXJ5QXBwRGF0YUNvbnRhaW5lci1WMV8wXzEtMjAxOTAyMjEtQQogICBUeXBlOiB4bWwKClB1YmxpYyBSZWFjaGFibGUgSW5mb3JtYXRpb24KICAgUGF0aDogaHR0cDovL3d3dy5vcGVubW9iaWxlYWxsaWFuY2Uub3JnL3RlY2gvcHJvZmlsZXMKICAgTmFtZTogTHdNMk1fQmluYXJ5QXBwRGF0YUNvbnRhaW5lci12MV8wXzEueG1sCgpOT1JNQVRJVkUgSU5GT1JNQVRJT04KCiAgSW5mb3JtYXRpb24gYWJvdXQgdGhpcyBmaWxlIGNhbiBiZSBmb3VuZCBpbiB0aGUgbGF0ZXN0IHJldmlzaW9uIG9mCgogIE9NQS1UUy1MV00yTV9CaW5hcnlBcHBEYXRhQ29udGFpbmVyLVYxXzBfMQoKICBUaGlzIGlzIGF2YWlsYWJsZSBhdCBodHRwOi8vd3d3Lm9wZW5tb2JpbGVhbGxpYW5jZS5vcmcvCgogIFNlbmQgY29tbWVudHMgdG8gaHR0cHM6Ly9naXRodWIuY29tL09wZW5Nb2JpbGVBbGxpYW5jZS9PTUFfTHdNMk1fZm9yX0RldmVsb3BlcnMvaXNzdWVzCgpDSEFOR0UgSElTVE9SWQoKMTUwNjIwMTggU3RhdHVzIGNoYW5nZWQgdG8gQXBwcm92ZWQgYnkgRE0sIERvYyBSZWYgIyBPTUEtRE0mU0UtMjAxOC0wMDYxLUlOUF9MV00yTV9BUFBEQVRBX1YxXzBfRVJQX2Zvcl9maW5hbF9BcHByb3ZhbAoyMTAyMjAxOSBTdGF0dXMgY2hhbmdlZCB0byBBcHByb3ZlZCBieSBJUFNPLCBEb2MgUmVmICMgT01BLUlQU08tMjAxOS0wMDI1LUlOUF9Md00yTV9PYmplY3RfQXBwX0RhdGFfQ29udGFpbmVyXzFfMF8xX2Zvcl9GaW5hbF9BcHByb3ZhbAoKTEVHQUwgRElTQ0xBSU1FUgoKQ29weXJpZ2h0IDIwMTkgT3BlbiBNb2JpbGUgQWxsaWFuY2UuCgpSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQKbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zCmFyZSBtZXQ6CgoxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodApub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCjIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0Cm5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUKZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KMy4gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgY29weXJpZ2h0IGhvbGRlciBub3IgdGhlIG5hbWVzIG9mIGl0cwpjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQKZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgoKVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUwoiQVMgSVMiIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVApMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUwpGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRQpDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULApJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLApCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7CkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIKQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUCkxJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOCkFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRQpQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KClRoZSBhYm92ZSBsaWNlbnNlIGlzIHVzZWQgYXMgYSBsaWNlbnNlIHVuZGVyIGNvcHlyaWdodCBvbmx5LiBQbGVhc2UKcmVmZXJlbmNlIHRoZSBPTUEgSVBSIFBvbGljeSBmb3IgcGF0ZW50IGxpY2Vuc2luZyB0ZXJtczoKaHR0cHM6Ly93d3cub21hc3BlY3dvcmtzLm9yZy9hYm91dC9pbnRlbGxlY3R1YWwtcHJvcGVydHktcmlnaHRzLwoKLS0+CjxMV00yTSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6bm9OYW1lc3BhY2VTY2hlbWFMb2NhdGlvbj0iaHR0cDovL29wZW5tb2JpbGVhbGxpYW5jZS5vcmcvdGVjaC9wcm9maWxlcy9MV00yTS54c2QiPgoJPE9iamVjdCBPYmplY3RUeXBlPSJNT0RlZmluaXRpb24iPgoJCTxOYW1lPkJpbmFyeUFwcERhdGFDb250YWluZXI8L05hbWU+CgkJPERlc2NyaXB0aW9uMT48IVtDREFUQVtUaGlzIEx3TTJNIE9iamVjdHMgcHJvdmlkZXMgdGhlIGFwcGxpY2F0aW9uIHNlcnZpY2UgZGF0YSByZWxhdGVkIHRvIGEgTHdNMk0gU2VydmVyLCBlZy4gV2F0ZXIgbWV0ZXIgZGF0YS4gClRoZXJlIGFyZSBzZXZlcmFsIG1ldGhvZHMgdG8gY3JlYXRlIGluc3RhbmNlIHRvIGluZGljYXRlIHRoZSBtZXNzYWdlIGRpcmVjdGlvbiBiYXNlZCBvbiB0aGUgbmVnb3RpYXRpb24gYmV0d2VlbiBBcHBsaWNhdGlvbiBhbmQgTHdNMk0uIFRoZSBDbGllbnQgYW5kIFNlcnZlciBzaG91bGQgbmVnb3RpYXRlIHRoZSBpbnN0YW5jZShzKSB1c2VkIHRvIGV4Y2hhbmdlIHRoZSBkYXRhLiBGb3IgZXhhbXBsZToKIC0gVXNpbmcgYSBzaW5nbGUgaW5zdGFuY2UgZm9yIGJvdGggZGlyZWN0aW9ucyBjb21tdW5pY2F0aW9uLCBmcm9tIENsaWVudCB0byBTZXJ2ZXIgYW5kIGZyb20gU2VydmVyIHRvIENsaWVudC4KIC0gVXNpbmcgYW4gaW5zdGFuY2UgZm9yIGNvbW11bmljYXRpb24gZnJvbSBDbGllbnQgdG8gU2VydmVyIGFuZCBhbm90aGVyIG9uZSBmb3IgY29tbXVuaWNhdGlvbiBmcm9tIFNlcnZlciB0byBDbGllbnQKIC0gVXNpbmcgc2V2ZXJhbCBpbnN0YW5jZXMKXV0+PC9EZXNjcmlwdGlvbjE+CgkJPE9iamVjdElEPjE5PC9PYmplY3RJRD4KCQk8T2JqZWN0VVJOPnVybjpvbWE6bHdtMm06b21hOjE5PC9PYmplY3RVUk4+CgkJPExXTTJNVmVyc2lvbj4xLjA8L0xXTTJNVmVyc2lvbj4KCQk8T2JqZWN0VmVyc2lvbj4xLjA8L09iamVjdFZlcnNpb24+CgkJPE11bHRpcGxlSW5zdGFuY2VzPk11bHRpcGxlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQk8TWFuZGF0b3J5Pk9wdGlvbmFsPC9NYW5kYXRvcnk+CgkJPFJlc291cmNlcz4KCQkJPEl0ZW0gSUQ9IjAiPjxOYW1lPkRhdGE8L05hbWU+CgkJCQk8T3BlcmF0aW9ucz5SVzwvT3BlcmF0aW9ucz4KCQkJCTxNdWx0aXBsZUluc3RhbmNlcz5NdWx0aXBsZTwvTXVsdGlwbGVJbnN0YW5jZXM+CgkJCQk8TWFuZGF0b3J5Pk1hbmRhdG9yeTwvTWFuZGF0b3J5PgoJCQkJPFR5cGU+T3BhcXVlPC9UeXBlPgoJCQkJPFJhbmdlRW51bWVyYXRpb24gLz4KCQkJCTxVbml0cyAvPgoJCQkJPERlc2NyaXB0aW9uPjwhW0NEQVRBW0luZGljYXRlcyB0aGUgYXBwbGljYXRpb24gZGF0YSBjb250ZW50Ll1dPjwvRGVzY3JpcHRpb24+CgkJCTwvSXRlbT4KCQkJPEl0ZW0gSUQ9IjEiPjxOYW1lPkRhdGEgUHJpb3JpdHk8L05hbWU+CgkJCQk8T3BlcmF0aW9ucz5SVzwvT3BlcmF0aW9ucz4KCQkJCTxNdWx0aXBsZUluc3RhbmNlcz5TaW5nbGU8L011bHRpcGxlSW5zdGFuY2VzPgoJCQkJPE1hbmRhdG9yeT5PcHRpb25hbDwvTWFuZGF0b3J5PgoJCQkJPFR5cGU+SW50ZWdlcjwvVHlwZT4KCQkJCTxSYW5nZUVudW1lcmF0aW9uPjEgYnl0ZXM8L1JhbmdlRW51bWVyYXRpb24+CgkJCQk8VW5pdHMgLz4KCQkJCTxEZXNjcmlwdGlvbj48IVtDREFUQVtJbmRpY2F0ZXMgdGhlIEFwcGxpY2F0aW9uIGRhdGEgcHJpb3JpdHk6CjA6SW1tZWRpYXRlCjE6QmVzdEVmZm9ydAoyOkxhdGVzdAozLTEwMDogUmVzZXJ2ZWQgZm9yIGZ1dHVyZSB1c2UuCjEwMS0yNTQ6IFByb3ByaWV0YXJ5IG1vZGUuXV0+PC9EZXNjcmlwdGlvbj4KCQkJPC9JdGVtPgoJCQk8SXRlbSBJRD0iMiI+PE5hbWU+RGF0YSBDcmVhdGlvbiBUaW1lPC9OYW1lPgoJCQkJPE9wZXJhdGlvbnM+Ulc8L09wZXJhdGlvbnM+CgkJCQk8TXVsdGlwbGVJbnN0YW5jZXM+U2luZ2xlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQkJCTxNYW5kYXRvcnk+T3B0aW9uYWw8L01hbmRhdG9yeT4KCQkJCTxUeXBlPlRpbWU8L1R5cGU+CgkJCQk8UmFuZ2VFbnVtZXJhdGlvbiAvPgoJCQkJPFVuaXRzIC8+CgkJCQk8RGVzY3JpcHRpb24+PCFbQ0RBVEFbSW5kaWNhdGVzIHRoZSBEYXRhIGluc3RhbmNlIGNyZWF0aW9uIHRpbWVzdGFtcC5dXT48L0Rlc2NyaXB0aW9uPgoJCQk8L0l0ZW0+CgkJCTxJdGVtIElEPSIzIj48TmFtZT5EYXRhIERlc2NyaXB0aW9uPC9OYW1lPgoJCQkJPE9wZXJhdGlvbnM+Ulc8L09wZXJhdGlvbnM+CgkJCQk8TXVsdGlwbGVJbnN0YW5jZXM+U2luZ2xlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQkJCTxNYW5kYXRvcnk+T3B0aW9uYWw8L01hbmRhdG9yeT4KCQkJCTxUeXBlPlN0cmluZzwvVHlwZT4KCQkJCTxSYW5nZUVudW1lcmF0aW9uPjMyIGJ5dGVzPC9SYW5nZUVudW1lcmF0aW9uPgoJCQkJPFVuaXRzIC8+CgkJCQk8RGVzY3JpcHRpb24+PCFbQ0RBVEFbSW5kaWNhdGVzIHRoZSBkYXRhIGRlc2NyaXB0aW9uLgplLmcuICJtZXRlciByZWFkaW5nIi5dXT48L0Rlc2NyaXB0aW9uPgoJCQk8L0l0ZW0+CgkJCTxJdGVtIElEPSI0Ij48TmFtZT5EYXRhIEZvcm1hdDwvTmFtZT4KCQkJCTxPcGVyYXRpb25zPlJXPC9PcGVyYXRpb25zPgoJCQkJPE11bHRpcGxlSW5zdGFuY2VzPlNpbmdsZTwvTXVsdGlwbGVJbnN0YW5jZXM+CgkJCQk8TWFuZGF0b3J5Pk9wdGlvbmFsPC9NYW5kYXRvcnk+CgkJCQk8VHlwZT5TdHJpbmc8L1R5cGU+CgkJCQk8UmFuZ2VFbnVtZXJhdGlvbj4zMiBieXRlczwvUmFuZ2VFbnVtZXJhdGlvbj4KCQkJCTxVbml0cyAvPgoJCQkJPERlc2NyaXB0aW9uPjwhW0NEQVRBW0luZGljYXRlcyB0aGUgZm9ybWF0IG9mIHRoZSBBcHBsaWNhdGlvbiBEYXRhLgplLmcuIFlHLU1ldGVyLVdhdGVyLVJlYWRpbmcKVVRGOC1zdHJpbmcKXV0+PC9EZXNjcmlwdGlvbj4KCQkJPC9JdGVtPgoJCQk8SXRlbSBJRD0iNSI+PE5hbWU+QXBwIElEPC9OYW1lPgoJCQkJPE9wZXJhdGlvbnM+Ulc8L09wZXJhdGlvbnM+CgkJCQk8TXVsdGlwbGVJbnN0YW5jZXM+U2luZ2xlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQkJCTxNYW5kYXRvcnk+T3B0aW9uYWw8L01hbmRhdG9yeT4KCQkJCTxUeXBlPkludGVnZXI8L1R5cGU+CgkJCQk8UmFuZ2VFbnVtZXJhdGlvbj4yIGJ5dGVzPC9SYW5nZUVudW1lcmF0aW9uPgoJCQkJPFVuaXRzIC8+CgkJCQk8RGVzY3JpcHRpb24+PCFbQ0RBVEFbSW5kaWNhdGVzIHRoZSBkZXN0aW5hdGlvbiBBcHBsaWNhdGlvbiBJRC5dXT48L0Rlc2NyaXB0aW9uPgoJCQk8L0l0ZW0+PC9SZXNvdXJjZXM+CgkJPERlc2NyaXB0aW9uMj48IVtDREFUQVtdXT48L0Rlc2NyaXB0aW9uMj4KCTwvT2JqZWN0Pgo8L0xXTTJNPgo=", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Resource data.", example = "77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLQpGSUxFIElORk9STUFUSU9OCgpPTUEgUGVybWFuZW50IERvY3VtZW50CiAgIEZpbGU6IE9NQS1TVVAtTHdNMk1fQmluYXJ5QXBwRGF0YUNvbnRhaW5lci1WMV8wXzEtMjAxOTAyMjEtQQogICBUeXBlOiB4bWwKClB1YmxpYyBSZWFjaGFibGUgSW5mb3JtYXRpb24KICAgUGF0aDogaHR0cDovL3d3dy5vcGVubW9iaWxlYWxsaWFuY2Uub3JnL3RlY2gvcHJvZmlsZXMKICAgTmFtZTogTHdNMk1fQmluYXJ5QXBwRGF0YUNvbnRhaW5lci12MV8wXzEueG1sCgpOT1JNQVRJVkUgSU5GT1JNQVRJT04KCiAgSW5mb3JtYXRpb24gYWJvdXQgdGhpcyBmaWxlIGNhbiBiZSBmb3VuZCBpbiB0aGUgbGF0ZXN0IHJldmlzaW9uIG9mCgogIE9NQS1UUy1MV00yTV9CaW5hcnlBcHBEYXRhQ29udGFpbmVyLVYxXzBfMQoKICBUaGlzIGlzIGF2YWlsYWJsZSBhdCBodHRwOi8vd3d3Lm9wZW5tb2JpbGVhbGxpYW5jZS5vcmcvCgogIFNlbmQgY29tbWVudHMgdG8gaHR0cHM6Ly9naXRodWIuY29tL09wZW5Nb2JpbGVBbGxpYW5jZS9PTUFfTHdNMk1fZm9yX0RldmVsb3BlcnMvaXNzdWVzCgpDSEFOR0UgSElTVE9SWQoKMTUwNjIwMTggU3RhdHVzIGNoYW5nZWQgdG8gQXBwcm92ZWQgYnkgRE0sIERvYyBSZWYgIyBPTUEtRE0mU0UtMjAxOC0wMDYxLUlOUF9MV00yTV9BUFBEQVRBX1YxXzBfRVJQX2Zvcl9maW5hbF9BcHByb3ZhbAoyMTAyMjAxOSBTdGF0dXMgY2hhbmdlZCB0byBBcHByb3ZlZCBieSBJUFNPLCBEb2MgUmVmICMgT01BLUlQU08tMjAxOS0wMDI1LUlOUF9Md00yTV9PYmplY3RfQXBwX0RhdGFfQ29udGFpbmVyXzFfMF8xX2Zvcl9GaW5hbF9BcHByb3ZhbAoKTEVHQUwgRElTQ0xBSU1FUgoKQ29weXJpZ2h0IDIwMTkgT3BlbiBNb2JpbGUgQWxsaWFuY2UuCgpSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQKbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zCmFyZSBtZXQ6CgoxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodApub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuCjIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0Cm5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUKZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KMy4gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgY29weXJpZ2h0IGhvbGRlciBub3IgdGhlIG5hbWVzIG9mIGl0cwpjb250cmlidXRvcnMgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQKZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLgoKVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUwoiQVMgSVMiIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVApMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUwpGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRQpDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULApJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLApCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7CkxPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIKQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUCkxJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOCkFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRQpQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KClRoZSBhYm92ZSBsaWNlbnNlIGlzIHVzZWQgYXMgYSBsaWNlbnNlIHVuZGVyIGNvcHlyaWdodCBvbmx5LiBQbGVhc2UKcmVmZXJlbmNlIHRoZSBPTUEgSVBSIFBvbGljeSBmb3IgcGF0ZW50IGxpY2Vuc2luZyB0ZXJtczoKaHR0cHM6Ly93d3cub21hc3BlY3dvcmtzLm9yZy9hYm91dC9pbnRlbGxlY3R1YWwtcHJvcGVydHktcmlnaHRzLwoKLS0+CjxMV00yTSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6bm9OYW1lc3BhY2VTY2hlbWFMb2NhdGlvbj0iaHR0cDovL29wZW5tb2JpbGVhbGxpYW5jZS5vcmcvdGVjaC9wcm9maWxlcy9MV00yTS54c2QiPgoJPE9iamVjdCBPYmplY3RUeXBlPSJNT0RlZmluaXRpb24iPgoJCTxOYW1lPkJpbmFyeUFwcERhdGFDb250YWluZXI8L05hbWU+CgkJPERlc2NyaXB0aW9uMT48IVtDREFUQVtUaGlzIEx3TTJNIE9iamVjdHMgcHJvdmlkZXMgdGhlIGFwcGxpY2F0aW9uIHNlcnZpY2UgZGF0YSByZWxhdGVkIHRvIGEgTHdNMk0gU2VydmVyLCBlZy4gV2F0ZXIgbWV0ZXIgZGF0YS4gClRoZXJlIGFyZSBzZXZlcmFsIG1ldGhvZHMgdG8gY3JlYXRlIGluc3RhbmNlIHRvIGluZGljYXRlIHRoZSBtZXNzYWdlIGRpcmVjdGlvbiBiYXNlZCBvbiB0aGUgbmVnb3RpYXRpb24gYmV0d2VlbiBBcHBsaWNhdGlvbiBhbmQgTHdNMk0uIFRoZSBDbGllbnQgYW5kIFNlcnZlciBzaG91bGQgbmVnb3RpYXRlIHRoZSBpbnN0YW5jZShzKSB1c2VkIHRvIGV4Y2hhbmdlIHRoZSBkYXRhLiBGb3IgZXhhbXBsZToKIC0gVXNpbmcgYSBzaW5nbGUgaW5zdGFuY2UgZm9yIGJvdGggZGlyZWN0aW9ucyBjb21tdW5pY2F0aW9uLCBmcm9tIENsaWVudCB0byBTZXJ2ZXIgYW5kIGZyb20gU2VydmVyIHRvIENsaWVudC4KIC0gVXNpbmcgYW4gaW5zdGFuY2UgZm9yIGNvbW11bmljYXRpb24gZnJvbSBDbGllbnQgdG8gU2VydmVyIGFuZCBhbm90aGVyIG9uZSBmb3IgY29tbXVuaWNhdGlvbiBmcm9tIFNlcnZlciB0byBDbGllbnQKIC0gVXNpbmcgc2V2ZXJhbCBpbnN0YW5jZXMKXV0+PC9EZXNjcmlwdGlvbjE+CgkJPE9iamVjdElEPjE5PC9PYmplY3RJRD4KCQk8T2JqZWN0VVJOPnVybjpvbWE6bHdtMm06b21hOjE5PC9PYmplY3RVUk4+CgkJPExXTTJNVmVyc2lvbj4xLjA8L0xXTTJNVmVyc2lvbj4KCQk8T2JqZWN0VmVyc2lvbj4xLjA8L09iamVjdFZlcnNpb24+CgkJPE11bHRpcGxlSW5zdGFuY2VzPk11bHRpcGxlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQk8TWFuZGF0b3J5Pk9wdGlvbmFsPC9NYW5kYXRvcnk+CgkJPFJlc291cmNlcz4KCQkJPEl0ZW0gSUQ9IjAiPjxOYW1lPkRhdGE8L05hbWU+CgkJCQk8T3BlcmF0aW9ucz5SVzwvT3BlcmF0aW9ucz4KCQkJCTxNdWx0aXBsZUluc3RhbmNlcz5NdWx0aXBsZTwvTXVsdGlwbGVJbnN0YW5jZXM+CgkJCQk8TWFuZGF0b3J5Pk1hbmRhdG9yeTwvTWFuZGF0b3J5PgoJCQkJPFR5cGU+T3BhcXVlPC9UeXBlPgoJCQkJPFJhbmdlRW51bWVyYXRpb24gLz4KCQkJCTxVbml0cyAvPgoJCQkJPERlc2NyaXB0aW9uPjwhW0NEQVRBW0luZGljYXRlcyB0aGUgYXBwbGljYXRpb24gZGF0YSBjb250ZW50Ll1dPjwvRGVzY3JpcHRpb24+CgkJCTwvSXRlbT4KCQkJPEl0ZW0gSUQ9IjEiPjxOYW1lPkRhdGEgUHJpb3JpdHk8L05hbWU+CgkJCQk8T3BlcmF0aW9ucz5SVzwvT3BlcmF0aW9ucz4KCQkJCTxNdWx0aXBsZUluc3RhbmNlcz5TaW5nbGU8L011bHRpcGxlSW5zdGFuY2VzPgoJCQkJPE1hbmRhdG9yeT5PcHRpb25hbDwvTWFuZGF0b3J5PgoJCQkJPFR5cGU+SW50ZWdlcjwvVHlwZT4KCQkJCTxSYW5nZUVudW1lcmF0aW9uPjEgYnl0ZXM8L1JhbmdlRW51bWVyYXRpb24+CgkJCQk8VW5pdHMgLz4KCQkJCTxEZXNjcmlwdGlvbj48IVtDREFUQVtJbmRpY2F0ZXMgdGhlIEFwcGxpY2F0aW9uIGRhdGEgcHJpb3JpdHk6CjA6SW1tZWRpYXRlCjE6QmVzdEVmZm9ydAoyOkxhdGVzdAozLTEwMDogUmVzZXJ2ZWQgZm9yIGZ1dHVyZSB1c2UuCjEwMS0yNTQ6IFByb3ByaWV0YXJ5IG1vZGUuXV0+PC9EZXNjcmlwdGlvbj4KCQkJPC9JdGVtPgoJCQk8SXRlbSBJRD0iMiI+PE5hbWU+RGF0YSBDcmVhdGlvbiBUaW1lPC9OYW1lPgoJCQkJPE9wZXJhdGlvbnM+Ulc8L09wZXJhdGlvbnM+CgkJCQk8TXVsdGlwbGVJbnN0YW5jZXM+U2luZ2xlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQkJCTxNYW5kYXRvcnk+T3B0aW9uYWw8L01hbmRhdG9yeT4KCQkJCTxUeXBlPlRpbWU8L1R5cGU+CgkJCQk8UmFuZ2VFbnVtZXJhdGlvbiAvPgoJCQkJPFVuaXRzIC8+CgkJCQk8RGVzY3JpcHRpb24+PCFbQ0RBVEFbSW5kaWNhdGVzIHRoZSBEYXRhIGluc3RhbmNlIGNyZWF0aW9uIHRpbWVzdGFtcC5dXT48L0Rlc2NyaXB0aW9uPgoJCQk8L0l0ZW0+CgkJCTxJdGVtIElEPSIzIj48TmFtZT5EYXRhIERlc2NyaXB0aW9uPC9OYW1lPgoJCQkJPE9wZXJhdGlvbnM+Ulc8L09wZXJhdGlvbnM+CgkJCQk8TXVsdGlwbGVJbnN0YW5jZXM+U2luZ2xlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQkJCTxNYW5kYXRvcnk+T3B0aW9uYWw8L01hbmRhdG9yeT4KCQkJCTxUeXBlPlN0cmluZzwvVHlwZT4KCQkJCTxSYW5nZUVudW1lcmF0aW9uPjMyIGJ5dGVzPC9SYW5nZUVudW1lcmF0aW9uPgoJCQkJPFVuaXRzIC8+CgkJCQk8RGVzY3JpcHRpb24+PCFbQ0RBVEFbSW5kaWNhdGVzIHRoZSBkYXRhIGRlc2NyaXB0aW9uLgplLmcuICJtZXRlciByZWFkaW5nIi5dXT48L0Rlc2NyaXB0aW9uPgoJCQk8L0l0ZW0+CgkJCTxJdGVtIElEPSI0Ij48TmFtZT5EYXRhIEZvcm1hdDwvTmFtZT4KCQkJCTxPcGVyYXRpb25zPlJXPC9PcGVyYXRpb25zPgoJCQkJPE11bHRpcGxlSW5zdGFuY2VzPlNpbmdsZTwvTXVsdGlwbGVJbnN0YW5jZXM+CgkJCQk8TWFuZGF0b3J5Pk9wdGlvbmFsPC9NYW5kYXRvcnk+CgkJCQk8VHlwZT5TdHJpbmc8L1R5cGU+CgkJCQk8UmFuZ2VFbnVtZXJhdGlvbj4zMiBieXRlczwvUmFuZ2VFbnVtZXJhdGlvbj4KCQkJCTxVbml0cyAvPgoJCQkJPERlc2NyaXB0aW9uPjwhW0NEQVRBW0luZGljYXRlcyB0aGUgZm9ybWF0IG9mIHRoZSBBcHBsaWNhdGlvbiBEYXRhLgplLmcuIFlHLU1ldGVyLVdhdGVyLVJlYWRpbmcKVVRGOC1zdHJpbmcKXV0+PC9EZXNjcmlwdGlvbj4KCQkJPC9JdGVtPgoJCQk8SXRlbSBJRD0iNSI+PE5hbWU+QXBwIElEPC9OYW1lPgoJCQkJPE9wZXJhdGlvbnM+Ulc8L09wZXJhdGlvbnM+CgkJCQk8TXVsdGlwbGVJbnN0YW5jZXM+U2luZ2xlPC9NdWx0aXBsZUluc3RhbmNlcz4KCQkJCTxNYW5kYXRvcnk+T3B0aW9uYWw8L01hbmRhdG9yeT4KCQkJCTxUeXBlPkludGVnZXI8L1R5cGU+CgkJCQk8UmFuZ2VFbnVtZXJhdGlvbj4yIGJ5dGVzPC9SYW5nZUVudW1lcmF0aW9uPgoJCQkJPFVuaXRzIC8+CgkJCQk8RGVzY3JpcHRpb24+PCFbQ0RBVEFbSW5kaWNhdGVzIHRoZSBkZXN0aW5hdGlvbiBBcHBsaWNhdGlvbiBJRC5dXT48L0Rlc2NyaXB0aW9uPgoJCQk8L0l0ZW0+PC9SZXNvdXJjZXM+CgkJPERlc2NyaXB0aW9uMj48IVtDREFUQVtdXT48L0Rlc2NyaXB0aW9uMj4KCTwvT2JqZWN0Pgo8L0xXTTJNPgo=", accessMode = Schema.AccessMode.READ_ONLY) private String data; public TbResource() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java index 331958ac58..f3e8f1bf8f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/TbResourceInfo.java @@ -16,8 +16,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonIgnore; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -26,7 +25,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @Slf4j @Data @EqualsAndHashCode(callSuper = true) @@ -34,19 +33,19 @@ public class TbResourceInfo extends BaseData implements HasName, H private static final long serialVersionUID = 7282664529021651736L; - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id. Tenant Id of the resource can't be changed.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id. Tenant Id of the resource can't be changed.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; @NoXss @Length(fieldName = "title") - @ApiModelProperty(position = 4, value = "Resource title.", example = "BinaryAppDataContainer id=19 v1.0") + @Schema(description = "Resource title.", example = "BinaryAppDataContainer id=19 v1.0") private String title; - @ApiModelProperty(position = 5, value = "Resource type.", example = "LWM2M_MODEL", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Resource type.", example = "LWM2M_MODEL", accessMode = Schema.AccessMode.READ_ONLY) private ResourceType resourceType; @NoXss @Length(fieldName = "resourceKey") - @ApiModelProperty(position = 6, value = "Resource key.", example = "19_1.0", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Resource key.", example = "19_1.0", accessMode = Schema.AccessMode.READ_ONLY) private String resourceKey; - @ApiModelProperty(position = 7, value = "Resource search text.", example = "19_1.0:binaryappdatacontainer", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Resource search text.", example = "19_1.0:binaryappdatacontainer", accessMode = Schema.AccessMode.READ_ONLY) private String searchText; public TbResourceInfo() { @@ -66,7 +65,7 @@ public class TbResourceInfo extends BaseData implements HasName, H this.searchText = resourceInfo.getSearchText(); } - @ApiModelProperty(position = 1, value = "JSON object with the Resource Id. " + + @Schema(description = "JSON object with the Resource Id. " + "Specify this field to update the Resource. " + "Referencing non-existing Resource Id will cause error. " + "Omit this field to create new Resource." ) @@ -75,7 +74,7 @@ public class TbResourceInfo extends BaseData implements HasName, H return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the resource creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the resource creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java b/common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java index 89cd9ec467..d01cc3aa41 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java @@ -18,15 +18,14 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @EqualsAndHashCode(callSuper = true) public class Tenant extends ContactBased implements HasTenantId, HasTitle { @@ -34,14 +33,14 @@ public class Tenant extends ContactBased implements HasTenantId, HasTi @Length(fieldName = "title") @NoXss - @ApiModelProperty(position = 3, value = "Title of the tenant", example = "Company A") + @Schema(description = "Title of the tenant", example = "Company A") private String title; @NoXss @Length(fieldName = "region") - @ApiModelProperty(position = 5, value = "Geo region of the tenant", example = "North America") + @Schema(description = "Geo region of the tenant", example = "North America") private String region; - @ApiModelProperty(position = 6, required = true, value = "JSON object with Tenant Profile Id") + @Schema(required = true, description = "JSON object with Tenant Profile Id") private TenantProfileId tenantProfileId; public Tenant() { @@ -74,7 +73,7 @@ public class Tenant extends ContactBased implements HasTenantId, HasTi } @Override - @ApiModelProperty(position = 4, value = "Name of the tenant. Read-only, duplicated from title for backward compatibility", example = "Company A", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Name of the tenant. Read-only, duplicated from title for backward compatibility", example = "Company A", accessMode = Schema.AccessMode.READ_ONLY) @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { return title; @@ -96,7 +95,7 @@ public class Tenant extends ContactBased implements HasTenantId, HasTi this.tenantProfileId = tenantProfileId; } - @ApiModelProperty(position = 1, value = "JSON object with the tenant Id. " + + @Schema(description = "JSON object with the tenant Id. " + "Specify this field to update the tenant. " + "Referencing non-existing tenant Id will cause error. " + "Omit this field to create new tenant." ) @@ -105,61 +104,61 @@ public class Tenant extends ContactBased implements HasTenantId, HasTi return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the tenant creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the tenant creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 7, required = true, value = "Country", example = "US") + @Schema(required = true, description = "Country", example = "US") @Override public String getCountry() { return super.getCountry(); } - @ApiModelProperty(position = 8, required = true, value = "State", example = "NY") + @Schema(required = true, description = "State", example = "NY") @Override public String getState() { return super.getState(); } - @ApiModelProperty(position = 9, required = true, value = "City", example = "New York") + @Schema(required = true, description = "City", example = "New York") @Override public String getCity() { return super.getCity(); } - @ApiModelProperty(position = 10, required = true, value = "Address Line 1", example = "42 Broadway Suite 12-400") + @Schema(required = true, description = "Address Line 1", example = "42 Broadway Suite 12-400") @Override public String getAddress() { return super.getAddress(); } - @ApiModelProperty(position = 11, required = true, value = "Address Line 2", example = "") + @Schema(required = true, description = "Address Line 2", example = "") @Override public String getAddress2() { return super.getAddress2(); } - @ApiModelProperty(position = 12, required = true, value = "Zip code", example = "10004") + @Schema(required = true, description = "Zip code", example = "10004") @Override public String getZip() { return super.getZip(); } - @ApiModelProperty(position = 13, required = true, value = "Phone number", example = "+1(415)777-7777") + @Schema(required = true, description = "Phone number", example = "+1(415)777-7777") @Override public String getPhone() { return super.getPhone(); } - @ApiModelProperty(position = 14, required = true, value = "Email", example = "example@company.com") + @Schema(required = true, description = "Email", example = "example@company.com") @Override public String getEmail() { return super.getEmail(); } - @ApiModelProperty(position = 15, value = "Additional parameters of the device", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "Additional parameters of the device",implementation = com.fasterxml.jackson.databind.JsonNode.class) @Override public JsonNode getAdditionalInfo() { return super.getAdditionalInfo(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java index e98e14d2d0..fd7ca7fc7f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/TenantInfo.java @@ -15,15 +15,14 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.TenantId; -@ApiModel +@Schema @Data public class TenantInfo extends Tenant { - @ApiModelProperty(position = 15, value = "Tenant Profile name", example = "Default") + @Schema(description = "Tenant Profile name", example = "Default") private String tenantProfileName; public TenantInfo() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TenantProfile.java b/common/data/src/main/java/org/thingsboard/server/common/data/TenantProfile.java index 5ce6c00fb8..d4b5f51e77 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TenantProfile.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/TenantProfile.java @@ -18,8 +18,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -34,7 +33,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Optional; -@ApiModel +@Schema @Data @ToString(exclude = {"profileDataBytes"}) @EqualsAndHashCode(callSuper = true) @@ -47,17 +46,17 @@ public class TenantProfile extends BaseData implements HasName @NoXss @Length(fieldName = "name") - @ApiModelProperty(position = 3, value = "Name of the tenant profile", example = "High Priority Tenants") + @Schema(description = "Name of the tenant profile", example = "High Priority Tenants") private String name; @NoXss - @ApiModelProperty(position = 4, value = "Description of the tenant profile", example = "Any text") + @Schema(description = "Description of the tenant profile", example = "Any text") private String description; - @ApiModelProperty(position = 5, value = "Default Tenant profile to be used.", example = "true") + @Schema(description = "Default Tenant profile to be used.", example = "true") private boolean isDefault; - @ApiModelProperty(position = 6, value = "If enabled, will push all messages related to this tenant and processed by the rule engine into separate queue. " + + @Schema(description = "If enabled, will push all messages related to this tenant and processed by the rule engine into separate queue. " + "Useful for complex microservices deployments, to isolate processing of the data for specific tenants", example = "true") private boolean isolatedTbRuleEngine; - @ApiModelProperty(position = 7, value = "Complex JSON object that contains profile settings: queue configs, max devices, max assets, rate limits, etc.") + @Schema(description = "Complex JSON object that contains profile settings: queue configs, max devices, max assets, rate limits, etc.") private transient TenantProfileData profileData; @JsonIgnore private byte[] profileDataBytes; @@ -79,7 +78,7 @@ public class TenantProfile extends BaseData implements HasName this.setProfileData(tenantProfile.getProfileData()); } - @ApiModelProperty(position = 1, value = "JSON object with the tenant profile Id. " + + @Schema(description = "JSON object with the tenant profile Id. " + "Specify this field to update the tenant profile. " + "Referencing non-existing tenant profile Id will cause error. " + "Omit this field to create new tenant profile.") @@ -88,7 +87,7 @@ public class TenantProfile extends BaseData implements HasName return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the tenant profile creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the tenant profile creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/UpdateMessage.java b/common/data/src/main/java/org/thingsboard/server/common/data/UpdateMessage.java index 43210de9d0..522ef80c53 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/UpdateMessage.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/UpdateMessage.java @@ -15,27 +15,26 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; -@ApiModel +@Schema @Data public class UpdateMessage implements Serializable { - @ApiModelProperty(position = 1, value = "'True' if new platform update is available.") + @Schema(description = "'True' if new platform update is available.") private final boolean updateAvailable; - @ApiModelProperty(position = 2, value = "Current ThingsBoard version.") + @Schema(description = "Current ThingsBoard version.") private final String currentVersion; - @ApiModelProperty(position = 3, value = "Latest ThingsBoard version.") + @Schema(description = "Latest ThingsBoard version.") private final String latestVersion; - @ApiModelProperty(position = 4, value = "Upgrade instructions URL.") + @Schema(description = "Upgrade instructions URL.") private final String upgradeInstructionsUrl; - @ApiModelProperty(position = 5, value = "Current ThingsBoard version release notes URL.") + @Schema(description = "Current ThingsBoard version release notes URL.") private final String currentVersionReleaseNotesUrl; - @ApiModelProperty(position = 6, value = "Latest ThingsBoard version release notes URL.") + @Schema(description = "Latest ThingsBoard version release notes URL.") private final String latestVersionReleaseNotesUrl; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/User.java b/common/data/src/main/java/org/thingsboard/server/common/data/User.java index b3d9268c6b..15bc41f22c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/User.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/User.java @@ -18,8 +18,7 @@ package org.thingsboard.server.common.data; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; @@ -32,7 +31,7 @@ import org.thingsboard.server.common.data.validation.NoXss; import static org.apache.commons.lang3.StringUtils.isNotEmpty; -@ApiModel +@Schema @EqualsAndHashCode(callSuper = true) public class User extends BaseDataWithAdditionalInfo implements HasName, HasTenantId, HasCustomerId, NotificationRecipient { @@ -71,7 +70,7 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, } - @ApiModelProperty(position = 1, value = "JSON object with the User Id. " + + @Schema(description = "JSON object with the User Id. " + "Specify this field to update the device. " + "Referencing non-existing User Id will cause error. " + "Omit this field to create new customer.") @@ -80,13 +79,13 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the user creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the user creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 3, value = "JSON object with the Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with the Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) public TenantId getTenantId() { return tenantId; } @@ -95,7 +94,7 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, this.tenantId = tenantId; } - @ApiModelProperty(position = 4, value = "JSON object with the Customer Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with the Customer Id.", accessMode = Schema.AccessMode.READ_ONLY) public CustomerId getCustomerId() { return customerId; } @@ -104,7 +103,7 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, this.customerId = customerId; } - @ApiModelProperty(position = 5, required = true, value = "Email of the user", example = "user@example.com") + @Schema(required = true, description = "Email of the user", example = "user@example.com") public String getEmail() { return email; } @@ -113,14 +112,14 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, this.email = email; } - @ApiModelProperty(position = 6, accessMode = ApiModelProperty.AccessMode.READ_ONLY, value = "Duplicates the email of the user, readonly", example = "user@example.com") + @Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "Duplicates the email of the user, readonly", example = "user@example.com") @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { return email; } - @ApiModelProperty(position = 7, required = true, value = "Authority", example = "SYS_ADMIN, TENANT_ADMIN or CUSTOMER_USER") + @Schema(required = true, description = "Authority", example = "SYS_ADMIN, TENANT_ADMIN or CUSTOMER_USER") public Authority getAuthority() { return authority; } @@ -129,7 +128,7 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, this.authority = authority; } - @ApiModelProperty(position = 8, required = true, value = "First name of the user", example = "John") + @Schema(required = true, description = "First name of the user", example = "John") public String getFirstName() { return firstName; } @@ -138,7 +137,7 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, this.firstName = firstName; } - @ApiModelProperty(position = 9, required = true, value = "Last name of the user", example = "Doe") + @Schema(required = true, description = "Last name of the user", example = "Doe") public String getLastName() { return lastName; } @@ -147,7 +146,7 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, this.lastName = lastName; } - @ApiModelProperty(position = 10, required = true, value = "Phone number of the user", example = "38012345123") + @Schema(required = true, description = "Phone number of the user", example = "38012345123") public String getPhone() { return phone; } @@ -156,7 +155,7 @@ public class User extends BaseDataWithAdditionalInfo implements HasName, this.phone = phone; } - @ApiModelProperty(position = 11, value = "Additional parameters of the user", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "Additional parameters of the user", implementation = com.fasterxml.jackson.databind.JsonNode.class) @Override public JsonNode getAdditionalInfo() { return super.getAdditionalInfo(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/UserEmailInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/UserEmailInfo.java index f1eb95c805..644144efa5 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/UserEmailInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/UserEmailInfo.java @@ -15,25 +15,24 @@ */ package org.thingsboard.server.common.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.UserId; -@ApiModel +@Schema @Data @AllArgsConstructor public class UserEmailInfo implements HasId { - @ApiModelProperty(position = 1, value = "User id") + @Schema(description = "User id") private UserId id; - @ApiModelProperty(position = 2, value = "User email", example = "john@gmail.com") + @Schema(description = "User email", example = "john@gmail.com") private String email; - @ApiModelProperty(position = 3, value = "User first name", example = "John") + @Schema(description = "User first name", example = "John") private String firstName; - @ApiModelProperty(position = 4, value = "User last name", example = "Brown") + @Schema(description = "User last name", example = "Brown") private String lastName; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java index 34fec2cd82..222570e914 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/Alarm.java @@ -18,8 +18,7 @@ package org.thingsboard.server.common.data.alarm; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -41,7 +40,7 @@ import java.util.List; /** * Created by ashvayka on 11.05.17. */ -@ApiModel +@Schema @Data @EqualsAndHashCode(callSuper = true) @Builder @@ -49,45 +48,45 @@ import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) public class Alarm extends BaseData implements HasName, HasTenantId, HasCustomerId { - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; - @ApiModelProperty(position = 4, value = "JSON object with Customer Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Customer Id", accessMode = Schema.AccessMode.READ_ONLY) private CustomerId customerId; @NoXss - @ApiModelProperty(position = 6, required = true, value = "representing type of the Alarm", example = "High Temperature Alarm") + @Schema(required = true, description = "representing type of the Alarm", example = "High Temperature Alarm") @Length(fieldName = "type") private String type; - @ApiModelProperty(position = 7, required = true, value = "JSON object with alarm originator id") + @Schema(required = true, description = "JSON object with alarm originator id") private EntityId originator; - @ApiModelProperty(position = 8, required = true, value = "Alarm severity", example = "CRITICAL") + @Schema(required = true, description = "Alarm severity", example = "CRITICAL") private AlarmSeverity severity; - @ApiModelProperty(position = 9, required = true, value = "Acknowledged", example = "true") + @Schema(required = true, description = "Acknowledged", example = "true") private boolean acknowledged; - @ApiModelProperty(position = 10, required = true, value = "Cleared", example = "false") + @Schema(required = true, description = "Cleared", example = "false") private boolean cleared; - @ApiModelProperty(position = 11, value = "Alarm assignee user id") + @Schema(description = "Alarm assignee user id") private UserId assigneeId; - @ApiModelProperty(position = 12, value = "Timestamp of the alarm start time, in milliseconds", example = "1634058704565") + @Schema(description = "Timestamp of the alarm start time, in milliseconds", example = "1634058704565") private long startTs; - @ApiModelProperty(position = 13, value = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522") + @Schema(description = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522") private long endTs; - @ApiModelProperty(position = 14, value = "Timestamp of the alarm acknowledgement, in milliseconds", example = "1634115221948") + @Schema(description = "Timestamp of the alarm acknowledgement, in milliseconds", example = "1634115221948") private long ackTs; - @ApiModelProperty(position = 15, value = "Timestamp of the alarm clearing, in milliseconds", example = "1634114528465") + @Schema(description = "Timestamp of the alarm clearing, in milliseconds", example = "1634114528465") private long clearTs; - @ApiModelProperty(position = 16, value = "Timestamp of the alarm assignment, in milliseconds", example = "1634115928465") + @Schema(description = "Timestamp of the alarm assignment, in milliseconds", example = "1634115928465") private long assignTs; - @ApiModelProperty(position = 17, value = "JSON object with alarm details") + @Schema(description = "JSON object with alarm details") private transient JsonNode details; - @ApiModelProperty(position = 18, value = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true") + @Schema(description = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true") private boolean propagate; - @ApiModelProperty(position = 19, value = "Propagation flag to specify if alarm should be propagated to the owner (tenant or customer) of alarm originator", example = "true") + @Schema(description = "Propagation flag to specify if alarm should be propagated to the owner (tenant or customer) of alarm originator", example = "true") private boolean propagateToOwner; - @ApiModelProperty(position = 20, value = "Propagation flag to specify if alarm should be propagated to the tenant entity", example = "true") + @Schema(description = "Propagation flag to specify if alarm should be propagated to the tenant entity", example = "true") private boolean propagateToTenant; - @ApiModelProperty(position = 21, value = "JSON array of relation types that should be used for propagation. " + + @Schema(description = "JSON array of relation types that should be used for propagation. " + "By default, 'propagateRelationTypes' array is empty which means that the alarm will be propagated based on any relation type to parent entities. " + "This parameter should be used only in case when 'propagate' parameter is set to true, otherwise, 'propagateRelationTypes' array will be ignored.") private List propagateRelationTypes; @@ -125,12 +124,12 @@ public class Alarm extends BaseData implements HasName, HasTenantId, Ha @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) - @ApiModelProperty(position = 5, required = true, value = "representing type of the Alarm", example = "High Temperature Alarm") + @Schema(required = true, description = "representing type of the Alarm", example = "High Temperature Alarm") public String getName() { return type; } - @ApiModelProperty(position = 1, value = "JSON object with the alarm Id. " + + @Schema(description = "JSON object with the alarm Id. " + "Specify this field to update the alarm. " + "Referencing non-existing alarm Id will cause error. " + "Omit this field to create new alarm.") @@ -140,14 +139,14 @@ public class Alarm extends BaseData implements HasName, HasTenantId, Ha } - @ApiModelProperty(position = 2, value = "Timestamp of the alarm creation, in milliseconds", example = "1634058704567", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the alarm creation, in milliseconds", example = "1634058704567", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } @JsonProperty(access = JsonProperty.Access.READ_ONLY) - @ApiModelProperty(position = 22, required = true, value = "status of the Alarm", example = "ACTIVE_UNACK", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "status of the Alarm", example = "ACTIVE_UNACK", accessMode = Schema.AccessMode.READ_ONLY) public AlarmStatus getStatus() { return toStatus(cleared, acknowledged); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java index 982e0f94d1..0ed046311f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -17,8 +17,7 @@ package org.thingsboard.server.common.data.alarm; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -30,23 +29,23 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @Data @Builder @AllArgsConstructor public class AlarmComment extends BaseData implements HasName { - @ApiModelProperty(position = 3, value = "JSON object with Alarm id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Alarm id.", accessMode = Schema.AccessMode.READ_ONLY) private EntityId alarmId; - @ApiModelProperty(position = 4, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with User id.", accessMode = Schema.AccessMode.READ_ONLY) private UserId userId; - @ApiModelProperty(position = 5, value = "Defines origination of comment. System type means comment was created by TB. OTHER type means comment was created by user.", example = "SYSTEM/OTHER", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Defines origination of comment. System type means comment was created by TB. OTHER type means comment was created by user.", example = "SYSTEM/OTHER", accessMode = Schema.AccessMode.READ_ONLY) private AlarmCommentType type; - @ApiModelProperty(position = 6, value = "JSON object with text of comment.", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "JSON object with text of comment.",implementation = com.fasterxml.jackson.databind.JsonNode.class) @NoXss @Length(fieldName = "comment", max = 10000) private transient JsonNode comment; - @ApiModelProperty(position = 1, value = "JSON object with the alarm comment Id. " + + @Schema(description = "JSON object with the alarm comment Id. " + "Specify this field to update the alarm comment. " + "Referencing non-existing alarm Id will cause error. " + "Omit this field to create new alarm." ) @@ -55,7 +54,7 @@ public class AlarmComment extends BaseData implements HasName { return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the alarm comment creation, in milliseconds", example = "1634058704567", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the alarm comment creation, in milliseconds", example = "1634058704567", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); @@ -71,7 +70,7 @@ public class AlarmComment extends BaseData implements HasName { @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) - @ApiModelProperty(position = 5, required = true, value = "representing comment text", example = "Please take a look") + @Schema(required = true, description = "representing comment text", example = "Please take a look") public String getName() { return comment.toString(); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java index e84cb78697..b68f771621 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCommentInfo.java @@ -15,24 +15,23 @@ */ package org.thingsboard.server.common.data.alarm; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -@ApiModel +@Schema @Data @EqualsAndHashCode(callSuper = true) public class AlarmCommentInfo extends AlarmComment { private static final long serialVersionUID = 2807343093519543377L; - @ApiModelProperty(position = 19, value = "User first name", example = "John") + @Schema(description = "User first name", example = "John") private String firstName; - @ApiModelProperty(position = 19, value = "User last name", example = "Brown") + @Schema(description = "User last name", example = "Brown") private String lastName; - @ApiModelProperty(position = 19, value = "User email address", example = "johnBrown@gmail.com") + @Schema(description = "User email address", example = "johnBrown@gmail.com") private String email; public AlarmCommentInfo() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java index 1c71e66b87..ea4649bcd6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java @@ -16,7 +16,7 @@ package org.thingsboard.server.common.data.alarm; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; import org.thingsboard.server.common.data.id.AlarmId; @@ -35,29 +35,29 @@ import jakarta.validation.constraints.NotNull; public class AlarmCreateOrUpdateActiveRequest implements AlarmModificationRequest { @NotNull - @ApiModelProperty(position = 1, value = "JSON object with Tenant Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; - @ApiModelProperty(position = 2, value = "JSON object with Customer Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Customer Id", accessMode = Schema.AccessMode.READ_ONLY) private CustomerId customerId; @NotNull - @ApiModelProperty(position = 3, required = true, value = "representing type of the Alarm", example = "High Temperature Alarm") + @Schema(required = true, description = "representing type of the Alarm", example = "High Temperature Alarm") @Length(fieldName = "type") private String type; @NotNull - @ApiModelProperty(position = 4, required = true, value = "JSON object with alarm originator id") + @Schema(required = true, description = "JSON object with alarm originator id") private EntityId originator; @NotNull - @ApiModelProperty(position = 5, required = true, value = "Alarm severity", example = "CRITICAL") + @Schema(required = true, description = "Alarm severity", example = "CRITICAL") private AlarmSeverity severity; - @ApiModelProperty(position = 6, value = "Timestamp of the alarm start time, in milliseconds", example = "1634058704565") + @Schema(description = "Timestamp of the alarm start time, in milliseconds", example = "1634058704565") private long startTs; - @ApiModelProperty(position = 7, value = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522") + @Schema(description = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522") private long endTs; @NoXss - @ApiModelProperty(position = 8, value = "JSON object with alarm details") + @Schema(description = "JSON object with alarm details") private JsonNode details; @Valid - @ApiModelProperty(position = 9, value = "JSON object with propagation details") + @Schema(description = "JSON object with propagation details") private AlarmPropagationInfo propagation; private UserId userId; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmInfo.java index 9086c4aa7b..61e53044ad 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmInfo.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.alarm; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -24,24 +23,24 @@ import lombok.ToString; @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -@ApiModel +@Schema public class AlarmInfo extends Alarm { private static final long serialVersionUID = 2807343093519543363L; @Getter @Setter - @ApiModelProperty(position = 19, value = "Alarm originator name", example = "Thermostat") + @Schema(description = "Alarm originator name", example = "Thermostat") private String originatorName; @Getter @Setter - @ApiModelProperty(position = 20, value = "Alarm originator label", example = "Thermostat label") + @Schema(description = "Alarm originator label", example = "Thermostat label") private String originatorLabel; @Getter @Setter - @ApiModelProperty(position = 21, value = "Alarm assignee") + @Schema(description = "Alarm assignee") private AlarmAssignee assignee; public AlarmInfo() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmPropagationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmPropagationInfo.java index 8ba744a85e..49ad2c4ded 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmPropagationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmPropagationInfo.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data.alarm; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; import org.thingsboard.server.common.data.validation.NoXss; @@ -29,14 +29,14 @@ public class AlarmPropagationInfo { public static AlarmPropagationInfo EMPTY = new AlarmPropagationInfo(false, false, false, Collections.emptyList()); - @ApiModelProperty(position = 1, value = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true") + @Schema(description = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true") private boolean propagate; - @ApiModelProperty(position = 2, value = "Propagation flag to specify if alarm should be propagated to the owner (tenant or customer) of alarm originator", example = "true") + @Schema(description = "Propagation flag to specify if alarm should be propagated to the owner (tenant or customer) of alarm originator", example = "true") private boolean propagateToOwner; - @ApiModelProperty(position = 3, value = "Propagation flag to specify if alarm should be propagated to the tenant entity", example = "true") + @Schema(description = "Propagation flag to specify if alarm should be propagated to the tenant entity", example = "true") private boolean propagateToTenant; @NoXss - @ApiModelProperty(position = 4, value = "JSON array of relation types that should be used for propagation. " + + @Schema(description = "JSON array of relation types that should be used for propagation. " + "By default, 'propagateRelationTypes' array is empty which means that the alarm will be propagated based on any relation type to parent entities. " + "This parameter should be used only in case when 'propagate' parameter is set to true, otherwise, 'propagateRelationTypes' array will be ignored.") private List propagateRelationTypes; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java index e97b40e1f1..06bacb50fc 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmUpdateRequest.java @@ -16,7 +16,7 @@ package org.thingsboard.server.common.data.alarm; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; import org.thingsboard.server.common.data.id.AlarmId; @@ -32,26 +32,26 @@ import jakarta.validation.constraints.NotNull; public class AlarmUpdateRequest implements AlarmModificationRequest { @NotNull - @ApiModelProperty(position = 1, value = "JSON object with Tenant Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; @NotNull - @ApiModelProperty(position = 2, value = "JSON object with the alarm Id. " + + @Schema(description = "JSON object with the alarm Id. " + "Specify this field to update the alarm. " + "Referencing non-existing alarm Id will cause error. " + "Omit this field to create new alarm.") private AlarmId alarmId; @NotNull - @ApiModelProperty(position = 3, required = true, value = "Alarm severity", example = "CRITICAL") + @Schema(required = true, description = "Alarm severity", example = "CRITICAL") private AlarmSeverity severity; - @ApiModelProperty(position = 4, value = "Timestamp of the alarm start time, in milliseconds", example = "1634058704565") + @Schema(description = "Timestamp of the alarm start time, in milliseconds", example = "1634058704565") private long startTs; - @ApiModelProperty(position = 5, value = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522") + @Schema(description = "Timestamp of the alarm end time(last time update), in milliseconds", example = "1634111163522") private long endTs; @NoXss - @ApiModelProperty(position = 6, value = "JSON object with alarm details") + @Schema(description = "JSON object with alarm details") private JsonNode details; @Valid - @ApiModelProperty(position = 7, value = "JSON object with propagation details") + @Schema(description = "JSON object with propagation details") private AlarmPropagationInfo propagation; private UserId userId; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/asset/Asset.java b/common/data/src/main/java/org/thingsboard/server/common/data/asset/Asset.java index bbb56305db..49bcc15875 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/asset/Asset.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/asset/Asset.java @@ -16,8 +16,7 @@ package org.thingsboard.server.common.data.asset; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -35,7 +34,7 @@ import org.thingsboard.server.common.data.validation.NoXss; import java.util.Optional; -@ApiModel +@Schema @EqualsAndHashCode(callSuper = true) public class Asset extends BaseDataWithAdditionalInfo implements HasLabel, HasTenantId, HasCustomerId, ExportableEntity { @@ -88,7 +87,7 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab this.externalId = asset.getExternalId(); } - @ApiModelProperty(position = 1, value = "JSON object with the asset Id. " + + @Schema(description = "JSON object with the asset Id. " + "Specify this field to update the asset. " + "Referencing non-existing asset Id will cause error. " + "Omit this field to create new asset.") @@ -97,13 +96,13 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the asset creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the asset creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) public TenantId getTenantId() { return tenantId; } @@ -112,7 +111,7 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab this.tenantId = tenantId; } - @ApiModelProperty(position = 4, value = "JSON object with Customer Id. Use 'assignAssetToCustomer' to change the Customer Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Customer Id. Use 'assignAssetToCustomer' to change the Customer Id.", accessMode = Schema.AccessMode.READ_ONLY) public CustomerId getCustomerId() { return customerId; } @@ -121,7 +120,7 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab this.customerId = customerId; } - @ApiModelProperty(position = 5, required = true, value = "Unique Asset Name in scope of Tenant", example = "Empire State Building") + @Schema(required = true, description = "Unique Asset Name in scope of Tenant", example = "Empire State Building") @Override public String getName() { return name; @@ -131,7 +130,7 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab this.name = name; } - @ApiModelProperty(position = 6, required = true, value = "Asset type", example = "Building") + @Schema(required = true, description = "Asset type", example = "Building") public String getType() { return type; } @@ -140,7 +139,7 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab this.type = type; } - @ApiModelProperty(position = 7, required = true, value = "Label that may be used in widgets", example = "NY Building") + @Schema(required = true, description = "Label that may be used in widgets", example = "NY Building") public String getLabel() { return label; } @@ -149,7 +148,7 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab this.label = label; } - @ApiModelProperty(position = 8, required = true, value = "JSON object with Asset Profile Id.") + @Schema(required = true, description = "JSON object with Asset Profile Id.") public AssetProfileId getAssetProfileId() { return assetProfileId; } @@ -158,7 +157,7 @@ public class Asset extends BaseDataWithAdditionalInfo implements HasLab this.assetProfileId = assetProfileId; } - @ApiModelProperty(position = 9, value = "Additional parameters of the asset", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "Additional parameters of the asset",implementation = com.fasterxml.jackson.databind.JsonNode.class) @Override public JsonNode getAdditionalInfo() { return super.getAdditionalInfo(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetInfo.java index b2d1fa95a2..08c084fde6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetInfo.java @@ -15,25 +15,24 @@ */ package org.thingsboard.server.common.data.asset; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.AssetId; -@ApiModel +@Schema @Data @EqualsAndHashCode(callSuper = true) public class AssetInfo extends Asset { private static final long serialVersionUID = -4094528227011066194L; - @ApiModelProperty(position = 10, value = "Title of the Customer that owns the asset.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Title of the Customer that owns the asset.", accessMode = Schema.AccessMode.READ_ONLY) private String customerTitle; - @ApiModelProperty(position = 11, value = "Indicates special 'Public' Customer that is auto-generated to use the assets on public dashboards.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Indicates special 'Public' Customer that is auto-generated to use the assets on public dashboards.", accessMode = Schema.AccessMode.READ_ONLY) private boolean customerIsPublic; - @ApiModelProperty(position = 12, value = "Name of the corresponding Asset Profile.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Name of the corresponding Asset Profile.", accessMode = Schema.AccessMode.READ_ONLY) private String assetProfileName; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfile.java b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfile.java index 5456ba36ce..f8acb0ef08 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfile.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfile.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.asset; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -34,7 +33,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @Data @ToString(exclude = {"image"}) @EqualsAndHashCode(callSuper = true) @@ -43,33 +42,33 @@ public class AssetProfile extends BaseData implements HasName, H private static final long serialVersionUID = 6998485460273302018L; - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id that owns the profile.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id that owns the profile.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; @NoXss @Length(fieldName = "name") - @ApiModelProperty(position = 4, value = "Unique Asset Profile Name in scope of Tenant.", example = "Building") + @Schema(description = "Unique Asset Profile Name in scope of Tenant.", example = "Building") private String name; @NoXss - @ApiModelProperty(position = 11, value = "Asset Profile description. ") + @Schema(description = "Asset Profile description. ") private String description; @Length(fieldName = "image", max = 1000000) - @ApiModelProperty(position = 12, value = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of asset profiles in the grid view. ") + @Schema(description = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of asset profiles in the grid view. ") private String image; private boolean isDefault; - @ApiModelProperty(position = 7, value = "Reference to the rule chain. " + + @Schema(description = "Reference to the rule chain. " + "If present, the specified rule chain will be used to process all messages related to asset, including asset updates, telemetry, attribute updates, etc. " + "Otherwise, the root rule chain will be used to process those messages.") private RuleChainId defaultRuleChainId; - @ApiModelProperty(position = 6, value = "Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to asset details.") + @Schema(description = "Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to asset details.") private DashboardId defaultDashboardId; @NoXss - @ApiModelProperty(position = 8, value = "Rule engine queue name. " + + @Schema(description = "Rule engine queue name. " + "If present, the specified queue will be used to store all unprocessed messages related to asset, including asset updates, telemetry, attribute updates, etc. " + "Otherwise, the 'Main' queue will be used to store those messages.") private String defaultQueueName; - @ApiModelProperty(position = 13, value = "Reference to the edge rule chain. " + + @Schema(description = "Reference to the edge rule chain. " + "If present, the specified edge rule chain will be used on the edge to process all messages related to asset, including asset updates, telemetry, attribute updates, etc. " + "Otherwise, the edge root rule chain will be used to process those messages.") private RuleChainId defaultEdgeRuleChainId; @@ -98,7 +97,7 @@ public class AssetProfile extends BaseData implements HasName, H this.externalId = assetProfile.getExternalId(); } - @ApiModelProperty(position = 1, value = "JSON object with the asset profile Id. " + + @Schema(description = "JSON object with the asset profile Id. " + "Specify this field to update the asset profile. " + "Referencing non-existing asset profile Id will cause error. " + "Omit this field to create new asset profile.") @@ -107,13 +106,13 @@ public class AssetProfile extends BaseData implements HasName, H return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the profile creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the profile creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 5, value = "Used to mark the default profile. Default profile is used when the asset profile is not specified during asset creation.") + @Schema(description = "Used to mark the default profile. Default profile is used when the asset profile is not specified during asset creation.") public boolean isDefault(){ return isDefault; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java index e590c4c094..dc1adb1b63 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetProfileInfo.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.asset; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.ToString; import lombok.Value; @@ -35,12 +35,12 @@ import java.util.UUID; @ToString(callSuper = true, exclude = "image") public class AssetProfileInfo extends EntityInfo { - @ApiModelProperty(position = 3, value = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of asset profiles in the grid view. ") + @Schema(description = "Either URL or Base64 data of the icon. Used in the mobile application to visualize set of asset profiles in the grid view. ") private final String image; - @ApiModelProperty(position = 4, value = "Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to asset details.") + @Schema(description = "Reference to the dashboard. Used in the mobile application to open the default dashboard when user navigates to asset details.") private final DashboardId defaultDashboardId; - @ApiModelProperty(position = 5, value = "Tenant id.") + @Schema(description = "Tenant id.") private final TenantId tenantId; @JsonCreator diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetSearchQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetSearchQuery.java index aeb693b02c..c8a7be5df5 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetSearchQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetSearchQuery.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data.asset; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -32,11 +32,11 @@ import java.util.List; @Data public class AssetSearchQuery { - @ApiModelProperty(position = 3, value = "Main search parameters.") + @Schema(description = "Main search parameters.") private RelationsSearchParameters parameters; - @ApiModelProperty(position = 1, value = "Type of the relation between root entity and asset (e.g. 'Contains' or 'Manages').") + @Schema(description = "Type of the relation between root entity and asset (e.g. 'Contains' or 'Manages').") private String relationType; - @ApiModelProperty(position = 2, value = "Array of asset types to filter the related entities (e.g. 'Building', 'Vehicle').") + @Schema(description = "Array of asset types to filter the related entities (e.g. 'Building', 'Vehicle').") private List assetTypes; public EntityRelationsQuery toEntitySearchQuery() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java b/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java index 5b6b68e622..5e95a54bb1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/audit/AuditLog.java @@ -16,8 +16,7 @@ package org.thingsboard.server.common.data.audit; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseData; @@ -28,31 +27,31 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @EqualsAndHashCode(callSuper = true) @Data public class AuditLog extends BaseData { - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; - @ApiModelProperty(position = 4, value = "JSON object with Customer Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Customer Id", accessMode = Schema.AccessMode.READ_ONLY) private CustomerId customerId; - @ApiModelProperty(position = 5, value = "JSON object with Entity id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Entity id", accessMode = Schema.AccessMode.READ_ONLY) private EntityId entityId; @NoXss - @ApiModelProperty(position = 6, value = "Name of the logged entity", example = "Thermometer", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Name of the logged entity", example = "Thermometer", accessMode = Schema.AccessMode.READ_ONLY) private String entityName; - @ApiModelProperty(position = 7, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with User id.", accessMode = Schema.AccessMode.READ_ONLY) private UserId userId; - @ApiModelProperty(position = 8, value = "Unique user name(email) of the user that performed some action on logged entity", example = "tenant@thingsboard.org", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Unique user name(email) of the user that performed some action on logged entity", example = "tenant@thingsboard.org", accessMode = Schema.AccessMode.READ_ONLY) private String userName; - @ApiModelProperty(position = 9, value = "String represented Action type", example = "ADDED", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "String represented Action type", example = "ADDED", accessMode = Schema.AccessMode.READ_ONLY) private ActionType actionType; - @ApiModelProperty(position = 10, value = "JsonNode represented action data", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JsonNode represented action data", accessMode = Schema.AccessMode.READ_ONLY) private JsonNode actionData; - @ApiModelProperty(position = 11, value = "String represented Action status", example = "SUCCESS", allowableValues = "SUCCESS,FAILURE", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "String represented Action status", example = "SUCCESS", allowableValues = "SUCCESS,FAILURE", accessMode = Schema.AccessMode.READ_ONLY) private ActionStatus actionStatus; - @ApiModelProperty(position = 12, value = "Failure action details info. An empty string in case of action status type 'SUCCESS', otherwise includes stack trace of the caused exception.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Failure action details info. An empty string in case of action status type 'SUCCESS', otherwise includes stack trace of the caused exception.", accessMode = Schema.AccessMode.READ_ONLY) private String actionFailureDetails; public AuditLog() { @@ -77,13 +76,13 @@ public class AuditLog extends BaseData { this.actionFailureDetails = auditLog.getActionFailureDetails(); } - @ApiModelProperty(position = 2, value = "Timestamp of the auditLog creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the auditLog creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 1, value = "JSON object with the auditLog Id") + @Schema(description = "JSON object with the auditLog Id") @Override public AuditLogId getId() { return super.getId(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java index dbde84abbe..f3157c1571 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.device; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -27,15 +26,15 @@ import org.thingsboard.server.common.data.relation.RelationsSearchParameters; import java.util.Collections; import java.util.List; -@ApiModel +@Schema @Data public class DeviceSearchQuery { - @ApiModelProperty(position = 3, value = "Main search parameters.") + @Schema(description = "Main search parameters.") private RelationsSearchParameters parameters; - @ApiModelProperty(position = 1, value = "Type of the relation between root entity and device (e.g. 'Contains' or 'Manages').") + @Schema(description = "Type of the relation between root entity and device (e.g. 'Contains' or 'Manages').") private String relationType; - @ApiModelProperty(position = 2, value = "Array of device types to filter the related entities (e.g. 'Temperature Sensor', 'Smoke Sensor').") + @Schema(description = "Array of device types to filter the related entities (e.g. 'Temperature Sensor', 'Smoke Sensor').") private List deviceTypes; public EntityRelationsQuery toEntitySearchQuery() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java index 9e7c85e6f4..a5dd1919e1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java @@ -15,11 +15,11 @@ */ package org.thingsboard.server.common.data.device.data; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.DeviceProfileType; -@ApiModel +@Schema @Data public class DefaultDeviceConfiguration implements DeviceConfiguration { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java index 79793b0fd7..aa1cb8dff8 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java @@ -19,12 +19,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.DeviceProfileType; import java.io.Serializable; -@ApiModel +@Schema @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java index 5ec461c271..b362231691 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java @@ -15,21 +15,20 @@ */ package org.thingsboard.server.common.data.device.data; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; -@ApiModel +@Schema @Data public class DeviceData implements Serializable { private static final long serialVersionUID = -3771567735290681274L; - @ApiModelProperty(position = 1, value = "Device configuration for device profile type. DEFAULT is only supported value for now") + @Schema(description = "Device configuration for device profile type. DEFAULT is only supported value for now") private DeviceConfiguration configuration; - @ApiModelProperty(position = 2, value = "Device transport configuration used to connect the device") + @Schema(description = "Device transport configuration used to connect the device") private DeviceTransportConfiguration transportConfiguration; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceTransportConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceTransportConfiguration.java index c5f385df4a..ace00a129f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceTransportConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceTransportConfiguration.java @@ -19,12 +19,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.DeviceTransportType; import java.io.Serializable; -@ApiModel +@Schema @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java index a8b83a1cf6..3cb3ff99f1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmCondition.java @@ -16,23 +16,22 @@ package org.thingsboard.server.common.data.device.profile; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import jakarta.validation.Valid; import java.io.Serializable; import java.util.List; -@ApiModel +@Schema @Data @JsonIgnoreProperties(ignoreUnknown = true) public class AlarmCondition implements Serializable { @Valid - @ApiModelProperty(position = 1, value = "JSON array of alarm condition filters") + @Schema(description = "JSON array of alarm condition filters") private List condition; - @ApiModelProperty(position = 2, value = "JSON object representing alarm condition type") + @Schema(description = "JSON object representing alarm condition type") private AlarmConditionSpec spec; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java index 7a44d707f9..39360cdb3e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilter.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.device.profile; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.query.EntityKeyValueType; import org.thingsboard.server.common.data.query.KeyFilterPredicate; @@ -25,20 +24,20 @@ import org.thingsboard.server.common.data.validation.NoXss; import jakarta.validation.Valid; import java.io.Serializable; -@ApiModel +@Schema @Data public class AlarmConditionFilter implements Serializable { @Valid - @ApiModelProperty(position = 1, value = "JSON object for specifying alarm condition by specific key") + @Schema(description = "JSON object for specifying alarm condition by specific key") private AlarmConditionFilterKey key; - @ApiModelProperty(position = 2, value = "String representation of the type of the value", example = "NUMERIC") + @Schema(description = "String representation of the type of the value", example = "NUMERIC") private EntityKeyValueType valueType; @NoXss - @ApiModelProperty(position = 3, value = "Value used in Constant comparison. For other types, such as TIME_SERIES or ATTRIBUTE, the predicate condition is used") + @Schema(description = "Value used in Constant comparison. For other types, such as TIME_SERIES or ATTRIBUTE, the predicate condition is used") private Object value; @Valid - @ApiModelProperty(position = 4, value = "JSON object representing filter condition") + @Schema(description = "JSON object representing filter condition") private KeyFilterPredicate predicate; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilterKey.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilterKey.java index 58dcedc993..a4782fdbff 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilterKey.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmConditionFilterKey.java @@ -15,21 +15,20 @@ */ package org.thingsboard.server.common.data.device.profile; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.validation.NoXss; import java.io.Serializable; -@ApiModel +@Schema @Data public class AlarmConditionFilterKey implements Serializable { - @ApiModelProperty(position = 1, value = "The key type", example = "TIME_SERIES") + @Schema(description = "The key type", example = "TIME_SERIES") private final AlarmConditionKeyType type; @NoXss - @ApiModelProperty(position = 2, value = "String value representing the key", example = "temp") + @Schema(description = "String value representing the key", example = "temp") private final String key; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java index 0f23ae5624..83615dfd4f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/AlarmRule.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.device.profile; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.validation.NoXss; @@ -24,20 +23,20 @@ import org.thingsboard.server.common.data.validation.NoXss; import jakarta.validation.Valid; import java.io.Serializable; -@ApiModel +@Schema @Data public class AlarmRule implements Serializable { @Valid - @ApiModelProperty(position = 1, value = "JSON object representing the alarm rule condition") + @Schema(description = "JSON object representing the alarm rule condition") private AlarmCondition condition; - @ApiModelProperty(position = 2, value = "JSON object representing time interval during which the rule is active") + @Schema(description = "JSON object representing time interval during which the rule is active") private AlarmSchedule schedule; // Advanced @NoXss - @ApiModelProperty(position = 3, value = "String value representing the additional details for an alarm rule") + @Schema(description = "String value representing the additional details for an alarm rule") private String alarmDetails; - @ApiModelProperty(position = 4, value = "JSON object with the dashboard Id representing the reference to alarm details dashboard used by mobile application") + @Schema(description = "JSON object with the dashboard Id representing the reference to alarm details dashboard used by mobile application") private DashboardId dashboardId; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java index 96f365a152..395149c52b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.device.profile; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.validation.Length; @@ -27,34 +26,34 @@ import java.io.Serializable; import java.util.List; import java.util.TreeMap; -@ApiModel +@Schema @Data public class DeviceProfileAlarm implements Serializable { - @ApiModelProperty(position = 1, value = "String value representing the alarm rule id", example = "highTemperatureAlarmID") + @Schema(description = "String value representing the alarm rule id", example = "highTemperatureAlarmID") private String id; @Length(fieldName = "alarm type") @NoXss - @ApiModelProperty(position = 2, value = "String value representing type of the alarm", example = "High Temperature Alarm") + @Schema(description = "String value representing type of the alarm", example = "High Temperature Alarm") private String alarmType; @Valid - @ApiModelProperty(position = 3, value = "Complex JSON object representing create alarm rules. The unique create alarm rule can be created for each alarm severity type. " + + @Schema(description = "Complex JSON object representing create alarm rules. The unique create alarm rule can be created for each alarm severity type. " + "There can be 5 create alarm rules configured per a single alarm type. See method implementation notes and AlarmRule model for more details") private TreeMap createRules; @Valid - @ApiModelProperty(position = 4, value = "JSON object representing clear alarm rule") + @Schema(description = "JSON object representing clear alarm rule") private AlarmRule clearRule; // Hidden in advanced settings - @ApiModelProperty(position = 5, value = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true") + @Schema(description = "Propagation flag to specify if alarm should be propagated to parent entities of alarm originator", example = "true") private boolean propagate; - @ApiModelProperty(position = 6, value = "Propagation flag to specify if alarm should be propagated to the owner (tenant or customer) of alarm originator", example = "true") + @Schema(description = "Propagation flag to specify if alarm should be propagated to the owner (tenant or customer) of alarm originator", example = "true") private boolean propagateToOwner; - @ApiModelProperty(position = 7, value = "Propagation flag to specify if alarm should be propagated to the tenant entity", example = "true") + @Schema(description = "Propagation flag to specify if alarm should be propagated to the tenant entity", example = "true") private boolean propagateToTenant; - @ApiModelProperty(position = 8, value = "JSON array of relation types that should be used for propagation. " + + @Schema(description = "JSON array of relation types that should be used for propagation. " + "By default, 'propagateRelationTypes' array is empty which means that the alarm will be propagated based on any relation type to parent entities. " + "This parameter should be used only in case when 'propagate' parameter is set to true, otherwise, 'propagateRelationTypes' array will be ignored.") private List propagateRelationTypes; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java index f6b2de915b..e2e7a646ea 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileData.java @@ -15,27 +15,26 @@ */ package org.thingsboard.server.common.data.device.profile; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import jakarta.validation.Valid; import java.io.Serializable; import java.util.List; -@ApiModel +@Schema @Data public class DeviceProfileData implements Serializable { - @ApiModelProperty(position = 1, value = "JSON object of device profile configuration") + @Schema(description = "JSON object of device profile configuration") private DeviceProfileConfiguration configuration; @Valid - @ApiModelProperty(position = 2, value = "JSON object of device profile transport configuration") + @Schema(description = "JSON object of device profile transport configuration") private DeviceProfileTransportConfiguration transportConfiguration; - @ApiModelProperty(position = 3, value = "JSON object of provisioning strategy type per device profile") + @Schema(description = "JSON object of provisioning strategy type per device profile") private DeviceProfileProvisionConfiguration provisionConfiguration; @Valid - @ApiModelProperty(position = 4, value = "JSON array of alarm rules configuration per device profile") + @Schema(description = "JSON array of alarm rules configuration per device profile") private List alarms; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfig.java index 4405115905..b59c5fadea 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfig.java @@ -15,56 +15,55 @@ */ package org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; -@ApiModel +@Schema @Data public class LwM2MServerSecurityConfig implements Serializable { - @ApiModelProperty(position = 1, value = "Server short Id. Used as link to associate server Object Instance. This identifier uniquely identifies each LwM2M Server configured for the LwM2M Client. " + + @Schema(description = "Server short Id. Used as link to associate server Object Instance. This identifier uniquely identifies each LwM2M Server configured for the LwM2M Client. " + "This Resource MUST be set when the Bootstrap-Server Resource has a value of 'false'. " + - "The values ID:0 and ID:65535 values MUST NOT be used for identifying the LwM2M Server.", example = "123", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + "The values ID:0 and ID:65535 values MUST NOT be used for identifying the LwM2M Server.", example = "123", accessMode = Schema.AccessMode.READ_ONLY) protected Integer shortServerId = 123; /** Security -> ObjectId = 0 'LWM2M Security' */ - @ApiModelProperty(position = 2, value = "Is Bootstrap Server or Lwm2m Server. " + + @Schema(description = "Is Bootstrap Server or Lwm2m Server. " + "The LwM2M Client MAY be configured to use one or more LwM2M Server Account(s). " + "The LwM2M Client MUST have at most one LwM2M Bootstrap-Server Account. " + - "(*) The LwM2M client MUST have at least one LwM2M server account after completing the boot sequence specified.", example = "true or false", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + "(*) The LwM2M client MUST have at least one LwM2M server account after completing the boot sequence specified.", example = "true or false", accessMode = Schema.AccessMode.READ_ONLY) protected boolean bootstrapServerIs = false; - @ApiModelProperty(position = 3, value = "Host for 'No Security' mode", example = "0.0.0.0", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Host for 'No Security' mode", example = "0.0.0.0", accessMode = Schema.AccessMode.READ_ONLY) protected String host; - @ApiModelProperty(position = 4, value = "Port for Lwm2m Server: 'No Security' mode: Lwm2m Server or Bootstrap Server", example = "'5685' or '5687'", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Port for Lwm2m Server: 'No Security' mode: Lwm2m Server or Bootstrap Server", example = "'5685' or '5687'", accessMode = Schema.AccessMode.READ_ONLY) protected Integer port; - @ApiModelProperty(position = 7, value = "Client Hold Off Time. The number of seconds to wait before initiating a Client Initiated Bootstrap once the LwM2M Client has determined it should initiate this bootstrap mode. (This information is relevant for use with a Bootstrap-Server only.)", example = "1", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Client Hold Off Time. The number of seconds to wait before initiating a Client Initiated Bootstrap once the LwM2M Client has determined it should initiate this bootstrap mode. (This information is relevant for use with a Bootstrap-Server only.)", example = "1", accessMode = Schema.AccessMode.READ_ONLY) protected Integer clientHoldOffTime = 1; - @ApiModelProperty(position = 8, value = "Server Public Key for 'Security' mode (DTLS): RPK or X509. Format: base64 encoded", example = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAZ0pSaGKHk/GrDaUDnQZpeEdGwX7m3Ws+U/kiVat\n" + - "+44sgk3c8g0LotfMpLlZJPhPwJ6ipXV+O1r7IZUjBs3LNA==", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Server Public Key for 'Security' mode (DTLS): RPK or X509. Format: base64 encoded", example = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAZ0pSaGKHk/GrDaUDnQZpeEdGwX7m3Ws+U/kiVat\n" + + "+44sgk3c8g0LotfMpLlZJPhPwJ6ipXV+O1r7IZUjBs3LNA==", accessMode = Schema.AccessMode.READ_ONLY) protected String serverPublicKey; - @ApiModelProperty(position = 9, value = "Server Public Key for 'Security' mode (DTLS): X509. Format: base64 encoded", example = "MMIICODCCAd6gAwIBAgIUI88U1zowOdrxDK/dOV+36gJxI2MwCgYIKoZIzj0EAwIwejELMAkGA1UEBhMCVUs\n" + + @Schema(description = "Server Public Key for 'Security' mode (DTLS): X509. Format: base64 encoded", example = "MMIICODCCAd6gAwIBAgIUI88U1zowOdrxDK/dOV+36gJxI2MwCgYIKoZIzj0EAwIwejELMAkGA1UEBhMCVUs\n" + "xEjAQBgNVBAgTCUt5aXYgY2l0eTENMAsGA1UEBxMES3lpdjEUMBIGA1UEChMLVGhpbmdzYm9hcmQxFzAVBgNVBAsMDkRFVkVMT1BFUl9URVNUMRkwFwYDVQQDDBBpbnRlcm1lZGlhdGVfY2EwMB4XDTIyMDEwOTEzMDMwMFoXDTI3MDEwODEzMDMwMFowFDESMBAGA1UEAxM\n" + "JbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUO3vBo/JTv0eooY7XHiKAIVDoWKFqtrU7C6q8AIKqpLcqhCdW+haFeBOH3PjY6EwaWkY04Bir4oanU0s7tz2uKOBpzCBpDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/\n" + "BAIwADAdBgNVHQ4EFgQUEjc3Q4a0TxzP/3x3EV4fHxYUg0YwHwYDVR0jBBgwFoAUuSquGycMU6Q0SYNcbtSkSD3TfH0wLwYDVR0RBCgwJoIVbG9jYWxob3N0LmxvY2FsZG9tYWlugglsb2NhbGhvc3SCAiAtMAoGCCqGSM49BAMCA0gAMEUCIQD7dbZObyUaoDiNbX+9fUNp\n" + - "AWrD7N7XuJUwZ9FcN75R3gIgb2RNjDkHoyUyF1YajwkBk+7XmIXNClmizNJigj908mw=", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + "AWrD7N7XuJUwZ9FcN75R3gIgb2RNjDkHoyUyF1YajwkBk+7XmIXNClmizNJigj908mw=", accessMode = Schema.AccessMode.READ_ONLY) protected String serverCertificate; - @ApiModelProperty(position = 10, value = "Bootstrap Server Account Timeout (If the value is set to 0, or if this resource is not instantiated, the Bootstrap-Server Account lifetime is infinite.)", example = "0", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Bootstrap Server Account Timeout (If the value is set to 0, or if this resource is not instantiated, the Bootstrap-Server Account lifetime is infinite.)", example = "0", accessMode = Schema.AccessMode.READ_ONLY) Integer bootstrapServerAccountTimeout = 0; /** Config -> ObjectId = 1 'LwM2M Server' */ - @ApiModelProperty(position = 11, value = "Specify the lifetime of the registration in seconds.", example = "300", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Specify the lifetime of the registration in seconds.", example = "300", accessMode = Schema.AccessMode.READ_ONLY) private Integer lifetime = 300; - @ApiModelProperty(position = 12, value = "The default value the LwM2M Client should use for the Minimum Period of an Observation in the absence of this parameter being included in an Observation. " + - "If this Resource doesn’t exist, the default value is 0.", example = "1", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "The default value the LwM2M Client should use for the Minimum Period of an Observation in the absence of this parameter being included in an Observation. " + + "If this Resource doesn’t exist, the default value is 0.", example = "1", accessMode = Schema.AccessMode.READ_ONLY) private Integer defaultMinPeriod = 1; /** ResourceID=6 'Notification Storing When Disabled or Offline' */ - @ApiModelProperty(position = 13, value = "If true, the LwM2M Client stores “Notify” operations to the LwM2M Server while the LwM2M Server account is disabled or the LwM2M Client is offline. After the LwM2M Server account is enabled or the LwM2M Client is online, the LwM2M Client reports the stored “Notify” operations to the Server. " + + @Schema(description = "If true, the LwM2M Client stores “Notify” operations to the LwM2M Server while the LwM2M Server account is disabled or the LwM2M Client is offline. After the LwM2M Server account is enabled or the LwM2M Client is online, the LwM2M Client reports the stored “Notify” operations to the Server. " + "If false, the LwM2M Client discards all the “Notify” operations or temporarily disables the Observe function while the LwM2M Server is disabled or the LwM2M Client is offline. " + - "The default value is true.", example = "true", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + "The default value is true.", example = "true", accessMode = Schema.AccessMode.READ_ONLY) private boolean notifIfDisabled = true; - @ApiModelProperty(position = 14, value = "This Resource defines the transport binding configured for the LwM2M Client. " + - "If the LwM2M Client supports the binding specified in this Resource, the LwM2M Client MUST use that transport for the Current Binding Mode.", example = "U", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "This Resource defines the transport binding configured for the LwM2M Client. " + + "If the LwM2M Client supports the binding specified in this Resource, the LwM2M Client MUST use that transport for the Current Binding Mode.", example = "U", accessMode = Schema.AccessMode.READ_ONLY) private String binding = "U"; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java index ce622322d9..ea3e5a8dce 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MServerSecurityConfigDefault.java @@ -15,15 +15,14 @@ */ package org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class LwM2MServerSecurityConfigDefault extends LwM2MServerSecurityConfig { - @ApiModelProperty(position = 5, value = "Host for 'Security' mode (DTLS)", example = "0.0.0.0", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Host for 'Security' mode (DTLS)", example = "0.0.0.0", accessMode = Schema.AccessMode.READ_ONLY) protected String securityHost; - @ApiModelProperty(position = 6, value = "Port for 'Security' mode (DTLS): Lwm2m Server or Bootstrap Server", example = "5686 or 5688", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Port for 'Security' mode (DTLS): Lwm2m Server or Bootstrap Server", example = "5686 or 5688", accessMode = Schema.AccessMode.READ_ONLY) protected Integer securityPort; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java index 6d1d9390ba..169f4007f0 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.edge; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.Setter; import lombok.ToString; @@ -31,7 +30,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @EqualsAndHashCode(callSuper = true) @ToString @Setter @@ -89,7 +88,7 @@ public class Edge extends BaseDataWithAdditionalInfo implements HasLabel this.secret = edge.getSecret(); } - @ApiModelProperty(position = 1, value = "JSON object with the Edge Id. " + + @Schema(description = "JSON object with the Edge Id. " + "Specify this field to update the Edge. " + "Referencing non-existing Edge Id will cause error. " + "Omit this field to create new Edge." ) @@ -98,51 +97,51 @@ public class Edge extends BaseDataWithAdditionalInfo implements HasLabel return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the edge creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the edge creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id. Use 'assignDeviceToTenant' to change the Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id. Use 'assignDeviceToTenant' to change the Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) @Override public TenantId getTenantId() { return this.tenantId; } - @ApiModelProperty(position = 4, value = "JSON object with Customer Id. Use 'assignEdgeToCustomer' to change the Customer Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Customer Id. Use 'assignEdgeToCustomer' to change the Customer Id.", accessMode = Schema.AccessMode.READ_ONLY) @Override public CustomerId getCustomerId() { return this.customerId; } - @ApiModelProperty(position = 5, value = "JSON object with Root Rule Chain Id. Use 'setEdgeRootRuleChain' to change the Root Rule Chain Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Root Rule Chain Id. Use 'setEdgeRootRuleChain' to change the Root Rule Chain Id.", accessMode = Schema.AccessMode.READ_ONLY) public RuleChainId getRootRuleChainId() { return this.rootRuleChainId; } - @ApiModelProperty(position = 6, required = true, value = "Unique Edge Name in scope of Tenant", example = "Silo_A_Edge") + @Schema(required = true, description = "Unique Edge Name in scope of Tenant", example = "Silo_A_Edge") @Override public String getName() { return this.name; } - @ApiModelProperty(position = 7, required = true, value = "Edge type", example = "Silos") + @Schema(required = true, description = "Edge type", example = "Silos") public String getType() { return this.type; } - @ApiModelProperty(position = 8, value = "Label that may be used in widgets", example = "Silo Edge on far field") + @Schema(description = "Label that may be used in widgets", example = "Silo Edge on far field") public String getLabel() { return this.label; } - @ApiModelProperty(position = 9, required = true, value = "Edge routing key ('username') to authorize on cloud") + @Schema(required = true, description = "Edge routing key ('username') to authorize on cloud") public String getRoutingKey() { return this.routingKey; } - @ApiModelProperty(position = 10, required = true, value = "Edge secret ('password') to authorize on cloud") + @Schema(required = true, description = "Edge secret ('password') to authorize on cloud") public String getSecret() { return this.secret; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInstallInstructions.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInstallInstructions.java index acfc458906..92a893c973 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInstallInstructions.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeInstallInstructions.java @@ -15,18 +15,17 @@ */ package org.thingsboard.server.common.data.edge; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel +@Schema @Data @AllArgsConstructor @NoArgsConstructor public class EdgeInstallInstructions { - @ApiModelProperty(position = 1, value = "Markdown with docker install instructions") + @Schema(description = "Markdown with docker install instructions") private String dockerInstallInstructions; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeSearchQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeSearchQuery.java index cf029ba793..575e4cbba0 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeSearchQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeSearchQuery.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data.edge; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -29,11 +29,11 @@ import java.util.List; @Data public class EdgeSearchQuery { - @ApiModelProperty(position = 3, value = "Main search parameters.") + @Schema(description = "Main search parameters.") private RelationsSearchParameters parameters; - @ApiModelProperty(position = 1, value = "Type of the relation between root entity and edge (e.g. 'Contains' or 'Manages').") + @Schema(description = "Type of the relation between root entity and edge (e.g. 'Contains' or 'Manages').") private String relationType; - @ApiModelProperty(position = 2, value = "Array of edge types to filter the related entities (e.g. 'Silos', 'Stores').") + @Schema(description = "Array of edge types to filter the related entities (e.g. 'Silos', 'Stores').") private List edgeTypes; public EntityRelationsQuery toEntitySearchQuery() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java index c840d828fa..de77d3bb76 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/entityview/EntityViewSearchQuery.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.entityview; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.relation.EntityRelation; @@ -27,15 +26,15 @@ import org.thingsboard.server.common.data.relation.RelationsSearchParameters; import java.util.Collections; import java.util.List; -@ApiModel +@Schema @Data public class EntityViewSearchQuery { - @ApiModelProperty(position = 3, value = "Main search parameters.") + @Schema(description = "Main search parameters.") private RelationsSearchParameters parameters; - @ApiModelProperty(position = 1, value = "Type of the relation between root entity and device (e.g. 'Contains' or 'Manages').") + @Schema(description = "Type of the relation between root entity and device (e.g. 'Contains' or 'Manages').") private String relationType; - @ApiModelProperty(position = 2, value = "Array of entity view types to filter the related entities (e.g. 'Temperature Sensor', 'Smoke Sensor').") + @Schema(description = "Array of entity view types to filter the related entities (e.g. 'Temperature Sensor', 'Smoke Sensor').") private List entityViewTypes; public EntityRelationsQuery toEntitySearchQuery() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/event/DebugEventFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/event/DebugEventFilter.java index c6773838a7..14507abae7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/event/DebugEventFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/event/DebugEventFilter.java @@ -15,20 +15,19 @@ */ package org.thingsboard.server.common.data.event; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.StringUtils; @Data -@ApiModel +@Schema public abstract class DebugEventFilter implements EventFilter { - @ApiModelProperty(position = 1, value = "String value representing the server name, identifier or ip address where the platform is running", example = "ip-172-31-24-152") + @Schema(description = "String value representing the server name, identifier or ip address where the platform is running", example = "ip-172-31-24-152") protected String server; - @ApiModelProperty(position = 10, value = "Boolean value to filter the errors", allowableValues = "false, true") + @Schema(description = "Boolean value to filter the errors", allowableValues = "false, true") protected boolean isError; - @ApiModelProperty(position = 11, value = "The case insensitive 'contains' filter based on error message", example = "not present in the DB") + @Schema(description = "The case insensitive 'contains' filter based on error message", example = "not present in the DB") protected String errorStr; public void setIsError(boolean isError) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/event/ErrorEventFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/event/ErrorEventFilter.java index e20cd0dfa9..951965ee72 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/event/ErrorEventFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/event/ErrorEventFilter.java @@ -15,20 +15,19 @@ */ package org.thingsboard.server.common.data.event; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.StringUtils; @Data -@ApiModel +@Schema public class ErrorEventFilter implements EventFilter { - @ApiModelProperty(position = 1, value = "String value representing the server name, identifier or ip address where the platform is running", example = "ip-172-31-24-152") + @Schema(description = "String value representing the server name, identifier or ip address where the platform is running", example = "ip-172-31-24-152") protected String server; - @ApiModelProperty(position = 2, value = "String value representing the method name when the error happened", example = "onClusterEventMsg") + @Schema(description = "String value representing the method name when the error happened", example = "onClusterEventMsg") protected String method; - @ApiModelProperty(position = 3, value = "The case insensitive 'contains' filter based on error message", example = "not present in the DB") + @Schema(description = "The case insensitive 'contains' filter based on error message", example = "not present in the DB") protected String errorStr; @Override diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/event/EventFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/event/EventFilter.java index 7a520e212f..af4a283ef7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/event/EventFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/event/EventFilter.java @@ -17,10 +17,9 @@ package org.thingsboard.server.common.data.event; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; -@ApiModel +@Schema @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, @@ -34,7 +33,7 @@ import io.swagger.annotations.ApiModelProperty; }) public interface EventFilter { - @ApiModelProperty(position = 1, required = true, value = "String value representing the event type", example = "STATS") + @Schema(required = true, description = "String value representing the event type", example = "STATS") EventType getEventType(); boolean isNotEmpty(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/event/LifeCycleEventFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/event/LifeCycleEventFilter.java index 659a16a135..3d193a5064 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/event/LifeCycleEventFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/event/LifeCycleEventFilter.java @@ -15,22 +15,21 @@ */ package org.thingsboard.server.common.data.event; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.StringUtils; @Data -@ApiModel +@Schema public class LifeCycleEventFilter implements EventFilter { - @ApiModelProperty(position = 1, value = "String value representing the server name, identifier or ip address where the platform is running", example = "ip-172-31-24-152") + @Schema(description = "String value representing the server name, identifier or ip address where the platform is running", example = "ip-172-31-24-152") protected String server; - @ApiModelProperty(position = 2, value = "String value representing the lifecycle event type", example = "STARTED") + @Schema(description = "String value representing the lifecycle event type", example = "STARTED") protected String event; - @ApiModelProperty(position = 3, value = "String value representing status of the lifecycle event", allowableValues = "Success, Failure") + @Schema(description = "String value representing status of the lifecycle event", allowableValues = "Success, Failure") protected String status; - @ApiModelProperty(position = 4, value = "The case insensitive 'contains' filter based on error message", example = "not present in the DB") + @Schema(description = "The case insensitive 'contains' filter based on error message", example = "not present in the DB") protected String errorStr; @Override diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/event/RuleChainDebugEventFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/event/RuleChainDebugEventFilter.java index 29e31cf0c8..7f00c26579 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/event/RuleChainDebugEventFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/event/RuleChainDebugEventFilter.java @@ -15,18 +15,17 @@ */ package org.thingsboard.server.common.data.event; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.StringUtils; @Data @EqualsAndHashCode(callSuper = true) -@ApiModel +@Schema public class RuleChainDebugEventFilter extends DebugEventFilter { - @ApiModelProperty(position = 2, value = "String value representing the message") + @Schema(description = "String value representing the message") protected String message; @Override diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/event/RuleNodeDebugEventFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/event/RuleNodeDebugEventFilter.java index 589a70106e..b9cdfe8d37 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/event/RuleNodeDebugEventFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/event/RuleNodeDebugEventFilter.java @@ -15,32 +15,31 @@ */ package org.thingsboard.server.common.data.event; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.StringUtils; @Data @EqualsAndHashCode(callSuper = true) -@ApiModel +@Schema public class RuleNodeDebugEventFilter extends DebugEventFilter { - @ApiModelProperty(position = 2, value = "String value representing msg direction type (incoming to entity or outcoming from entity)", allowableValues = "IN, OUT") + @Schema(description = "String value representing msg direction type (incoming to entity or outcoming from entity)", allowableValues = "IN, OUT") protected String msgDirectionType; - @ApiModelProperty(position = 3, value = "String value representing the entity id in the event body (originator of the message)", example = "de9d54a0-2b7a-11ec-a3cc-23386423d98f") + @Schema(description = "String value representing the entity id in the event body (originator of the message)", example = "de9d54a0-2b7a-11ec-a3cc-23386423d98f") protected String entityId; - @ApiModelProperty(position = 4, value = "String value representing the entity type", allowableValues = "DEVICE") + @Schema(description = "String value representing the entity type", allowableValues = "DEVICE") protected String entityType; - @ApiModelProperty(position = 5, value = "String value representing the message id in the rule engine", example = "de9d54a0-2b7a-11ec-a3cc-23386423d98f") + @Schema(description = "String value representing the message id in the rule engine", example = "de9d54a0-2b7a-11ec-a3cc-23386423d98f") protected String msgId; - @ApiModelProperty(position = 6, value = "String value representing the message type", example = "POST_TELEMETRY_REQUEST") + @Schema(description = "String value representing the message type", example = "POST_TELEMETRY_REQUEST") protected String msgType; - @ApiModelProperty(position = 7, value = "String value representing the type of message routing", example = "Success") + @Schema(description = "String value representing the type of message routing", example = "Success") protected String relationType; - @ApiModelProperty(position = 8, value = "The case insensitive 'contains' filter based on data (key and value) for the message.", example = "humidity") + @Schema(description = "The case insensitive 'contains' filter based on data (key and value) for the message.", example = "humidity") protected String dataSearch; - @ApiModelProperty(position = 9, value = "The case insensitive 'contains' filter based on metadata (key and value) for the message.", example = "deviceName") + @Schema(description = "The case insensitive 'contains' filter based on metadata (key and value) for the message.", example = "deviceName") protected String metadataSearch; @Override diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/event/StatisticsEventFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/event/StatisticsEventFilter.java index 15ac1c9c90..24485dd297 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/event/StatisticsEventFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/event/StatisticsEventFilter.java @@ -15,24 +15,23 @@ */ package org.thingsboard.server.common.data.event; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.StringUtils; @Data -@ApiModel +@Schema public class StatisticsEventFilter implements EventFilter { - @ApiModelProperty(position = 1, value = "String value representing the server name, identifier or ip address where the platform is running", example = "ip-172-31-24-152") + @Schema(description = "String value representing the server name, identifier or ip address where the platform is running", example = "ip-172-31-24-152") protected String server; - @ApiModelProperty(position = 2, value = "The minimum number of successfully processed messages", example = "25") + @Schema(description = "The minimum number of successfully processed messages", example = "25") protected Integer minMessagesProcessed; - @ApiModelProperty(position = 3, value = "The maximum number of successfully processed messages", example = "250") + @Schema(description = "The maximum number of successfully processed messages", example = "250") protected Integer maxMessagesProcessed; - @ApiModelProperty(position = 4, value = "The minimum number of errors occurred during messages processing", example = "30") + @Schema(description = "The minimum number of errors occurred during messages processing", example = "30") protected Integer minErrorsOccurred; - @ApiModelProperty(position = 5, value = "The maximum number of errors occurred during messages processing", example = "300") + @Schema(description = "The maximum number of errors occurred during messages processing", example = "300") protected Integer maxErrorsOccurred; @Override diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java index 1cccaa4147..fdd8902127 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmCommentId.java @@ -17,11 +17,11 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; import java.util.UUID; -@ApiModel +@Schema public class AlarmCommentId extends UUIDBased { private static final long serialVersionUID = 1L; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmId.java index 74e61ce9f3..be60f8f329 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/AlarmId.java @@ -17,13 +17,12 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; -@ApiModel +@Schema public class AlarmId extends UUIDBased implements EntityId { private static final long serialVersionUID = 1L; @@ -37,7 +36,7 @@ public class AlarmId extends UUIDBased implements EntityId { return new AlarmId(UUID.fromString(alarmId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "ALARM", allowableValues = "ALARM") + @Schema(required = true, description = "string", example = "ALARM", allowableValues = "ALARM") @Override public EntityType getEntityType() { return EntityType.ALARM; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/ApiUsageStateId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/ApiUsageStateId.java index 50e24a0f22..0cdf879eac 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/ApiUsageStateId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/ApiUsageStateId.java @@ -17,13 +17,12 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; -@ApiModel +@Schema public class ApiUsageStateId extends UUIDBased implements EntityId { @JsonCreator @@ -35,7 +34,7 @@ public class ApiUsageStateId extends UUIDBased implements EntityId { return new ApiUsageStateId(UUID.fromString(userId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "API_USAGE_STATE", allowableValues = "API_USAGE_STATE") + @Schema(required = true, description = "string", example = "API_USAGE_STATE", allowableValues = "API_USAGE_STATE") @Override public EntityType getEntityType() { return EntityType.API_USAGE_STATE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/AssetId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/AssetId.java index 593c305a07..01fdc7680b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/AssetId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/AssetId.java @@ -17,13 +17,12 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; -@ApiModel +@Schema public class AssetId extends UUIDBased implements EntityId { private static final long serialVersionUID = 1L; @@ -37,7 +36,7 @@ public class AssetId extends UUIDBased implements EntityId { return new AssetId(UUID.fromString(assetId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "ASSET", allowableValues = "ASSET") + @Schema(required = true, description = "string", example = "ASSET", allowableValues = "ASSET") @Override public EntityType getEntityType() { return EntityType.ASSET; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/AssetProfileId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/AssetProfileId.java index 5de08e53e5..7fbf28c4d3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/AssetProfileId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/AssetProfileId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -35,7 +35,7 @@ public class AssetProfileId extends UUIDBased implements EntityId { return new AssetProfileId(UUID.fromString(assetProfileId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "ASSET_PROFILE", allowableValues = "ASSET_PROFILE") + @Schema(required = true, description = "string", example = "ASSET_PROFILE", allowableValues = "ASSET_PROFILE") @Override public EntityType getEntityType() { return EntityType.ASSET_PROFILE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/CustomerId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/CustomerId.java index beaa331ecf..dccd89b73b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/CustomerId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/CustomerId.java @@ -17,13 +17,12 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; -@ApiModel +@Schema public final class CustomerId extends UUIDBased implements EntityId { private static final long serialVersionUID = 1L; @@ -33,7 +32,7 @@ public final class CustomerId extends UUIDBased implements EntityId { super(id); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "CUSTOMER", allowableValues = "CUSTOMER") + @Schema(required = true, description = "string", example = "CUSTOMER", allowableValues = "CUSTOMER") @Override public EntityType getEntityType() { return EntityType.CUSTOMER; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/DashboardId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/DashboardId.java index 740a801651..3af27d5457 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/DashboardId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/DashboardId.java @@ -17,13 +17,12 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; -@ApiModel +@Schema public class DashboardId extends UUIDBased implements EntityId { @JsonCreator @@ -35,7 +34,7 @@ public class DashboardId extends UUIDBased implements EntityId { return new DashboardId(UUID.fromString(dashboardId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "DASHBOARD", allowableValues = "DASHBOARD") + @Schema(required = true, description = "string", example = "DASHBOARD", allowableValues = "DASHBOARD") @Override public EntityType getEntityType() { return EntityType.DASHBOARD; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceId.java index e39c5805ce..25c1fb6be4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceId.java @@ -17,13 +17,12 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; -@ApiModel +@Schema public class DeviceId extends UUIDBased implements EntityId { private static final long serialVersionUID = 1L; @@ -38,7 +37,7 @@ public class DeviceId extends UUIDBased implements EntityId { } @Override - @ApiModelProperty(position = 2, required = true, value = "string", example = "DEVICE", allowableValues = "DEVICE") + @Schema(required = true, description = "string", example = "DEVICE", allowableValues = "DEVICE") public EntityType getEntityType() { return EntityType.DEVICE; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceProfileId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceProfileId.java index 26bc6d2b96..25c22ce8c1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceProfileId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceProfileId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -35,7 +35,7 @@ public class DeviceProfileId extends UUIDBased implements EntityId { return new DeviceProfileId(UUID.fromString(deviceProfileId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "DEVICE_PROFILE", allowableValues = "DEVICE_PROFILE") + @Schema(required = true, description = "string", example = "DEVICE_PROFILE", allowableValues = "DEVICE_PROFILE") @Override public EntityType getEntityType() { return EntityType.DEVICE_PROFILE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EdgeId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EdgeId.java index fb96f15740..b5a6632b44 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EdgeId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EdgeId.java @@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType; import org.thingsboard.server.common.data.EntityType; @@ -41,7 +41,7 @@ public class EdgeId extends UUIDBased implements EntityId { return new EdgeId(UUID.fromString(edgeId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "EDGE", allowableValues = "EDGE") + @Schema(required = true, description = "string", example = "EDGE", allowableValues = "EDGE") @Override public EntityType getEntityType() { return EntityType.EDGE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java index 3f112e92ed..a6addb1d11 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java @@ -18,8 +18,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.io.Serializable; @@ -31,15 +30,15 @@ import java.util.UUID; @JsonDeserialize(using = EntityIdDeserializer.class) @JsonSerialize(using = EntityIdSerializer.class) -@ApiModel +@Schema public interface EntityId extends HasUUID, Serializable { //NOSONAR, the constant is closely related to EntityId UUID NULL_UUID = UUID.fromString("13814000-1dd2-11b2-8080-808080808080"); - @ApiModelProperty(position = 1, required = true, value = "ID of the entity, time-based UUID v1", example = "784f394c-42b6-435a-983c-b7beff2784f9") + @Schema(required = true, description = "ID of the entity, time-based UUID v1", example = "784f394c-42b6-435a-983c-b7beff2784f9") UUID getId(); - @ApiModelProperty(position = 2, required = true, example = "DEVICE") + @Schema(required = true, example = "DEVICE") EntityType getEntityType(); @JsonIgnore diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityViewId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityViewId.java index 9cf7e83fa3..0a57acb813 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityViewId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityViewId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -38,7 +38,7 @@ public class EntityViewId extends UUIDBased implements EntityId { return new EntityViewId(UUID.fromString(entityViewID)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "ENTITY_VIEW", allowableValues = "ENTITY_VIEW") + @Schema(required = true, description = "string", example = "ENTITY_VIEW", allowableValues = "ENTITY_VIEW") @Override public EntityType getEntityType() { return EntityType.ENTITY_VIEW; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/OtaPackageId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/OtaPackageId.java index 8977da637b..2799ecfdab 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/OtaPackageId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/OtaPackageId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -35,7 +35,7 @@ public class OtaPackageId extends UUIDBased implements EntityId { return new OtaPackageId(UUID.fromString(firmwareId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "OTA_PACKAGE", allowableValues = "OTA_PACKAGE") + @Schema(required = true, description = "string", example = "OTA_PACKAGE", allowableValues = "OTA_PACKAGE") @Override public EntityType getEntityType() { return EntityType.OTA_PACKAGE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/RpcId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/RpcId.java index 7a3045c8a8..4f640303b9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/RpcId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/RpcId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -31,7 +31,7 @@ public final class RpcId extends UUIDBased implements EntityId { super(id); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "RPC", allowableValues = "RPC") + @Schema(required = true, description = "string", example = "RPC", allowableValues = "RPC") @Override public EntityType getEntityType() { return EntityType.RPC; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/RuleChainId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/RuleChainId.java index cb3e2ca334..a4e4b9019c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/RuleChainId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/RuleChainId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -29,7 +29,7 @@ public class RuleChainId extends UUIDBased implements EntityId { super(id); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "RULE_CHAIN", allowableValues = "RULE_CHAIN") + @Schema(required = true, description = "string", example = "RULE_CHAIN", allowableValues = "RULE_CHAIN") @Override public EntityType getEntityType() { return EntityType.RULE_CHAIN; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/RuleNodeId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/RuleNodeId.java index db410dfea2..a4fc103ada 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/RuleNodeId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/RuleNodeId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -29,7 +29,7 @@ public class RuleNodeId extends UUIDBased implements EntityId { super(id); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "RULE_NODE", allowableValues = "RULE_NODE") + @Schema(required = true, description = "string", example = "RULE_NODE", allowableValues = "RULE_NODE") @Override public EntityType getEntityType() { return EntityType.RULE_NODE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/TbResourceId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/TbResourceId.java index e2716b0f43..eb1ce5cd13 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/TbResourceId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/TbResourceId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -31,7 +31,7 @@ public class TbResourceId extends UUIDBased implements EntityId { super(id); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "TB_RESOURCE", allowableValues = "TB_RESOURCE") + @Schema(required = true, description = "string", example = "TB_RESOURCE", allowableValues = "TB_RESOURCE") @Override public EntityType getEntityType() { return EntityType.TB_RESOURCE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/TenantId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/TenantId.java index 6f5fb09927..9a4264ca60 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/TenantId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/TenantId.java @@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.ConcurrentReferenceHashMap.ReferenceType; import org.thingsboard.server.common.data.EntityType; @@ -50,7 +50,7 @@ public final class TenantId extends UUIDBased implements EntityId { return this.equals(SYS_TENANT_ID); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "TENANT", allowableValues = "TENANT") + @Schema(required = true, description = "string", example = "TENANT", allowableValues = "TENANT") @Override public EntityType getEntityType() { return EntityType.TENANT; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/TenantProfileId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/TenantProfileId.java index f1e67a9435..e73d94df9f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/TenantProfileId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/TenantProfileId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -35,7 +35,7 @@ public class TenantProfileId extends UUIDBased implements EntityId { return new TenantProfileId(UUID.fromString(tenantProfileId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "TENANT_PROFILE", allowableValues = "TENANT_PROFILE") + @Schema(required = true, description = "string", example = "TENANT_PROFILE", allowableValues = "TENANT_PROFILE") @Override public EntityType getEntityType() { return EntityType.TENANT_PROFILE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/UUIDBased.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/UUIDBased.java index b234ee5961..5b52bd0af9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/UUIDBased.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/UUIDBased.java @@ -15,13 +15,12 @@ */ package org.thingsboard.server.common.data.id; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import java.io.Serializable; import java.util.UUID; -@ApiModel +@Schema public abstract class UUIDBased implements HasUUID, Serializable { private static final long serialVersionUID = 1L; @@ -37,7 +36,7 @@ public abstract class UUIDBased implements HasUUID, Serializable { this.id = id; } - @ApiModelProperty(position = 1, required = true, value = "string", example = "784f394c-42b6-435a-983c-b7beff2784f9") + @Schema(required = true, description = "string", example = "784f394c-42b6-435a-983c-b7beff2784f9") public UUID getId() { return id; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java index 999e762a12..4053ada987 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -33,7 +33,7 @@ public class UserId extends UUIDBased implements EntityId { return new UserId(UUID.fromString(userId)); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "USER", allowableValues = "USER") + @Schema(required = true, description = "string", example = "USER", allowableValues = "USER") @Override public EntityType getEntityType() { return EntityType.USER; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetTypeId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetTypeId.java index ff5fe2b62f..3dfef42d57 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetTypeId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetTypeId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -31,7 +31,7 @@ public final class WidgetTypeId extends UUIDBased implements EntityId { super(id); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "WIDGET_TYPE", allowableValues = "WIDGET_TYPE") + @Schema(required = true, description = "string", example = "WIDGET_TYPE", allowableValues = "WIDGET_TYPE") @Override public EntityType getEntityType() { return EntityType.WIDGET_TYPE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetsBundleId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetsBundleId.java index b6e6d2cc00..46509c1fe4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetsBundleId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/WidgetsBundleId.java @@ -17,7 +17,7 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.EntityType; import java.util.UUID; @@ -31,7 +31,7 @@ public final class WidgetsBundleId extends UUIDBased implements EntityId { super(id); } - @ApiModelProperty(position = 2, required = true, value = "string", example = "WIDGETS_BUNDLE", allowableValues = "WIDGETS_BUNDLE") + @Schema(required = true, description = "string", example = "WIDGETS_BUNDLE", allowableValues = "WIDGETS_BUNDLE") @Override public EntityType getEntityType() { return EntityType.WIDGETS_BUNDLE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mInstance.java b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mInstance.java index 382dca5415..7614501c56 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mInstance.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mInstance.java @@ -15,16 +15,15 @@ */ package org.thingsboard.server.common.data.lwm2m; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class LwM2mInstance { - @ApiModelProperty(position = 1, value = "LwM2M Instance id.", example = "0") + @Schema(description = "LwM2M Instance id.", example = "0") int id; - @ApiModelProperty(position = 2, value = "LwM2M Resource observe.") + @Schema(description = "LwM2M Resource observe.") LwM2mResourceObserve[] resources; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mObject.java b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mObject.java index 18de593227..44165bccd1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mObject.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mObject.java @@ -15,23 +15,22 @@ */ package org.thingsboard.server.common.data.lwm2m; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class LwM2mObject { - @ApiModelProperty(position = 1, value = "LwM2M Object id.", example = "19") + @Schema(description = "LwM2M Object id.", example = "19") int id; - @ApiModelProperty(position = 2, value = "LwM2M Object key id.", example = "19_1.0") + @Schema(description = "LwM2M Object key id.", example = "19_1.0") String keyId; - @ApiModelProperty(position = 3, value = "LwM2M Object name.", example = "BinaryAppDataContainer") + @Schema(description = "LwM2M Object name.", example = "BinaryAppDataContainer") String name; - @ApiModelProperty(position = 4, value = "LwM2M Object multiple.", example = "true") + @Schema(description = "LwM2M Object multiple.", example = "true") boolean multiple; - @ApiModelProperty(position = 5, value = "LwM2M Object mandatory.", example = "false") + @Schema(description = "LwM2M Object mandatory.", example = "false") boolean mandatory; - @ApiModelProperty(position = 6, value = "LwM2M Object instances.") + @Schema(description = "LwM2M Object instances.") LwM2mInstance [] instances; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResourceObserve.java b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResourceObserve.java index a40f422ad0..611d3ca66a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResourceObserve.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/lwm2m/LwM2mResourceObserve.java @@ -15,28 +15,27 @@ */ package org.thingsboard.server.common.data.lwm2m; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import java.util.stream.Stream; -@ApiModel +@Schema @Data @AllArgsConstructor public class LwM2mResourceObserve { - @ApiModelProperty(position = 1, value = "LwM2M Resource Observe id.", example = "0") + @Schema(description = "LwM2M Resource Observe id.", example = "0") int id; - @ApiModelProperty(position = 2, value = "LwM2M Resource Observe name.", example = "Data") + @Schema(description = "LwM2M Resource Observe name.", example = "Data") String name; - @ApiModelProperty(position = 3, value = "LwM2M Resource Observe observe.", example = "false") + @Schema(description = "LwM2M Resource Observe observe.", example = "false") boolean observe; - @ApiModelProperty(position = 4, value = "LwM2M Resource Observe attribute.", example = "false") + @Schema(description = "LwM2M Resource Observe attribute.", example = "false") boolean attribute; - @ApiModelProperty(position = 5, value = "LwM2M Resource Observe telemetry.", example = "false") + @Schema(description = "LwM2M Resource Observe telemetry.", example = "false") boolean telemetry; - @ApiModelProperty(position = 6, value = "LwM2M Resource Observe key name.", example = "data") + @Schema(description = "LwM2M Resource Observe key name.", example = "data") String keyName; public LwM2mResourceObserve(int id, String name, boolean observe, boolean attribute, boolean telemetry) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2BasicMapperConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2BasicMapperConfig.java index ba86a5781c..96ab5ccbed 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2BasicMapperConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2BasicMapperConfig.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.oauth2; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; @@ -27,31 +26,31 @@ import org.thingsboard.server.common.data.validation.Length; @EqualsAndHashCode @Data @ToString -@ApiModel +@Schema public class OAuth2BasicMapperConfig { @Length(fieldName = "emailAttributeKey", max = 31) - @ApiModelProperty(value = "Email attribute key of OAuth2 principal attributes. " + + @Schema(description = "Email attribute key of OAuth2 principal attributes. " + "Must be specified for BASIC mapper type and cannot be specified for GITHUB type") private final String emailAttributeKey; @Length(fieldName = "firstNameAttributeKey", max = 31) - @ApiModelProperty(value = "First name attribute key") + @Schema(description = "First name attribute key") private final String firstNameAttributeKey; @Length(fieldName = "lastNameAttributeKey", max = 31) - @ApiModelProperty(value = "Last name attribute key") + @Schema(description = "Last name attribute key") private final String lastNameAttributeKey; - @ApiModelProperty(value = "Tenant naming strategy. For DOMAIN type, domain for tenant name will be taken from the email (substring before '@')", required = true) + @Schema(description = "Tenant naming strategy. For DOMAIN type, domain for tenant name will be taken from the email (substring before '@')", required = true) private final TenantNameStrategyType tenantNameStrategy; @Length(fieldName = "tenantNamePattern") - @ApiModelProperty(value = "Tenant name pattern for CUSTOM naming strategy. " + + @Schema(description = "Tenant name pattern for CUSTOM naming strategy. " + "OAuth2 attributes in the pattern can be used by enclosing attribute key in '%{' and '}'", example = "%{email}") private final String tenantNamePattern; @Length(fieldName = "customerNamePattern") - @ApiModelProperty(value = "Customer name pattern. When creating a user on the first OAuth2 log in, if specified, " + + @Schema(description = "Customer name pattern. When creating a user on the first OAuth2 log in, if specified, " + "customer name will be used to create or find existing customer in the platform and assign customerId to the user") private final String customerNamePattern; @Length(fieldName = "defaultDashboardName") - @ApiModelProperty(value = "Name of the tenant's dashboard to set as default dashboard for newly created user") + @Schema(description = "Name of the tenant's dashboard to set as default dashboard for newly created user") private final String defaultDashboardName; - @ApiModelProperty(value = "Whether default dashboard should be open in full screen") + @Schema(description = "Whether default dashboard should be open in full screen") private final boolean alwaysFullScreen; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java index c7770cca0f..be8d2c9d54 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientInfo.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.oauth2; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -26,14 +25,14 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor -@ApiModel +@Schema public class OAuth2ClientInfo { - @ApiModelProperty(value = "OAuth2 client name", example = "GitHub") + @Schema(description = "OAuth2 client name", example = "GitHub") private String name; - @ApiModelProperty(value = "Name of the icon, displayed on OAuth2 log in button", example = "github-logo") + @Schema(description = "Name of the icon, displayed on OAuth2 log in button", example = "github-logo") private String icon; - @ApiModelProperty(value = "URI for OAuth2 log in. On HTTP GET request to this URI, it redirects to the OAuth2 provider page", + @Schema(description = "URI for OAuth2 log in. On HTTP GET request to this URI, it redirects to the OAuth2 provider page", example = "/oauth2/authorization/8352f191-2b4d-11ec-9ed1-cbf57c026ecc") private String url; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationTemplate.java index 57945bf93e..cf56547e4d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationTemplate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ClientRegistrationTemplate.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.oauth2; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -33,45 +32,45 @@ import java.util.List; @Data @ToString @NoArgsConstructor -@ApiModel +@Schema public class OAuth2ClientRegistrationTemplate extends BaseDataWithAdditionalInfo implements HasName { @Length(fieldName = "providerId") - @ApiModelProperty(value = "OAuth2 provider identifier (e.g. its name)", required = true) + @Schema(description = "OAuth2 provider identifier (e.g. its name)", required = true) private String providerId; @Valid - @ApiModelProperty(value = "Default config for mapping OAuth2 log in response to platform entities") + @Schema(description = "Default config for mapping OAuth2 log in response to platform entities") private OAuth2MapperConfig mapperConfig; @Length(fieldName = "authorizationUri") - @ApiModelProperty(value = "Default authorization URI of the OAuth2 provider") + @Schema(description = "Default authorization URI of the OAuth2 provider") private String authorizationUri; @Length(fieldName = "accessTokenUri") - @ApiModelProperty(value = "Default access token URI of the OAuth2 provider") + @Schema(description = "Default access token URI of the OAuth2 provider") private String accessTokenUri; - @ApiModelProperty(value = "Default OAuth scopes that will be requested from OAuth2 platform") + @Schema(description = "Default OAuth scopes that will be requested from OAuth2 platform") private List scope; @Length(fieldName = "userInfoUri") - @ApiModelProperty(value = "Default user info URI of the OAuth2 provider") + @Schema(description = "Default user info URI of the OAuth2 provider") private String userInfoUri; @Length(fieldName = "userNameAttributeName") - @ApiModelProperty(value = "Default name of the username attribute in OAuth2 provider log in response") + @Schema(description = "Default name of the username attribute in OAuth2 provider log in response") private String userNameAttributeName; @Length(fieldName = "jwkSetUri") - @ApiModelProperty(value = "Default JSON Web Key URI of the OAuth2 provider") + @Schema(description = "Default JSON Web Key URI of the OAuth2 provider") private String jwkSetUri; @Length(fieldName = "clientAuthenticationMethod") - @ApiModelProperty(value = "Default client authentication method to use: 'BASIC' or 'POST'") + @Schema(description = "Default client authentication method to use: 'BASIC' or 'POST'") private String clientAuthenticationMethod; - @ApiModelProperty(value = "Comment for OAuth2 provider") + @Schema(description = "Comment for OAuth2 provider") private String comment; @Length(fieldName = "loginButtonIcon") - @ApiModelProperty(value = "Default log in button icon for OAuth2 provider") + @Schema(description = "Default log in button icon for OAuth2 provider") private String loginButtonIcon; @Length(fieldName = "loginButtonLabel") - @ApiModelProperty(value = "Default OAuth2 provider label") + @Schema(description = "Default OAuth2 provider label") private String loginButtonLabel; @Length(fieldName = "helpLink") - @ApiModelProperty(value = "Help link for OAuth2 provider") + @Schema(description = "Help link for OAuth2 provider") private String helpLink; public OAuth2ClientRegistrationTemplate(OAuth2ClientRegistrationTemplate clientRegistrationTemplate) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2DomainInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2DomainInfo.java index 06a175b441..71108ef137 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2DomainInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2DomainInfo.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.oauth2; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -30,10 +29,10 @@ import lombok.ToString; @NoArgsConstructor @AllArgsConstructor @Builder -@ApiModel +@Schema public class OAuth2DomainInfo { - @ApiModelProperty(value = "Domain scheme. Mixed scheme means than both HTTP and HTTPS are going to be used", required = true) + @Schema(description = "Domain scheme. Mixed scheme means than both HTTP and HTTPS are going to be used", required = true) private SchemeType scheme; - @ApiModelProperty(value = "Domain name. Cannot be empty", required = true) + @Schema(description = "Domain name. Cannot be empty", required = true) private String name; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Info.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Info.java index 30531c3241..5c292ef23e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Info.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Info.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.oauth2; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -32,10 +31,10 @@ import java.util.List; @Builder(toBuilder = true) @NoArgsConstructor @AllArgsConstructor -@ApiModel +@Schema public class OAuth2Info { - @ApiModelProperty("Whether OAuth2 settings are enabled or not") + @Schema(description = "Whether OAuth2 settings are enabled or not") private boolean enabled; - @ApiModelProperty(value = "List of configured OAuth2 clients. Cannot contain null values", required = true) + @Schema(description = "List of configured OAuth2 clients. Cannot contain null values", required = true) private List oauth2ParamsInfos; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java index 89c8bcaa07..0896734d84 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MapperConfig.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data.oauth2; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; @@ -28,16 +28,16 @@ import jakarta.validation.Valid; @Data @ToString public class OAuth2MapperConfig { - @ApiModelProperty(value = "Whether user should be created if not yet present on the platform after successful authentication") + @Schema(description = "Whether user should be created if not yet present on the platform after successful authentication") private boolean allowUserCreation; - @ApiModelProperty(value = "Whether user credentials should be activated when user is created after successful authentication") + @Schema(description = "Whether user credentials should be activated when user is created after successful authentication") private boolean activateUser; - @ApiModelProperty(value = "Type of OAuth2 mapper. Depending on this param, different mapper config fields must be specified", required = true) + @Schema(description = "Type of OAuth2 mapper. Depending on this param, different mapper config fields must be specified", required = true) private MapperType type; @Valid - @ApiModelProperty(value = "Mapper config for BASIC and GITHUB mapper types") + @Schema(description = "Mapper config for BASIC and GITHUB mapper types") private OAuth2BasicMapperConfig basic; @Valid - @ApiModelProperty(value = "Mapper config for CUSTOM mapper type") + @Schema(description = "Mapper config for CUSTOM mapper type") private OAuth2CustomMapperConfig custom; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MobileInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MobileInfo.java index 2f6717adfc..f8999fa44b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MobileInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2MobileInfo.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.oauth2; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -30,10 +29,10 @@ import lombok.ToString; @NoArgsConstructor @AllArgsConstructor @Builder -@ApiModel +@Schema public class OAuth2MobileInfo { - @ApiModelProperty(value = "Application package name. Cannot be empty", required = true) + @Schema(description = "Application package name. Cannot be empty", required = true) private String pkgName; - @ApiModelProperty(value = "Application secret. The length must be at least 16 characters", required = true) + @Schema(description = "Application secret. The length must be at least 16 characters", required = true) private String appSecret; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ParamsInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ParamsInfo.java index 8dcb827d71..9e34a5e598 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ParamsInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2ParamsInfo.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.oauth2; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -32,16 +31,16 @@ import java.util.List; @Builder(toBuilder = true) @NoArgsConstructor @AllArgsConstructor -@ApiModel +@Schema public class OAuth2ParamsInfo { - @ApiModelProperty(value = "List of configured domains where OAuth2 platform will redirect a user after successful " + + @Schema(description = "List of configured domains where OAuth2 platform will redirect a user after successful " + "authentication. Cannot be empty. There have to be only one domain with specific name with scheme type 'MIXED'. " + "Configured domains with the same name must have different scheme types", required = true) private List domainInfos; - @ApiModelProperty(value = "Mobile applications settings. Application package name must be unique within the list", required = true) + @Schema(description = "Mobile applications settings. Application package name must be unique within the list", required = true) private List mobileInfos; - @ApiModelProperty(value = "List of OAuth2 provider settings. Cannot be empty", required = true) + @Schema(description = "List of OAuth2 provider settings. Cannot be empty", required = true) private List clientRegistrations; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2RegistrationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2RegistrationInfo.java index e212585efb..3ccbb72bdb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2RegistrationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2RegistrationInfo.java @@ -16,8 +16,7 @@ package org.thingsboard.server.common.data.oauth2; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -33,34 +32,34 @@ import java.util.List; @NoArgsConstructor @AllArgsConstructor @Builder -@ApiModel +@Schema public class OAuth2RegistrationInfo { - @ApiModelProperty(value = "Config for mapping OAuth2 log in response to platform entities", required = true) + @Schema(description = "Config for mapping OAuth2 log in response to platform entities", required = true) private OAuth2MapperConfig mapperConfig; - @ApiModelProperty(value = "OAuth2 client ID. Cannot be empty", required = true) + @Schema(description = "OAuth2 client ID. Cannot be empty", required = true) private String clientId; - @ApiModelProperty(value = "OAuth2 client secret. Cannot be empty", required = true) + @Schema(description = "OAuth2 client secret. Cannot be empty", required = true) private String clientSecret; - @ApiModelProperty(value = "Authorization URI of the OAuth2 provider. Cannot be empty", required = true) + @Schema(description = "Authorization URI of the OAuth2 provider. Cannot be empty", required = true) private String authorizationUri; - @ApiModelProperty(value = "Access token URI of the OAuth2 provider. Cannot be empty", required = true) + @Schema(description = "Access token URI of the OAuth2 provider. Cannot be empty", required = true) private String accessTokenUri; - @ApiModelProperty(value = "OAuth scopes that will be requested from OAuth2 platform. Cannot be empty", required = true) + @Schema(description = "OAuth scopes that will be requested from OAuth2 platform. Cannot be empty", required = true) private List scope; - @ApiModelProperty(value = "User info URI of the OAuth2 provider") + @Schema(description = "User info URI of the OAuth2 provider") private String userInfoUri; - @ApiModelProperty(value = "Name of the username attribute in OAuth2 provider response. Cannot be empty") + @Schema(description = "Name of the username attribute in OAuth2 provider response. Cannot be empty") private String userNameAttributeName; - @ApiModelProperty(value = "JSON Web Key URI of the OAuth2 provider") + @Schema(description = "JSON Web Key URI of the OAuth2 provider") private String jwkSetUri; - @ApiModelProperty(value = "Client authentication method to use: 'BASIC' or 'POST'. Cannot be empty", required = true) + @Schema(description = "Client authentication method to use: 'BASIC' or 'POST'. Cannot be empty", required = true) private String clientAuthenticationMethod; - @ApiModelProperty(value = "OAuth2 provider label. Cannot be empty", required = true) + @Schema(description = "OAuth2 provider label. Cannot be empty", required = true) private String loginButtonLabel; - @ApiModelProperty(value = "Log in button icon for OAuth2 provider") + @Schema(description = "Log in button icon for OAuth2 provider") private String loginButtonIcon; - @ApiModelProperty(value = "List of platforms for which usage of the OAuth2 client is allowed (empty for all allowed)") + @Schema(description = "List of platforms for which usage of the OAuth2 client is allowed (empty for all allowed)") private List platforms; - @ApiModelProperty(value = "Additional info of OAuth2 client (e.g. providerName)", required = true) + @Schema(description = "Additional info of OAuth2 client (e.g. providerName)", required = true) private JsonNode additionalInfo; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/objects/AttributesEntityView.java b/common/data/src/main/java/org/thingsboard/server/common/data/objects/AttributesEntityView.java index 44f9ab0a2f..b2e71bf947 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/objects/AttributesEntityView.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/objects/AttributesEntityView.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.objects; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.NoArgsConstructor; @@ -28,15 +27,15 @@ import java.util.List; * Created by Victor Basanets on 9/05/2017. */ @Data -@ApiModel +@Schema @NoArgsConstructor public class AttributesEntityView implements Serializable { - @ApiModelProperty(position = 1, required = true, value = "List of client-side attribute keys to expose", example = "currentConfiguration") + @Schema(required = true, description = "List of client-side attribute keys to expose", example = "currentConfiguration") private List cs = new ArrayList<>(); - @ApiModelProperty(position = 3, required = true, value = "List of server-side attribute keys to expose", example = "model") + @Schema(required = true, description = "List of server-side attribute keys to expose", example = "model") private List ss = new ArrayList<>(); - @ApiModelProperty(position = 2, required = true, value = "List of shared attribute keys to expose", example = "targetConfiguration") + @Schema(required = true, description = "List of shared attribute keys to expose", example = "targetConfiguration") private List sh = new ArrayList<>(); public AttributesEntityView(List cs, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/objects/TelemetryEntityView.java b/common/data/src/main/java/org/thingsboard/server/common/data/objects/TelemetryEntityView.java index 2dd115138e..ad538128b7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/objects/TelemetryEntityView.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/objects/TelemetryEntityView.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.objects; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.NoArgsConstructor; @@ -27,14 +26,14 @@ import java.util.List; /** * Created by Victor Basanets on 9/05/2017. */ -@ApiModel +@Schema @Data @NoArgsConstructor public class TelemetryEntityView implements Serializable { - @ApiModelProperty(position = 1, required = true, value = "List of time-series data keys to expose", example = "temperature, humidity") + @Schema(required = true, description = "List of time-series data keys to expose", example = "temperature, humidity") private List timeseries; - @ApiModelProperty(position = 2, required = true, value = "JSON object with attributes to expose") + @Schema(required = true, description = "JSON object with attributes to expose") private AttributesEntityView attributes; public TelemetryEntityView(List timeseries, AttributesEntityView attributes) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java index 2ae94a0064..4f510ebb2b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java @@ -17,15 +17,14 @@ package org.thingsboard.server.common.data.page; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import java.util.Collections; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; -@ApiModel +@Schema public class PageData { private final List data; @@ -48,22 +47,22 @@ public class PageData { this.hasNext = hasNext; } - @ApiModelProperty(position = 1, value = "Array of the entities", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Array of the entities", accessMode = Schema.AccessMode.READ_ONLY) public List getData() { return data; } - @ApiModelProperty(position = 2, value = "Total number of available pages. Calculated based on the 'pageSize' request parameter and total number of entities that match search criteria", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Total number of available pages. Calculated based on the 'pageSize' request parameter and total number of entities that match search criteria", accessMode = Schema.AccessMode.READ_ONLY) public int getTotalPages() { return totalPages; } - @ApiModelProperty(position = 3, value = "Total number of elements in all available pages", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Total number of elements in all available pages", accessMode = Schema.AccessMode.READ_ONLY) public long getTotalElements() { return totalElements; } - @ApiModelProperty(position = 4, value = "'false' value indicates the end of the result set", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "'false' value indicates the end of the result set", accessMode = Schema.AccessMode.READ_ONLY) @JsonProperty("hasNext") public boolean hasNext() { return hasNext; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentDescriptor.java b/common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentDescriptor.java index 1c186f2697..3387f85e6f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentDescriptor.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/plugin/ComponentDescriptor.java @@ -16,8 +16,7 @@ package org.thingsboard.server.common.data.plugin; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -29,27 +28,27 @@ import org.thingsboard.server.common.data.validation.Length; /** * @author Andrew Shvayka */ -@ApiModel +@Schema @ToString public class ComponentDescriptor extends BaseData { private static final long serialVersionUID = 1L; - @ApiModelProperty(position = 3, value = "Type of the Rule Node", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Type of the Rule Node", accessMode = Schema.AccessMode.READ_ONLY) @Getter @Setter private ComponentType type; - @ApiModelProperty(position = 4, value = "Scope of the Rule Node. Always set to 'TENANT', since no rule chains on the 'SYSTEM' level yet.", accessMode = ApiModelProperty.AccessMode.READ_ONLY, allowableValues = "TENANT", example = "TENANT") + @Schema(description = "Scope of the Rule Node. Always set to 'TENANT', since no rule chains on the 'SYSTEM' level yet.", accessMode = Schema.AccessMode.READ_ONLY, allowableValues = "TENANT", example = "TENANT") @Getter @Setter private ComponentScope scope; - @ApiModelProperty(position = 5, value = "Clustering mode of the RuleNode. This mode represents the ability to start Rule Node in multiple microservices.", accessMode = ApiModelProperty.AccessMode.READ_ONLY, allowableValues = "USER_PREFERENCE, ENABLED, SINGLETON", example = "ENABLED") + @Schema(description = "Clustering mode of the RuleNode. This mode represents the ability to start Rule Node in multiple microservices.", accessMode = Schema.AccessMode.READ_ONLY, allowableValues = "USER_PREFERENCE, ENABLED, SINGLETON", example = "ENABLED") @Getter @Setter private ComponentClusteringMode clusteringMode; @Length(fieldName = "name") - @ApiModelProperty(position = 6, value = "Name of the Rule Node. Taken from the @RuleNode annotation.", accessMode = ApiModelProperty.AccessMode.READ_ONLY, example = "Custom Rule Node") + @Schema(description = "Name of the Rule Node. Taken from the @RuleNode annotation.", accessMode = Schema.AccessMode.READ_ONLY, example = "Custom Rule Node") @Getter @Setter private String name; - @ApiModelProperty(position = 7, value = "Full name of the Java class that implements the Rule Engine Node interface.", accessMode = ApiModelProperty.AccessMode.READ_ONLY, example = "com.mycompany.CustomRuleNode") + @Schema(description = "Full name of the Java class that implements the Rule Engine Node interface.", accessMode = Schema.AccessMode.READ_ONLY, example = "com.mycompany.CustomRuleNode") @Getter @Setter private String clazz; - @ApiModelProperty(position = 8, value = "Complex JSON object that represents the Rule Node configuration.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Complex JSON object that represents the Rule Node configuration.", accessMode = Schema.AccessMode.READ_ONLY) @Getter @Setter private transient JsonNode configurationDescriptor; @Length(fieldName = "actions") - @ApiModelProperty(position = 9, value = "Rule Node Actions. Deprecated. Always null.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Rule Node Actions. Deprecated. Always null.", accessMode = Schema.AccessMode.READ_ONLY) @Getter @Setter private String actions; public ComponentDescriptor() { @@ -70,7 +69,7 @@ public class ComponentDescriptor extends BaseData { this.actions = plugin.getActions(); } - @ApiModelProperty(position = 1, value = "JSON object with the descriptor Id. " + + @Schema(description = "JSON object with the descriptor Id. " + "Specify existing descriptor id to update the descriptor. " + "Referencing non-existing descriptor Id will cause error. " + "Omit this field to create new descriptor." ) @@ -79,7 +78,7 @@ public class ComponentDescriptor extends BaseData { return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the descriptor creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the descriptor creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityCountQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityCountQuery.java index 2665abe7e9..e85cbc2fb8 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityCountQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityCountQuery.java @@ -15,14 +15,14 @@ */ package org.thingsboard.server.common.data.query; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.ToString; import java.util.Collections; import java.util.List; -@ApiModel +@Schema @ToString public class EntityCountQuery { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityKey.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityKey.java index f5362dd824..76d90087fe 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityKey.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/EntityKey.java @@ -15,12 +15,12 @@ */ package org.thingsboard.server.common.data.query; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; -@ApiModel +@Schema @Data public class EntityKey implements Serializable { private static final long serialVersionUID = -6421575477523085543L; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/KeyFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/KeyFilter.java index ad5d42e31d..c8999cce2b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/KeyFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/KeyFilter.java @@ -15,12 +15,12 @@ */ package org.thingsboard.server.common.data.query; -import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; -@ApiModel +@Schema @Data public class KeyFilter implements Serializable { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java index fa2d52f3f4..ecde8d82dc 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java @@ -17,8 +17,7 @@ package org.thingsboard.server.common.data.relation; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.BaseDataWithAdditionalInfo; import org.thingsboard.server.common.data.id.EntityId; @@ -27,7 +26,7 @@ import org.thingsboard.server.common.data.validation.Length; import java.io.Serializable; @Slf4j -@ApiModel +@Schema public class EntityRelation implements Serializable { private static final long serialVersionUID = 2807343040519543363L; @@ -73,7 +72,7 @@ public class EntityRelation implements Serializable { this.additionalInfo = entityRelation.getAdditionalInfo(); } - @ApiModelProperty(position = 1, value = "JSON object with [from] Entity Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with [from] Entity Id.", accessMode = Schema.AccessMode.READ_ONLY) public EntityId getFrom() { return from; } @@ -82,7 +81,7 @@ public class EntityRelation implements Serializable { this.from = from; } - @ApiModelProperty(position = 2, value = "JSON object with [to] Entity Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with [to] Entity Id.", accessMode = Schema.AccessMode.READ_ONLY) public EntityId getTo() { return to; } @@ -91,7 +90,7 @@ public class EntityRelation implements Serializable { this.to = to; } - @ApiModelProperty(position = 3, value = "String value of relation type.", example = "Contains") + @Schema(description = "String value of relation type.", example = "Contains") public String getType() { return type; } @@ -100,7 +99,7 @@ public class EntityRelation implements Serializable { this.type = type; } - @ApiModelProperty(position = 4, value = "Represents the type group of the relation.", example = "COMMON") + @Schema(description = "Represents the type group of the relation.", example = "COMMON") public RelationTypeGroup getTypeGroup() { return typeGroup; } @@ -109,7 +108,7 @@ public class EntityRelation implements Serializable { this.typeGroup = typeGroup; } - @ApiModelProperty(position = 5, value = "Additional parameters of the relation", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "Additional parameters of the relation",implementation = com.fasterxml.jackson.databind.JsonNode.class) public JsonNode getAdditionalInfo() { return BaseDataWithAdditionalInfo.getJson(() -> additionalInfo, () -> additionalInfoBytes); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelationInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelationInfo.java index 44acbb6a5f..364d40b062 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelationInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelationInfo.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data.relation; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; public class EntityRelationInfo extends EntityRelation { @@ -32,7 +32,7 @@ public class EntityRelationInfo extends EntityRelation { super(entityRelation); } - @ApiModelProperty(position = 6, value = "Name of the entity for [from] direction.", accessMode = ApiModelProperty.AccessMode.READ_ONLY, example = "A4B72CCDFF33") + @Schema(description = "Name of the entity for [from] direction.", accessMode = Schema.AccessMode.READ_ONLY, example = "A4B72CCDFF33") public String getFromName() { return fromName; } @@ -41,7 +41,7 @@ public class EntityRelationInfo extends EntityRelation { this.fromName = fromName; } - @ApiModelProperty(position = 7, value = "Name of the entity for [to] direction.", accessMode = ApiModelProperty.AccessMode.READ_ONLY, example = "A4B72CCDFF35") + @Schema(description = "Name of the entity for [to] direction.", accessMode = Schema.AccessMode.READ_ONLY, example = "A4B72CCDFF35") public String getToName() { return toName; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelationsQuery.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelationsQuery.java index b3f052d59e..cefd2fa4f4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelationsQuery.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelationsQuery.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.relation; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; @@ -25,12 +24,12 @@ import java.util.List; * Created by ashvayka on 02.05.17. */ @Data -@ApiModel +@Schema public class EntityRelationsQuery { - @ApiModelProperty(position = 2, value = "Main search parameters.") + @Schema(description = "Main search parameters.") private RelationsSearchParameters parameters; - @ApiModelProperty(position = 1, value = "Main filters.") + @Schema(description = "Main filters.") private List filters; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationEntityTypeFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationEntityTypeFilter.java index 80ff4fe874..b8e5e94a19 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationEntityTypeFilter.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationEntityTypeFilter.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.relation; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import org.thingsboard.server.common.data.EntityType; @@ -28,12 +27,12 @@ import java.util.List; */ @Data @AllArgsConstructor -@ApiModel +@Schema public class RelationEntityTypeFilter { - @ApiModelProperty(position = 1, value = "Type of the relation between root entity and other entity (e.g. 'Contains' or 'Manages').", example = "Contains") + @Schema(description = "Type of the relation between root entity and other entity (e.g. 'Contains' or 'Manages').", example = "Contains") private String relationType; - @ApiModelProperty(position = 2, value = "Array of entity types to filter the related entities (e.g. 'DEVICE', 'ASSET').") + @Schema(description = "Array of entity types to filter the related entities (e.g. 'DEVICE', 'ASSET').") private List entityTypes; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java index 23a3a6407c..cfc338ff55 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/RelationsSearchParameters.java @@ -16,8 +16,7 @@ package org.thingsboard.server.common.data.relation; import com.fasterxml.jackson.annotation.JsonIgnore; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import org.thingsboard.server.common.data.EntityType; @@ -29,22 +28,22 @@ import java.util.UUID; /** * Created by ashvayka on 03.05.17. */ -@ApiModel +@Schema @Data @AllArgsConstructor public class RelationsSearchParameters { - @ApiModelProperty(position = 1, value = "Root entity id to start search from.", example = "784f394c-42b6-435a-983c-b7beff2784f9") + @Schema(description = "Root entity id to start search from.", example = "784f394c-42b6-435a-983c-b7beff2784f9") private UUID rootId; - @ApiModelProperty(position = 2, value = "Type of the root entity.") + @Schema(description = "Type of the root entity.") private EntityType rootType; - @ApiModelProperty(position = 3, value = "Type of the root entity.") + @Schema(description = "Type of the root entity.") private EntitySearchDirection direction; - @ApiModelProperty(position = 4, value = "Type of the relation.") + @Schema(description = "Type of the relation.") private RelationTypeGroup relationTypeGroup; - @ApiModelProperty(position = 5, value = "Maximum level of the search depth.") + @Schema(description = "Maximum level of the search depth.") private int maxLevel = 1; - @ApiModelProperty(position = 6, value = "Fetch entities that match the last level of search. Useful to find Devices that are strictly 'maxLevel' relations away from the root entity.") + @Schema(description = "Fetch entities that match the last level of search. Useful to find Devices that are strictly 'maxLevel' relations away from the root entity.") private boolean fetchLastLevelOnly; public RelationsSearchParameters(EntityId entityId, EntitySearchDirection direction, int maxLevel, boolean fetchLastLevelOnly) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rpc/Rpc.java b/common/data/src/main/java/org/thingsboard/server/common/data/rpc/Rpc.java index 154a725761..d764a1fe0b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rpc/Rpc.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rpc/Rpc.java @@ -16,8 +16,7 @@ package org.thingsboard.server.common.data.rpc; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseData; @@ -26,24 +25,24 @@ import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.RpcId; import org.thingsboard.server.common.data.id.TenantId; -@ApiModel +@Schema @Data @EqualsAndHashCode(callSuper = true) public class Rpc extends BaseData implements HasTenantId { - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; - @ApiModelProperty(position = 4, value = "JSON object with Device Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Device Id.", accessMode = Schema.AccessMode.READ_ONLY) private DeviceId deviceId; - @ApiModelProperty(position = 5, value = "Expiration time of the request.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Expiration time of the request.", accessMode = Schema.AccessMode.READ_ONLY) private long expirationTime; - @ApiModelProperty(position = 6, value = "The request body that will be used to send message to device.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "The request body that will be used to send message to device.", accessMode = Schema.AccessMode.READ_ONLY) private JsonNode request; - @ApiModelProperty(position = 7, value = "The response from the device.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "The response from the device.", accessMode = Schema.AccessMode.READ_ONLY) private JsonNode response; - @ApiModelProperty(position = 8, value = "The current status of the RPC call.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "The current status of the RPC call.", accessMode = Schema.AccessMode.READ_ONLY) private RpcStatus status; - @ApiModelProperty(position = 9, value = "Additional info used in the rule engine to process the updates to the RPC state.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Additional info used in the rule engine to process the updates to the RPC state.", accessMode = Schema.AccessMode.READ_ONLY) private JsonNode additionalInfo; public Rpc() { @@ -65,13 +64,13 @@ public class Rpc extends BaseData implements HasTenantId { this.additionalInfo = rpc.getAdditionalInfo(); } - @ApiModelProperty(position = 1, value = "JSON object with the rpc Id. Referencing non-existing rpc Id will cause error.") + @Schema(description = "JSON object with the rpc Id. Referencing non-existing rpc Id will cause error.") @Override public RpcId getId() { return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the rpc creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the rpc creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/DefaultRuleChainCreateRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/DefaultRuleChainCreateRequest.java index 0df8b4e03a..3ab6912824 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/DefaultRuleChainCreateRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/DefaultRuleChainCreateRequest.java @@ -15,21 +15,20 @@ */ package org.thingsboard.server.common.data.rule; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.io.Serializable; -@ApiModel +@Schema @Data @Slf4j public class DefaultRuleChainCreateRequest implements Serializable { private static final long serialVersionUID = 5600333716030561537L; - @ApiModelProperty(position = 1, required = true, value = "Name of the new rule chain", example = "Root Rule Chain") + @Schema(required = true, description = "Name of the new rule chain", example = "Root Rule Chain") private String name; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/NodeConnectionInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/NodeConnectionInfo.java index 4bccbf6366..febf3e29f0 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/NodeConnectionInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/NodeConnectionInfo.java @@ -15,20 +15,19 @@ */ package org.thingsboard.server.common.data.rule; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** * Created by ashvayka on 21.03.18. */ -@ApiModel +@Schema @Data public class NodeConnectionInfo { - @ApiModelProperty(position = 1, required = true, value = "Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'from' part of the connection.") + @Schema(required = true, description = "Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'from' part of the connection.") private int fromIndex; - @ApiModelProperty(position = 2, required = true, value = "Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'to' part of the connection.") + @Schema(required = true, description = "Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'to' part of the connection.") private int toIndex; - @ApiModelProperty(position = 3, required = true, value = "Type of the relation. Typically indicated the result of processing by the 'from' rule node. For example, 'Success' or 'Failure'") + @Schema(required = true, description = "Type of the relation. Typically indicated the result of processing by the 'from' rule node. For example, 'Success' or 'Failure'") private String type; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChain.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChain.java index edb70cefda..9d4099755e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChain.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChain.java @@ -17,8 +17,7 @@ package org.thingsboard.server.common.data.rule; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -32,7 +31,7 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @Data @EqualsAndHashCode(callSuper = true) @Slf4j @@ -40,21 +39,21 @@ public class RuleChain extends BaseDataWithAdditionalInfo implement private static final long serialVersionUID = -5656679015121935465L; - @ApiModelProperty(position = 3, required = true, value = "JSON object with Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; @NoXss @Length(fieldName = "name") - @ApiModelProperty(position = 4, required = true, value = "Rule Chain name", example = "Humidity data processing") + @Schema(required = true, description = "Rule Chain name", example = "Humidity data processing") private String name; - @ApiModelProperty(position = 5, value = "Rule Chain type. 'EDGE' rule chains are processing messages on the edge devices only.", example = "A4B72CCDFF33") + @Schema(description = "Rule Chain type. 'EDGE' rule chains are processing messages on the edge devices only.", example = "A4B72CCDFF33") private RuleChainType type; - @ApiModelProperty(position = 6, value = "JSON object with Rule Chain Id. Pointer to the first rule node that should receive all messages pushed to this rule chain.") + @Schema(description = "JSON object with Rule Chain Id. Pointer to the first rule node that should receive all messages pushed to this rule chain.") private RuleNodeId firstRuleNodeId; - @ApiModelProperty(position = 7, value = "Indicates root rule chain. The root rule chain process messages from all devices and entities by default. User may configure default rule chain per device profile.") + @Schema(description = "Indicates root rule chain. The root rule chain process messages from all devices and entities by default. User may configure default rule chain per device profile.") private boolean root; - @ApiModelProperty(position = 8, value = "Reserved for future usage.") + @Schema(description = "Reserved for future usage.") private boolean debugMode; - @ApiModelProperty(position = 9, value = "Reserved for future usage. The actual list of rule nodes and their relations is stored in the database separately.") + @Schema(description = "Reserved for future usage. The actual list of rule nodes and their relations is stored in the database separately.") private transient JsonNode configuration; private RuleChainId externalId; @@ -86,7 +85,7 @@ public class RuleChain extends BaseDataWithAdditionalInfo implement return name; } - @ApiModelProperty(position = 1, value = "JSON object with the Rule Chain Id. " + + @Schema(description = "JSON object with the Rule Chain Id. " + "Specify this field to update the Rule Chain. " + "Referencing non-existing Rule Chain Id will cause error. " + "Omit this field to create new rule chain." ) @@ -95,7 +94,7 @@ public class RuleChain extends BaseDataWithAdditionalInfo implement return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the rule chain creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the rule chain creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainConnectionInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainConnectionInfo.java index edd22564f1..87a7dde0ca 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainConnectionInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainConnectionInfo.java @@ -16,23 +16,22 @@ package org.thingsboard.server.common.data.rule; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.RuleChainId; /** * Created by ashvayka on 21.03.18. */ -@ApiModel +@Schema @Data public class RuleChainConnectionInfo { - @ApiModelProperty(position = 1, required = true, value = "Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'from' part of the connection.") + @Schema(required = true, description = "Index of rule node in the 'nodes' array of the RuleChainMetaData. Indicates the 'from' part of the connection.") private int fromIndex; - @ApiModelProperty(position = 2, required = true, value = "JSON object with the Rule Chain Id.") + @Schema(required = true, description = "JSON object with the Rule Chain Id.") private RuleChainId targetRuleChainId; - @ApiModelProperty(position = 3, required = true, value = "JSON object with the additional information about the connection.") + @Schema(required = true, description = "JSON object with the additional information about the connection.") private JsonNode additionalInfo; - @ApiModelProperty(position = 4, required = true, value = "Type of the relation. Typically indicated the result of processing by the 'from' rule node. For example, 'Success' or 'Failure'") + @Schema(required = true, description = "Type of the relation. Typically indicated the result of processing by the 'from' rule node. For example, 'Success' or 'Failure'") private String type; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainData.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainData.java index ee53811ce1..74aaaa2c12 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainData.java @@ -15,18 +15,17 @@ */ package org.thingsboard.server.common.data.rule; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; -@ApiModel +@Schema @Data public class RuleChainData { - @ApiModelProperty(position = 1, required = true, value = "List of the Rule Chain objects.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "List of the Rule Chain objects.", accessMode = Schema.AccessMode.READ_ONLY) List ruleChains; - @ApiModelProperty(position = 2, required = true, value = "List of the Rule Chain metadata objects.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "List of the Rule Chain metadata objects.", accessMode = Schema.AccessMode.READ_ONLY) List metadata; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainMetaData.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainMetaData.java index 6ebdeed1dc..79d2f75254 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainMetaData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainMetaData.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.rule; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.RuleChainId; @@ -26,23 +25,23 @@ import java.util.List; /** * Created by igor on 3/13/18. */ -@ApiModel +@Schema @Data public class RuleChainMetaData { - @ApiModelProperty(position = 1, required = true, value = "JSON object with Rule Chain Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "JSON object with Rule Chain Id.", accessMode = Schema.AccessMode.READ_ONLY) private RuleChainId ruleChainId; - @ApiModelProperty(position = 2, required = true, value = "Index of the first rule node in the 'nodes' list") + @Schema(required = true, description = "Index of the first rule node in the 'nodes' list") private Integer firstNodeIndex; - @ApiModelProperty(position = 3, required = true, value = "List of rule node JSON objects") + @Schema(required = true, description = "List of rule node JSON objects") private List nodes; - @ApiModelProperty(position = 4, required = true, value = "List of JSON objects that represent connections between rule nodes") + @Schema(required = true, description = "List of JSON objects that represent connections between rule nodes") private List connections; - @ApiModelProperty(position = 5, required = true, value = "List of JSON objects that represent connections between rule nodes and other rule chains.") + @Schema(required = true, description = "List of JSON objects that represent connections between rule nodes and other rule chains.") private List ruleChainConnections; public void addConnectionInfo(int fromIndex, int toIndex, String type) { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainOutputLabelsUsage.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainOutputLabelsUsage.java index 7a2b2c5b8d..f148aaa9f4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainOutputLabelsUsage.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleChainOutputLabelsUsage.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.rule; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.id.RuleChainId; @@ -24,21 +23,21 @@ import org.thingsboard.server.common.data.id.RuleNodeId; import java.util.Set; -@ApiModel +@Schema @Data @Slf4j public class RuleChainOutputLabelsUsage { - @ApiModelProperty(position = 1, required = true, value = "Rule Chain Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "Rule Chain Id", accessMode = Schema.AccessMode.READ_ONLY) private RuleChainId ruleChainId; - @ApiModelProperty(position = 2, required = true, value = "Rule Node Id", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "Rule Node Id", accessMode = Schema.AccessMode.READ_ONLY) private RuleNodeId ruleNodeId; - @ApiModelProperty(position = 3, required = true, value = "Rule Chain Name", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "Rule Chain Name", accessMode = Schema.AccessMode.READ_ONLY) private String ruleChainName; - @ApiModelProperty(position = 4, required = true, value = "Rule Node Name", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "Rule Node Name", accessMode = Schema.AccessMode.READ_ONLY) private String ruleNodeName; - @ApiModelProperty(position = 5, required = true, value = "Output labels", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(required = true, description = "Output labels", accessMode = Schema.AccessMode.READ_ONLY) private Set labels; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNode.java b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNode.java index 16a127e48a..1926bb8c3c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNode.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleNode.java @@ -17,8 +17,7 @@ package org.thingsboard.server.common.data.rule; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.extern.slf4j.Slf4j; @@ -29,7 +28,7 @@ import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @Data @EqualsAndHashCode(callSuper = true) @Slf4j @@ -37,20 +36,20 @@ public class RuleNode extends BaseDataWithAdditionalInfo implements private static final long serialVersionUID = -5656679015121235465L; - @ApiModelProperty(position = 3, value = "JSON object with the Rule Chain Id. ", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with the Rule Chain Id. ", accessMode = Schema.AccessMode.READ_ONLY) private RuleChainId ruleChainId; @Length(fieldName = "type") - @ApiModelProperty(position = 4, value = "Full Java Class Name of the rule node implementation. ", example = "com.mycompany.iot.rule.engine.ProcessingNode") + @Schema(description = "Full Java Class Name of the rule node implementation. ", example = "com.mycompany.iot.rule.engine.ProcessingNode") private String type; @NoXss @Length(fieldName = "name") - @ApiModelProperty(position = 5, value = "User defined name of the rule node. Used on UI and for logging. ", example = "Process sensor reading") + @Schema(description = "User defined name of the rule node. Used on UI and for logging. ", example = "Process sensor reading") private String name; - @ApiModelProperty(position = 6, value = "Enable/disable debug. ", example = "false") + @Schema(description = "Enable/disable debug. ", example = "false") private boolean debugMode; - @ApiModelProperty(position = 7, value = "Enable/disable singleton mode. ", example = "false") + @Schema(description = "Enable/disable singleton mode. ", example = "false") private boolean singletonMode; - @ApiModelProperty(position = 8, value = "JSON with the rule node configuration. Structure depends on the rule node implementation.", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "JSON with the rule node configuration. Structure depends on the rule node implementation.",implementation = com.fasterxml.jackson.databind.JsonNode.class) private transient JsonNode configuration; @JsonIgnore private byte[] configurationBytes; @@ -89,7 +88,7 @@ public class RuleNode extends BaseDataWithAdditionalInfo implements setJson(data, json -> this.configuration = json, bytes -> this.configurationBytes = bytes); } - @ApiModelProperty(position = 1, value = "JSON object with the Rule Node Id. " + + @Schema(description = "JSON object with the Rule Node Id. " + "Specify this field to update the Rule Node. " + "Referencing non-existing Rule Node Id will cause error. " + "Omit this field to create new rule node." ) @@ -98,13 +97,13 @@ public class RuleNode extends BaseDataWithAdditionalInfo implements return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the rule node creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the rule node creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 8, value = "Additional parameters of the rule node. Contains 'layoutX' and 'layoutY' properties for visualization.", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "Additional parameters of the rule node. Contains 'layoutX' and 'layoutY' properties for visualization.",implementation = com.fasterxml.jackson.databind.JsonNode.class) @Override public JsonNode getAdditionalInfo() { return super.getAdditionalInfo(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/DeviceCredentials.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/DeviceCredentials.java index e12aa43cbc..cdd5950fbb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/DeviceCredentials.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/DeviceCredentials.java @@ -15,14 +15,13 @@ */ package org.thingsboard.server.common.data.security; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.id.DeviceCredentialsId; import org.thingsboard.server.common.data.id.DeviceId; -@ApiModel +@Schema @EqualsAndHashCode(callSuper = true) public class DeviceCredentials extends BaseData implements DeviceCredentialsFilter { @@ -48,7 +47,7 @@ public class DeviceCredentials extends BaseData implements this.credentialsValue = deviceCredentials.getCredentialsValue(); } - @ApiModelProperty(position = 1, required = true, accessMode = ApiModelProperty.AccessMode.READ_ONLY, value = "The Id is automatically generated during device creation. " + + @Schema(required = true, accessMode = Schema.AccessMode.READ_ONLY, description = "The Id is automatically generated during device creation. " + "Use 'getDeviceCredentialsByDeviceId' to obtain the id based on device id. " + "Use 'updateDeviceCredentials' to update device credentials. ", example = "784f394c-42b6-435a-983c-b7beff2784f9") @Override @@ -56,13 +55,13 @@ public class DeviceCredentials extends BaseData implements return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the device credentials creation, in milliseconds", example = "1609459200000") + @Schema(description = "Timestamp of the device credentials creation, in milliseconds", example = "1609459200000") @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 3, required = true, value = "JSON object with the device Id.") + @Schema(required = true, description = "JSON object with the device Id.") public DeviceId getDeviceId() { return deviceId; } @@ -71,7 +70,7 @@ public class DeviceCredentials extends BaseData implements this.deviceId = deviceId; } - @ApiModelProperty(position = 4, value = "Type of the credentials", allowableValues="ACCESS_TOKEN, X509_CERTIFICATE, MQTT_BASIC, LWM2M_CREDENTIALS") + @Schema(description = "Type of the credentials", allowableValues ="ACCESS_TOKEN, X509_CERTIFICATE, MQTT_BASIC, LWM2M_CREDENTIALS") @Override public DeviceCredentialsType getCredentialsType() { return credentialsType; @@ -81,7 +80,7 @@ public class DeviceCredentials extends BaseData implements this.credentialsType = credentialsType; } - @ApiModelProperty(position = 5, required = true, value = "Unique Credentials Id per platform instance. " + + @Schema(required = true, description = "Unique Credentials Id per platform instance. " + "Used to lookup credentials from the database. " + "By default, new access token for your device. " + "Depends on the type of the credentials." @@ -95,7 +94,7 @@ public class DeviceCredentials extends BaseData implements this.credentialsId = credentialsId; } - @ApiModelProperty(position = 6, value = "Value of the credentials. " + + @Schema(description = "Value of the credentials. " + "Null in case of ACCESS_TOKEN credentials type. Base64 value in case of X509_CERTIFICATE. " + "Complex object in case of MQTT_BASIC and LWM2M_CREDENTIALS", example = "Null in case of ACCESS_TOKEN. See model definition.") public String getCredentialsValue() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/JwtPair.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/JwtPair.java index 62f15499e3..af2962f314 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/JwtPair.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/JwtPair.java @@ -15,20 +15,19 @@ */ package org.thingsboard.server.common.data.security.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.NoArgsConstructor; import org.thingsboard.server.common.data.security.Authority; -@ApiModel(value = "JWT Pair") +@Schema(description = "JWT Pair") @Data @NoArgsConstructor public class JwtPair { - @ApiModelProperty(position = 1, value = "The JWT Access Token. Used to perform API calls.", example = "AAB254FF67D..") + @Schema(description = "The JWT Access Token. Used to perform API calls.", example = "AAB254FF67D..") private String token; - @ApiModelProperty(position = 1, value = "The JWT Refresh Token. Used to get new JWT Access Token if old one has expired.", example = "AAB254FF67D..") + @Schema(description = "The JWT Refresh Token. Used to get new JWT Access Token if old one has expired.", example = "AAB254FF67D..") private String refreshToken; private Authority scope; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/JwtSettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/JwtSettings.java index 33bbca468b..53c0096a22 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/JwtSettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/JwtSettings.java @@ -15,13 +15,12 @@ */ package org.thingsboard.server.common.data.security.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -@ApiModel(value = "JWT Settings") +@Schema(description = "JWT Settings") @AllArgsConstructor @NoArgsConstructor @Data @@ -30,26 +29,26 @@ public class JwtSettings { /** * {@link JwtToken} will expire after this time. */ - @ApiModelProperty(position = 1, value = "The JWT will expire after seconds.", example = "9000") + @Schema(description = "The JWT will expire after seconds.", example = "9000") private Integer tokenExpirationTime; /** * {@link JwtToken} can be refreshed during this timeframe. */ - @ApiModelProperty(position = 2, value = "The JWT can be refreshed during seconds.", example = "604800") + @Schema(description = "The JWT can be refreshed during seconds.", example = "604800") private Integer refreshTokenExpTime; /** * Token issuer. */ - @ApiModelProperty(position = 3, value = "The JWT issuer.", example = "thingsboard.io") + @Schema(description = "The JWT issuer.", example = "thingsboard.io") private String tokenIssuer; /** * Key is used to sign {@link JwtToken}. * Base64 encoded */ - @ApiModelProperty(position = 4, value = "The JWT key is used to sing token. Base64 encoded.", example = "cTU4WnNqemI2aU5wbWVjdm1vYXRzanhjNHRUcXliMjE=") + @Schema(description = "The JWT key is used to sing token. Base64 encoded.", example = "cTU4WnNqemI2aU5wbWVjdm1vYXRzanhjNHRUcXliMjE=") private String tokenSigningKey; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java index 4c19b1fa5d..bdfbf975ad 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java @@ -15,22 +15,21 @@ */ package org.thingsboard.server.common.data.security.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; -@ApiModel +@Schema @Data public class SecuritySettings implements Serializable { private static final long serialVersionUID = -1307613974597312465L; - @ApiModelProperty(position = 1, value = "The user password policy object." ) + @Schema(description = "The user password policy object." ) private UserPasswordPolicy passwordPolicy; - @ApiModelProperty(position = 2, value = "Maximum number of failed login attempts allowed before user account is locked." ) + @Schema(description = "Maximum number of failed login attempts allowed before user account is locked." ) private Integer maxFailedLoginAttempts; - @ApiModelProperty(position = 3, value = "Email to use for notifications about locked users." ) + @Schema(description = "Email to use for notifications about locked users." ) private String userLockoutNotificationEmail; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/UserPasswordPolicy.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/UserPasswordPolicy.java index 881af89e27..d94183ba02 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/UserPasswordPolicy.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/UserPasswordPolicy.java @@ -15,32 +15,31 @@ */ package org.thingsboard.server.common.data.security.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; -@ApiModel +@Schema @Data public class UserPasswordPolicy implements Serializable { - @ApiModelProperty(position = 1, value = "Minimum number of symbols in the password." ) + @Schema(description = "Minimum number of symbols in the password." ) private Integer minimumLength; - @ApiModelProperty(position = 1, value = "Minimum number of uppercase letters in the password." ) + @Schema(description = "Minimum number of uppercase letters in the password." ) private Integer minimumUppercaseLetters; - @ApiModelProperty(position = 1, value = "Minimum number of lowercase letters in the password." ) + @Schema(description = "Minimum number of lowercase letters in the password." ) private Integer minimumLowercaseLetters; - @ApiModelProperty(position = 1, value = "Minimum number of digits in the password." ) + @Schema(description = "Minimum number of digits in the password." ) private Integer minimumDigits; - @ApiModelProperty(position = 1, value = "Minimum number of special in the password." ) + @Schema(description = "Minimum number of special in the password." ) private Integer minimumSpecialCharacters; - @ApiModelProperty(position = 1, value = "Allow whitespaces") + @Schema(description = "Allow whitespaces") private Boolean allowWhitespaces = true; - @ApiModelProperty(position = 1, value = "Password expiration period (days). Force expiration of the password." ) + @Schema(description = "Password expiration period (days). Force expiration of the password." ) private Integer passwordExpirationPeriodDays; - @ApiModelProperty(position = 1, value = "Password reuse frequency (days). Disallow to use the same password for the defined number of days" ) + @Schema(description = "Password reuse frequency (days). Disallow to use the same password for the defined number of days" ) private Integer passwordReuseFrequencyDays; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/settings/AbstractUserDashboardInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/settings/AbstractUserDashboardInfo.java index ce214cb603..21ab795f1d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/settings/AbstractUserDashboardInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/settings/AbstractUserDashboardInfo.java @@ -15,23 +15,22 @@ */ package org.thingsboard.server.common.data.settings; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.HasTitle; import java.io.Serializable; import java.util.UUID; -@ApiModel +@Schema @Data public abstract class AbstractUserDashboardInfo implements HasTitle, Serializable { private static final long serialVersionUID = -6461562426034242608L; - @ApiModelProperty(position = 1, value = "JSON object with Dashboard id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Dashboard id.", accessMode = Schema.AccessMode.READ_ONLY) private UUID id; - @ApiModelProperty(position = 2, value = "Title of the dashboard.") + @Schema(description = "Title of the dashboard.") private String title; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/settings/LastVisitedDashboardInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/settings/LastVisitedDashboardInfo.java index e49910eb43..0085f059f0 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/settings/LastVisitedDashboardInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/settings/LastVisitedDashboardInfo.java @@ -15,23 +15,22 @@ */ package org.thingsboard.server.common.data.settings; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; @EqualsAndHashCode(callSuper = true) -@ApiModel +@Schema @Data public class LastVisitedDashboardInfo extends AbstractUserDashboardInfo implements Serializable { private static final long serialVersionUID = -6461562426034242608L; - @ApiModelProperty(position = 3, value = "Starred flag") + @Schema(description = "Starred flag") private boolean starred; - @ApiModelProperty(position = 4, value = "Last visit timestamp") + @Schema(description = "Last visit timestamp") private long lastVisited; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/settings/StarredDashboardInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/settings/StarredDashboardInfo.java index e71404c392..6fba8798e8 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/settings/StarredDashboardInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/settings/StarredDashboardInfo.java @@ -15,20 +15,19 @@ */ package org.thingsboard.server.common.data.settings; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; @EqualsAndHashCode(callSuper = true) -@ApiModel +@Schema @Data public class StarredDashboardInfo extends AbstractUserDashboardInfo implements Serializable { private static final long serialVersionUID = -7830828696329673361L; - @ApiModelProperty(position = 4, value = "Starred timestamp") + @Schema(description = "Starred timestamp") private long starredAt; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserDashboardsInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserDashboardsInfo.java index ef0b01889c..61056a3ae0 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserDashboardsInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserDashboardsInfo.java @@ -15,8 +15,7 @@ */ package org.thingsboard.server.common.data.settings; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; @@ -25,7 +24,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -@ApiModel +@Schema @Data @AllArgsConstructor public class UserDashboardsInfo implements Serializable { @@ -33,10 +32,10 @@ public class UserDashboardsInfo implements Serializable { private static final long serialVersionUID = 2628320657987010348L; public static final UserDashboardsInfo EMPTY = new UserDashboardsInfo(Collections.emptyList(), Collections.emptyList()); - @ApiModelProperty(position = 1, value = "List of last visited dashboards.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "List of last visited dashboards.", accessMode = Schema.AccessMode.READ_ONLY) private List last; - @ApiModelProperty(position = 2, value = "List of starred dashboards.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "List of starred dashboards.", accessMode = Schema.AccessMode.READ_ONLY) private List starred; public UserDashboardsInfo() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserSettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserSettings.java index cf48d9c215..34e80ae1d5 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserSettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/settings/UserSettings.java @@ -17,8 +17,7 @@ package org.thingsboard.server.common.data.settings; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.validation.Length; @@ -29,21 +28,21 @@ import java.io.Serializable; import static org.thingsboard.server.common.data.BaseDataWithAdditionalInfo.getJson; import static org.thingsboard.server.common.data.BaseDataWithAdditionalInfo.setJson; -@ApiModel +@Schema @Data public class UserSettings implements Serializable { private static final long serialVersionUID = 2628320657987010348L; - @ApiModelProperty(position = 1, value = "JSON object with User id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with User id.", accessMode = Schema.AccessMode.READ_ONLY) private UserId userId; - @ApiModelProperty(position = 2, value = "Type of the settings.") + @Schema(description = "Type of the settings.") @NoXss @Length(fieldName = "type", max = 50) private UserSettingsType type; - @ApiModelProperty(position = 3, value = "JSON object with user settings.", dataType = "com.fasterxml.jackson.databind.JsonNode") + @Schema(description = "JSON object with user settings.",implementation = com.fasterxml.jackson.databind.JsonNode.class) @NoXss @Length(fieldName = "settings", max = 100000) private transient JsonNode settings; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java index c153c7a0a0..7c76f01807 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java @@ -15,19 +15,18 @@ */ package org.thingsboard.server.common.data.sms.config; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class AwsSnsSmsProviderConfiguration implements SmsProviderConfiguration { - @ApiModelProperty(position = 1, value = "The AWS SNS Access Key ID.") + @Schema(description = "The AWS SNS Access Key ID.") private String accessKeyId; - @ApiModelProperty(position = 2, value = "The AWS SNS Access Key.") + @Schema(description = "The AWS SNS Access Key.") private String secretAccessKey; - @ApiModelProperty(position = 3, value = "The AWS region.") + @Schema(description = "The AWS region.") private String region; @Override diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmppSmsProviderConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmppSmsProviderConfiguration.java index fddb4016b1..ba1f4461d4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmppSmsProviderConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmppSmsProviderConfiguration.java @@ -15,34 +15,34 @@ */ package org.thingsboard.server.common.data.sms.config; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data public class SmppSmsProviderConfiguration implements SmsProviderConfiguration { - @ApiModelProperty(value = "SMPP version", allowableValues = "3.3, 3.4", required = true) + @Schema(description = "SMPP version", allowableValues = "3.3, 3.4", required = true) private String protocolVersion; - @ApiModelProperty(value = "SMPP host", required = true) + @Schema(description = "SMPP host", required = true) private String host; - @ApiModelProperty(value = "SMPP port", required = true) + @Schema(description = "SMPP port", required = true) private Integer port; - @ApiModelProperty(value = "System ID", required = true) + @Schema(description = "System ID", required = true) private String systemId; - @ApiModelProperty(value = "Password", required = true) + @Schema(description = "Password", required = true) private String password; - @ApiModelProperty(value = "System type", required = false) + @Schema(description = "System type", required = false) private String systemType; - @ApiModelProperty(value = "TX - Transmitter, RX - Receiver, TRX - Transciever. By default TX is used", required = false) + @Schema(description = "TX - Transmitter, RX - Receiver, TRX - Transciever. By default TX is used", required = false) private SmppBindType bindType; - @ApiModelProperty(value = "Service type", required = false) + @Schema(description = "Service type", required = false) private String serviceType; - @ApiModelProperty(value = "Source address", required = false) + @Schema(description = "Source address", required = false) private String sourceAddress; - @ApiModelProperty(value = "Source TON (Type of Number). Needed is source address is set. 5 by default.\n" + + @Schema(description = "Source TON (Type of Number). Needed is source address is set. 5 by default.\n" + "0 - Unknown\n" + "1 - International\n" + "2 - National\n" + @@ -51,7 +51,7 @@ public class SmppSmsProviderConfiguration implements SmsProviderConfiguration { "5 - Alphanumeric\n" + "6 - Abbreviated", required = false) private Byte sourceTon; - @ApiModelProperty(value = "Source NPI (Numbering Plan Identification). Needed is source address is set. 0 by default.\n" + + @Schema(description = "Source NPI (Numbering Plan Identification). Needed is source address is set. 0 by default.\n" + "0 - Unknown\n" + "1 - ISDN/telephone numbering plan (E163/E164)\n" + "3 - Data numbering plan (X.121)\n" + @@ -64,7 +64,7 @@ public class SmppSmsProviderConfiguration implements SmsProviderConfiguration { "18 - WAP Client Id (to be defined by WAP Forum)", required = false) private Byte sourceNpi; - @ApiModelProperty(value = "Destination TON (Type of Number). 5 by default.\n" + + @Schema(description = "Destination TON (Type of Number). 5 by default.\n" + "0 - Unknown\n" + "1 - International\n" + "2 - National\n" + @@ -73,7 +73,7 @@ public class SmppSmsProviderConfiguration implements SmsProviderConfiguration { "5 - Alphanumeric\n" + "6 - Abbreviated", required = false) private Byte destinationTon; - @ApiModelProperty(value = "Destination NPI (Numbering Plan Identification). 0 by default.\n" + + @Schema(description = "Destination NPI (Numbering Plan Identification). 0 by default.\n" + "0 - Unknown\n" + "1 - ISDN/telephone numbering plan (E163/E164)\n" + "3 - Data numbering plan (X.121)\n" + @@ -86,11 +86,11 @@ public class SmppSmsProviderConfiguration implements SmsProviderConfiguration { "18 - WAP Client Id (to be defined by WAP Forum)", required = false) private Byte destinationNpi; - @ApiModelProperty(value = "Address range", required = false) + @Schema(description = "Address range", required = false) private String addressRange; - @ApiModelProperty(allowableValues = "0-10,13-14", - value = "0 - SMSC Default Alphabet (ASCII for short and long code and to GSM for toll-free, used as default)\n" + + @Schema(allowableValues = "0-10,13-14", + description = "0 - SMSC Default Alphabet (ASCII for short and long code and to GSM for toll-free, used as default)\n" + "1 - IA5 (ASCII for short and long code, Latin 9 for toll-free (ISO-8859-9))\n" + "2 - Octet Unspecified (8-bit binary)\n" + "3 - Latin 1 (ISO-8859-1)\n" + diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java index 9a7e5fbfbf..5f792fc869 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java @@ -15,19 +15,18 @@ */ package org.thingsboard.server.common.data.sms.config; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class TestSmsRequest { - @ApiModelProperty(position = 1, value = "The SMS provider configuration") + @Schema(description = "The SMS provider configuration") private SmsProviderConfiguration providerConfiguration; - @ApiModelProperty(position = 2, value = "The phone number or other identifier to specify as a recipient of the SMS.") + @Schema(description = "The phone number or other identifier to specify as a recipient of the SMS.") private String numberTo; - @ApiModelProperty(position = 3, value = "The test message") + @Schema(description = "The test message") private String message; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java index 55cce68703..f9a5fb5c77 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java @@ -15,19 +15,18 @@ */ package org.thingsboard.server.common.data.sms.config; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@ApiModel +@Schema @Data public class TwilioSmsProviderConfiguration implements SmsProviderConfiguration { - @ApiModelProperty(position = 1, value = "Twilio account Sid.") + @Schema(description = "Twilio account Sid.") private String accountSid; - @ApiModelProperty(position = 2, value = "Twilio account Token.") + @Schema(description = "Twilio account Token.") private String accountToken; - @ApiModelProperty(position = 3, value = "The number/id of a sender.") + @Schema(description = "The number/id of a sender.") private String numberFrom; @Override diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/TenantProfileData.java b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/TenantProfileData.java index 1def815cff..67427ac29d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/TenantProfileData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/TenantProfileData.java @@ -15,20 +15,19 @@ */ package org.thingsboard.server.common.data.tenant.profile; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; -@ApiModel +@Schema @Data public class TenantProfileData { - @ApiModelProperty(position = 1, value = "Complex JSON object that contains profile settings: max devices, max assets, rate limits, etc.") + @Schema(description = "Complex JSON object that contains profile settings: max devices, max assets, rate limits, etc.") private TenantProfileConfiguration configuration; - @ApiModelProperty(position = 2, value = "JSON array of queue configuration per tenant profile") + @Schema(description = "JSON array of queue configuration per tenant profile") private List queueConfiguration; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/BaseWidgetType.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/BaseWidgetType.java index a7e9fee82a..7580bca240 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/BaseWidgetType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/BaseWidgetType.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data.widget; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.HasName; @@ -30,19 +30,19 @@ public class BaseWidgetType extends BaseData implements HasName, H private static final long serialVersionUID = 8388684344603660756L; - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; @NoXss @Length(fieldName = "bundleAlias") - @ApiModelProperty(position = 4, value = "Reference to widget bundle", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Reference to widget bundle", accessMode = Schema.AccessMode.READ_ONLY) private String bundleAlias; @NoXss @Length(fieldName = "alias") - @ApiModelProperty(position = 5, value = "Unique alias that is used in dashboards as a reference widget type", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Unique alias that is used in dashboards as a reference widget type", accessMode = Schema.AccessMode.READ_ONLY) private String alias; @NoXss @Length(fieldName = "name") - @ApiModelProperty(position = 6, value = "Widget name used in search and UI", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Widget name used in search and UI", accessMode = Schema.AccessMode.READ_ONLY) private String name; public BaseWidgetType() { @@ -61,7 +61,7 @@ public class BaseWidgetType extends BaseData implements HasName, H this.name = widgetType.getName(); } - @ApiModelProperty(position = 1, value = "JSON object with the Widget Type Id. " + + @Schema(description = "JSON object with the Widget Type Id. " + "Specify this field to update the Widget Type. " + "Referencing non-existing Widget Type Id will cause error. " + "Omit this field to create new Widget Type." ) @@ -70,7 +70,7 @@ public class BaseWidgetType extends BaseData implements HasName, H return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the Widget Type creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the Widget Type creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetType.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetType.java index f726cfb71a..de6421c24c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetType.java @@ -16,14 +16,14 @@ package org.thingsboard.server.common.data.widget; import com.fasterxml.jackson.databind.JsonNode; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.WidgetTypeId; @Data public class WidgetType extends BaseWidgetType { - @ApiModelProperty(position = 7, value = "Complex JSON object that describes the widget type", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Complex JSON object that describes the widget type", accessMode = Schema.AccessMode.READ_ONLY) private transient JsonNode descriptor; public WidgetType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java index e6faece85d..0e06012c70 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeDetails.java @@ -16,7 +16,7 @@ package org.thingsboard.server.common.data.widget; import com.fasterxml.jackson.annotation.JsonPropertyOrder; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.validation.Length; @@ -27,11 +27,11 @@ import org.thingsboard.server.common.data.validation.NoXss; public class WidgetTypeDetails extends WidgetType { @Length(fieldName = "image", max = 1000000) - @ApiModelProperty(position = 8, value = "Base64 encoded thumbnail", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Base64 encoded thumbnail", accessMode = Schema.AccessMode.READ_ONLY) private String image; @NoXss @Length(fieldName = "description") - @ApiModelProperty(position = 9, value = "Description of the widget", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Description of the widget", accessMode = Schema.AccessMode.READ_ONLY) private String description; public WidgetTypeDetails() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java index f5c4abd66d..0ba8761af6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetTypeInfo.java @@ -15,7 +15,7 @@ */ package org.thingsboard.server.common.data.widget; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.validation.NoXss; @@ -23,13 +23,13 @@ import org.thingsboard.server.common.data.validation.NoXss; @Data public class WidgetTypeInfo extends BaseWidgetType { - @ApiModelProperty(position = 7, value = "Base64 encoded widget thumbnail", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Base64 encoded widget thumbnail", accessMode = Schema.AccessMode.READ_ONLY) private String image; @NoXss - @ApiModelProperty(position = 7, value = "Description of the widget type", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Description of the widget type", accessMode = Schema.AccessMode.READ_ONLY) private String description; @NoXss - @ApiModelProperty(position = 8, value = "Type of the widget (timeseries, latest, control, alarm or static)", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Type of the widget (timeseries, latest, control, alarm or static)", accessMode = Schema.AccessMode.READ_ONLY) private String widgetType; public WidgetTypeInfo() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetsBundle.java b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetsBundle.java index 0ceef991ad..c93d08612f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetsBundle.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/widget/WidgetsBundle.java @@ -16,8 +16,7 @@ package org.thingsboard.server.common.data.widget; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -32,7 +31,7 @@ import org.thingsboard.server.common.data.id.WidgetsBundleId; import org.thingsboard.server.common.data.validation.Length; import org.thingsboard.server.common.data.validation.NoXss; -@ApiModel +@Schema @EqualsAndHashCode(callSuper = true) public class WidgetsBundle extends BaseData implements HasName, HasTenantId, ExportableEntity, HasTitle { @@ -40,34 +39,34 @@ public class WidgetsBundle extends BaseData implements HasName, @Getter @Setter - @ApiModelProperty(position = 3, value = "JSON object with Tenant Id.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "JSON object with Tenant Id.", accessMode = Schema.AccessMode.READ_ONLY) private TenantId tenantId; @NoXss @Length(fieldName = "alias") @Getter @Setter - @ApiModelProperty(position = 4, value = "Unique alias that is used in widget types as a reference widget bundle", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Unique alias that is used in widget types as a reference widget bundle", accessMode = Schema.AccessMode.READ_ONLY) private String alias; @NoXss @Length(fieldName = "title") @Getter @Setter - @ApiModelProperty(position = 5, value = "Title used in search and UI", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Title used in search and UI", accessMode = Schema.AccessMode.READ_ONLY) private String title; @Length(fieldName = "image", max = 1000000) @Getter @Setter - @ApiModelProperty(position = 6, value = "Base64 encoded thumbnail", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Base64 encoded thumbnail", accessMode = Schema.AccessMode.READ_ONLY) private String image; @NoXss @Length(fieldName = "description") @Getter @Setter - @ApiModelProperty(position = 7, value = "Description", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Description", accessMode = Schema.AccessMode.READ_ONLY) private String description; @Getter @@ -92,7 +91,7 @@ public class WidgetsBundle extends BaseData implements HasName, this.externalId = widgetsBundle.getExternalId(); } - @ApiModelProperty(position = 1, value = "JSON object with the Widget Bundle Id. " + + @Schema(description = "JSON object with the Widget Bundle Id. " + "Specify this field to update the Widget Bundle. " + "Referencing non-existing Widget Bundle Id will cause error. " + "Omit this field to create new Widget Bundle." ) @@ -101,13 +100,13 @@ public class WidgetsBundle extends BaseData implements HasName, return super.getId(); } - @ApiModelProperty(position = 2, value = "Timestamp of the Widget Bundle creation, in milliseconds", example = "1609459200000", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Timestamp of the Widget Bundle creation, in milliseconds", example = "1609459200000", accessMode = Schema.AccessMode.READ_ONLY) @Override public long getCreatedTime() { return super.getCreatedTime(); } - @ApiModelProperty(position = 3, value = "Same as title of the Widget Bundle. Read-only field. Update the 'title' to change the 'name' of the Widget Bundle.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + @Schema(description = "Same as title of the Widget Bundle. Read-only field. Update the 'title' to change the 'name' of the Widget Bundle.", accessMode = Schema.AccessMode.READ_ONLY) @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getName() { diff --git a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java index cf0b25ec90..a5e4f2af54 100644 --- a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java +++ b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java @@ -17,8 +17,11 @@ package org.thingsboard.server.transport.http; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -127,22 +130,22 @@ public class DeviceApiController implements TbTransportService { @Autowired private HttpTransportContext transportContext; - @ApiOperation(value = "Get attributes (getDeviceAttributes)", - notes = "Returns all attributes that belong to device. " + @Operation(summary = "Get attributes (getDeviceAttributes)", + description = "Returns all attributes that belong to device. " + "Use optional 'clientKeys' and/or 'sharedKeys' parameter to return specific attributes. " + "\n Example of the result: " + MARKDOWN_CODE_BLOCK_START + ATTRIBUTE_PAYLOAD_EXAMPLE + MARKDOWN_CODE_BLOCK_END + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) - @RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.GET, produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + @RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public DeferredResult getDeviceAttributes( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @ApiParam(value = "Comma separated key names for attribute with client scope", required = true, defaultValue = "state") + @Parameter(description = "Comma separated key names for attribute with client scope", required = true , schema = @Schema(defaultValue = "state")) @RequestParam(value = "clientKeys", required = false, defaultValue = "") String clientKeys, - @ApiParam(value = "Comma separated key names for attribute with shared scope", required = true, defaultValue = "configuration") + @Parameter(description = "Comma separated key names for attribute with shared scope", required = true , schema = @Schema(defaultValue = "configuration")) @RequestParam(value = "sharedKeys", required = false, defaultValue = "") String sharedKeys) { DeferredResult responseWriter = new DeferredResult<>(); transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), @@ -165,19 +168,19 @@ public class DeviceApiController implements TbTransportService { return responseWriter; } - @ApiOperation(value = "Post attributes (postDeviceAttributes)", - notes = "Post client attribute updates on behalf of device. " + @Operation(summary = "Post attributes (postDeviceAttributes)", + description = "Post client attribute updates on behalf of device. " + "\n Example of the request: " + MARKDOWN_CODE_BLOCK_START + ATTRIBUTE_PAYLOAD_EXAMPLE + MARKDOWN_CODE_BLOCK_END + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.POST) public DeferredResult postDeviceAttributes( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @ApiParam(value = "JSON with attribute key-value pairs. See API call description for example.") + @Parameter(description = "JSON with attribute key-value pairs. See API call description for example.") @RequestBody String json) { DeferredResult responseWriter = new DeferredResult<>(); transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), @@ -189,15 +192,15 @@ public class DeviceApiController implements TbTransportService { return responseWriter; } - @ApiOperation(value = "Post time-series data (postTelemetry)", - notes = "Post time-series data on behalf of device. " + @Operation(summary = "Post time-series data (postTelemetry)", + description = "Post time-series data on behalf of device. " + "\n Example of the request: " + TS_PAYLOAD + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @RequestMapping(value = "/{deviceToken}/telemetry", method = RequestMethod.POST) public DeferredResult postTelemetry( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, @RequestBody String json, HttpServletRequest request) { DeferredResult responseWriter = new DeferredResult(); @@ -210,8 +213,8 @@ public class DeviceApiController implements TbTransportService { return responseWriter; } - @ApiOperation(value = "Save claiming information (claimDevice)", - notes = "Saves the information required for user to claim the device. " + + @Operation(summary = "Save claiming information (claimDevice)", + description = "Saves the information required for user to claim the device. " + "See more info about claiming in the corresponding 'Claiming devices' platform documentation." + "\n Example of the request payload: " + MARKDOWN_CODE_BLOCK_START @@ -220,10 +223,10 @@ public class DeviceApiController implements TbTransportService { + "Note: both 'secretKey' and 'durationMs' is optional parameters. " + "In case the secretKey is not specified, the empty string as a default value is used. In case the durationMs is not specified, the system parameter device.claim.duration is used.\n\n" + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @RequestMapping(value = "/{deviceToken}/claim", method = RequestMethod.POST) public DeferredResult claimDevice( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, @RequestBody(required = false) String json) { DeferredResult responseWriter = new DeferredResult<>(); @@ -237,17 +240,17 @@ public class DeviceApiController implements TbTransportService { return responseWriter; } - @ApiOperation(value = "Subscribe to RPC commands (subscribeToCommands) (Deprecated)", - notes = "Subscribes to RPC commands using http long polling. " + + @Operation(summary = "Subscribe to RPC commands (subscribeToCommands) (Deprecated)", + description = "Subscribes to RPC commands using http long polling. " + "Deprecated, since long polling is resource and network consuming. " + "Consider using MQTT or CoAP protocol for light-weight real-time updates. \n\n" + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) - @RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.GET, produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + @RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public DeferredResult subscribeToCommands( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @ApiParam(value = "Optional timeout of the long poll. Typically less then 60 seconds, since limited on the server side.") + @Parameter(description = "Optional timeout of the long poll. Typically less then 60 seconds, since limited on the server side.") @RequestParam(value = "timeout", required = false, defaultValue = "0") long timeout) { DeferredResult responseWriter = new DeferredResult<>(); transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), @@ -263,17 +266,17 @@ public class DeviceApiController implements TbTransportService { return responseWriter; } - @ApiOperation(value = "Reply to RPC commands (replyToCommand)", - notes = "Replies to server originated RPC command identified by 'requestId' parameter. The response is arbitrary JSON.\n\n" + + @Operation(summary = "Reply to RPC commands (replyToCommand)", + description = "Replies to server originated RPC command identified by 'requestId' parameter. The response is arbitrary JSON.\n\n" + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @RequestMapping(value = "/{deviceToken}/rpc/{requestId}", method = RequestMethod.POST) public DeferredResult replyToCommand( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @ApiParam(value = "RPC request id from the incoming RPC request", required = true, defaultValue = "123") + @Parameter(description = "RPC request id from the incoming RPC request", required = true , schema = @Schema(defaultValue = "123")) @PathVariable("requestId") Integer requestId, - @ApiParam(value = "Reply to the RPC request, JSON. For example: {\"status\":\"success\"}", required = true) + @Parameter(description = "Reply to the RPC request, JSON. For example: {\"status\":\"success\"}", required = true) @RequestBody String json) { DeferredResult responseWriter = new DeferredResult(); transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), @@ -284,8 +287,8 @@ public class DeviceApiController implements TbTransportService { return responseWriter; } - @ApiOperation(value = "Send the RPC command (postRpcRequest)", - notes = "Send the RPC request to server. The request payload is a JSON document that contains 'method' and 'params'. For example:" + + @Operation(summary = "Send the RPC command (postRpcRequest)", + description = "Send the RPC request to server. The request payload is a JSON document that contains 'method' and 'params'. For example:" + MARKDOWN_CODE_BLOCK_START + "{\"method\": \"sumOnServer\", \"params\":{\"a\":2, \"b\":2}}" + MARKDOWN_CODE_BLOCK_END + @@ -294,12 +297,12 @@ public class DeviceApiController implements TbTransportService { "{\"result\": 4}" + MARKDOWN_CODE_BLOCK_END + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.POST) public DeferredResult postRpcRequest( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @ApiParam(value = "The RPC request JSON", required = true) + @Parameter(description = "The RPC request JSON", required = true) @RequestBody String json) { DeferredResult responseWriter = new DeferredResult(); transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), @@ -317,17 +320,17 @@ public class DeviceApiController implements TbTransportService { return responseWriter; } - @ApiOperation(value = "Subscribe to attribute updates (subscribeToAttributes) (Deprecated)", - notes = "Subscribes to client and shared scope attribute updates using http long polling. " + + @Operation(summary = "Subscribe to attribute updates (subscribeToAttributes) (Deprecated)", + description = "Subscribes to client and shared scope attribute updates using http long polling. " + "Deprecated, since long polling is resource and network consuming. " + "Consider using MQTT or CoAP protocol for light-weight real-time updates. \n\n" + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) - @RequestMapping(value = "/{deviceToken}/attributes/updates", method = RequestMethod.GET, produces = "application/json") + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + @RequestMapping(value = "/{deviceToken}/attributes/updates", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public DeferredResult subscribeToAttributes( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @ApiParam(value = "Optional timeout of the long poll. Typically less then 60 seconds, since limited on the server side.") + @Parameter(description = "Optional timeout of the long poll. Typically less then 60 seconds, since limited on the server side.") @RequestParam(value = "timeout", required = false, defaultValue = "0") long timeout) { DeferredResult responseWriter = new DeferredResult<>(); transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), @@ -343,8 +346,8 @@ public class DeviceApiController implements TbTransportService { return responseWriter; } - @ApiOperation(value = "Get Device Firmware (getFirmware)", - notes = "Downloads the current firmware package." + + @Operation(summary = "Get Device Firmware (getFirmware)", + description = "Downloads the current firmware package." + "When the platform initiates firmware update, " + "it informs the device by updating the 'fw_title', 'fw_version', 'fw_checksum' and 'fw_checksum_algorithm' shared attributes." + "The 'fw_title' and 'fw_version' parameters must be supplied in this request to double-check " + @@ -354,24 +357,24 @@ public class DeviceApiController implements TbTransportService { "For example, device may request first 16 KB of firmware using 'chunk'=0 and 'size'=16384. " + "Next 16KB using 'chunk'=1 and 'size'=16384. The last chunk should have less bytes then requested using 'size' parameter. \n\n" + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @RequestMapping(value = "/{deviceToken}/firmware", method = RequestMethod.GET) public DeferredResult getFirmware( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @ApiParam(value = "Title of the firmware, corresponds to the value of 'fw_title' attribute.", required = true) + @Parameter(description = "Title of the firmware, corresponds to the value of 'fw_title' attribute.", required = true) @RequestParam(value = "title") String title, - @ApiParam(value = "Version of the firmware, corresponds to the value of 'fw_version' attribute.", required = true) + @Parameter(description = "Version of the firmware, corresponds to the value of 'fw_version' attribute.", required = true) @RequestParam(value = "version") String version, - @ApiParam(value = "Size of the chunk. Optional. Omit to download the entire file without chunks.") + @Parameter(description = "Size of the chunk. Optional. Omit to download the entire file without chunks.") @RequestParam(value = "size", required = false, defaultValue = "0") int size, - @ApiParam(value = "Index of the chunk. Optional. Omit to download the entire file without chunks.") + @Parameter(description = "Index of the chunk. Optional. Omit to download the entire file without chunks.") @RequestParam(value = "chunk", required = false, defaultValue = "0") int chunk) { return getOtaPackageCallback(deviceToken, title, version, size, chunk, OtaPackageType.FIRMWARE); } - @ApiOperation(value = "Get Device Software (getSoftware)", - notes = "Downloads the current software package." + + @Operation(summary = "Get Device Software (getSoftware)", + description = "Downloads the current software package." + "When the platform initiates software update, " + "it informs the device by updating the 'sw_title', 'sw_version', 'sw_checksum' and 'sw_checksum_algorithm' shared attributes." + "The 'sw_title' and 'sw_version' parameters must be supplied in this request to double-check " + @@ -381,24 +384,24 @@ public class DeviceApiController implements TbTransportService { "For example, device may request first 16 KB of software using 'chunk'=0 and 'size'=16384. " + "Next 16KB using 'chunk'=1 and 'size'=16384. The last chunk should have less bytes then requested using 'size' parameter. \n\n" + REQUIRE_ACCESS_TOKEN, - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @RequestMapping(value = "/{deviceToken}/software", method = RequestMethod.GET) public DeferredResult getSoftware( - @ApiParam(value = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, defaultValue = "YOUR_DEVICE_ACCESS_TOKEN") + @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @ApiParam(value = "Title of the software, corresponds to the value of 'sw_title' attribute.", required = true) + @Parameter(description = "Title of the software, corresponds to the value of 'sw_title' attribute.", required = true) @RequestParam(value = "title") String title, - @ApiParam(value = "Version of the software, corresponds to the value of 'sw_version' attribute.", required = true) + @Parameter(description = "Version of the software, corresponds to the value of 'sw_version' attribute.", required = true) @RequestParam(value = "version") String version, - @ApiParam(value = "Size of the chunk. Optional. Omit to download the entire file without using chunks.") + @Parameter(description = "Size of the chunk. Optional. Omit to download the entire file without using chunks.") @RequestParam(value = "size", required = false, defaultValue = "0") int size, - @ApiParam(value = "Index of the chunk. Optional. Omit to download the entire file without using chunks.") + @Parameter(description = "Index of the chunk. Optional. Omit to download the entire file without using chunks.") @RequestParam(value = "chunk", required = false, defaultValue = "0") int chunk) { return getOtaPackageCallback(deviceToken, title, version, size, chunk, OtaPackageType.SOFTWARE); } - @ApiOperation(value = "Provision new device (provisionDevice)", - notes = "Exchange the provision request to the device credentials. " + + @Operation(summary = "Provision new device (provisionDevice)", + description = "Exchange the provision request to the device credentials. " + "See more info about provisioning in the corresponding 'Device provisioning' platform documentation." + "Requires valid JSON request with the following format: " + MARKDOWN_CODE_BLOCK_START + @@ -417,10 +420,10 @@ public class DeviceApiController implements TbTransportService { " \"status\":\"SUCCESS\"\n" + "}" + MARKDOWN_CODE_BLOCK_END , - produces = MediaType.APPLICATION_JSON_VALUE) + responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) @RequestMapping(value = "/provision", method = RequestMethod.POST) public DeferredResult provisionDevice( - @ApiParam(value = "JSON with provision request. See API call description for example.") + @Parameter(description = "JSON with provision request. See API call description for example.") @RequestBody String json) { DeferredResult responseWriter = new DeferredResult<>(); transportContext.getTransportService().process(JsonConverter.convertToProvisionRequestMsg(json), diff --git a/pom.xml b/pom.xml index b5475cc655..9d0fc4fe15 100755 --- a/pom.xml +++ b/pom.xml @@ -59,7 +59,7 @@ 3.11.14 31.1-jre 2.6.1 - 3.4 + 3.12.0 1.15 2.11.0 1.2 @@ -92,8 +92,8 @@ 4.8.0 3.0.0-M9 3.0.2 - 3.0.4 - 1.6.3 + 2.1.0 + 2.2.9 0.7 1.18.2 1.69 @@ -135,7 +135,7 @@ 1.5.2 5.9.3 2.6.0 - 5.13.1 + 5.15.0 1.3.0 1.2.7 @@ -143,7 +143,7 @@ 3.23.1 5.2.0 1.3 - 1.17.3 + 1.18.3 1.12 3.0.0 6.1.0.202203080745-r @@ -1768,13 +1768,13 @@ ${curator.version} - org.thingsboard - springfox-boot-starter - ${springfox-swagger.version} + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc-swagger.version} - io.swagger - swagger-annotations + io.swagger.core.v3 + swagger-annotations-jakarta ${swagger-annotations.version} @@ -2010,6 +2010,16 @@ mockserver-netty ${mock-server.version} test + + + io.swagger.parser.v3 + swagger-parser-v2-converter + + + io.swagger.parser.v3 + swagger-parser + + org.mock-server From 0e72c36628168e8c0362bbeb7948621e0a8613a5 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Mon, 12 Jun 2023 14:42:50 +0200 Subject: [PATCH 018/397] minor improvements --- pom.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pom.xml b/pom.xml index 9d0fc4fe15..9419e1aede 100755 --- a/pom.xml +++ b/pom.xml @@ -2010,16 +2010,6 @@ mockserver-netty ${mock-server.version} test - - - io.swagger.parser.v3 - swagger-parser-v2-converter - - - io.swagger.parser.v3 - swagger-parser - - org.mock-server From 7dd5cada3501787e96d784981e8f16cdf47041b0 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 12 Jun 2023 18:16:24 +0300 Subject: [PATCH 019/397] UI: Refactoring and fix notification delivery method in mobile --- .../pages/admin/sms-provider.component.html | 79 ++++++++++--------- .../sent-notification-dialog.component.html | 25 +++--- .../sent-notification-dialog.component.scss | 57 +------------ .../sent/sent-notification-dialog.componet.ts | 8 +- ...emplate-notification-dialog.component.html | 7 ++ ...emplate-notification-dialog.component.scss | 3 +- .../app/shared/models/notification.models.ts | 4 +- 7 files changed, 78 insertions(+), 105 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.html b/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.html index 0f21bd0fd9..6b878f5d4d 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/sms-provider.component.html @@ -26,7 +26,7 @@
- +
- - - - admin.slack-settings - - -
-
- - -
- - -
+ +
+ + + + admin.slack-settings + + +
+
+ + +
+
admin.slack-api-token - +
-
- - - - - admin.mobile-settings - - - - - -
-
-
- + + + admin.mobile-settings + + + + + +
+ + label="{{ 'admin.firebase-service-account-file' | translate }}" + accept=".json,application/json" + allowedExtensions="json" + [existingFileName]="notificationSettingsForm.get('deliveryMethodsConfigs.MOBILE.firebaseServiceAccountCredentialsFileName')?.value" + (fileNameChanged)="notificationSettingsForm?.get('deliveryMethodsConfigs.MOBILE.firebaseServiceAccountCredentialsFileName').patchValue($event)">
-
-
-
-
-
- + + +
+ + diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html index a12f70139b..5be232104b 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html @@ -39,13 +39,19 @@ {{ 'notification.compose' | translate }}
-
- - {{ 'notification.start-from-scratch' | translate }} - {{ 'notification.use-template' | translate }} - +
+ +
- +
notification.delivery-method.mobile-preview
- {{ preview.processedTemplates.MOBILE.body }} +
{{ preview.processedTemplates.MOBILE.subject }}
+
{{ preview.processedTemplates.MOBILE.body }}
diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss index 0702d6bf52..4623ab1637 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss @@ -17,7 +17,7 @@ @import "../../../../../../theme"; :host-context(.tb-fullscreen-dialog .mat-mdc-dialog-container) { - width: 820px; + width: 930px; height: 100%; max-width: 100%; max-height: 100vh; @@ -76,6 +76,7 @@ .delivery-method-container { display: inline-flex; flex: 1 1 calc(50% - 8px); + max-width: calc(50% - 8px); padding: 16px 12px; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 6px; @@ -211,58 +212,8 @@ } } - .mat-button-toggle-group.tb-notification-use-template-toggle-group { - &.mat-button-toggle-group-appearance-standard { - border: none; - border-radius: 18px; - margin-bottom: 24px; - - .mat-button-toggle + .mat-button-toggle { - border-left: none; - } - } - - .mat-button-toggle { - background: rgba(0, 0, 0, 0.06); - height: 36px; - align-items: center; - display: flex; - - .mat-button-toggle-ripple { - top: 2px; - left: 2px; - right: 2px; - bottom: 2px; - border-radius: 18px; - } - } - - .mat-button-toggle-button { - color: #959595; - } - - .mat-button-toggle-focus-overlay { - border-radius: 18px; - margin: 2px; - } - - .mat-button-toggle-checked .mat-button-toggle-button { - background-color: $tb-primary-color; - color: #fff; - border-radius: 18px; - margin-left: 2px; - margin-right: 2px; - } - - .mat-button-toggle-appearance-standard .mat-button-toggle-label-content { - line-height: 34px; - font-size: 16px; - font-weight: 500; - } - - .mat-button-toggle-checked.mat-button-toggle-appearance-standard:not(.mat-button-toggle-disabled):hover .mat-button-toggle-focus-overlay { - opacity: .01; - } + .tb-notification-use-template-toggle-group { + margin-bottom: 24px; } .preview-group { diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts index 938ec2756f..674da8c5e8 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts @@ -90,7 +90,7 @@ export class SentNotificationDialogComponent extends protected fb: FormBuilder, private notificationService: NotificationService, private dialog: MatDialog, - private translate: TranslateService) { + public translate: TranslateService) { super(store, router, dialogRef, fb); this.notificationDeliveryMethods.forEach(method => { @@ -309,13 +309,17 @@ export class SentNotificationDialogComponent extends } allowConfigureDeliveryMethod(deliveryMethod: NotificationDeliveryMethod): boolean { + const tenantAllowConfigureDeliveryMethod = new Set([ + NotificationDeliveryMethod.SLACK, + NotificationDeliveryMethod.MOBILE + ]); if (deliveryMethod === NotificationDeliveryMethod.WEB) { return false; } if(this.isSysAdmin()) { return true; } else if (this.isTenantAdmin()) { - return deliveryMethod === NotificationDeliveryMethod.SLACK || deliveryMethod === NotificationDeliveryMethod.MOBILE; + return tenantAllowConfigureDeliveryMethod.has(deliveryMethod); } return false; } diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html index 1a623af7b9..784f36157b 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html @@ -271,6 +271,13 @@ trigger-text="{{ 'notification.see-documentation' | translate }}">
+ + notification.subject + + + {{ 'notification.subject-required' | translate }} + + notification.message \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n\n',dependencies:[{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:U.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatLabel,selector:"mat-label"},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:E.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:$e.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:fe.SafePipe,name:"safe"},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class $n extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(A),this.slackChanelTypesTranslateMap=M}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,[D.required]],conversationType:[e?e.conversationType:null,[D.required]],conversation:[e?e.conversation:null,[D.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([D.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:G.Store},{token:E.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:B.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:U.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatLabel,selector:"mat-label"},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Je.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:Je.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:H.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:E.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ye.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:G.Store},{type:E.FormBuilder}]}});class Jn extends s{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,[D.required]],accessKeyId:[e?e.accessKeyId:null,[D.required]],secretAccessKey:[e?e.secretAccessKey:null,[D.required]],region:[e?e.region:null,[D.required]]})}}e("SnsConfigComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatLabel,selector:"mat-label"},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:E.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class Yn extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=qt,this.sqsQueueTypes=Object.keys(qt),this.sqsQueueTypeTranslationsMap=At}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[D.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[D.required]],delaySeconds:[e?e.delaySeconds:null,[D.min(0),D.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[D.required]],secretAccessKey:[e?e.secretAccessKey:null,[D.required]],region:[e?e.region:null,[D.required]]})}}e("SqsConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:B.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatLabel,selector:"mat-label"},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Q.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:$.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:E.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:E.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:E.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:on,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:fe.SafePipe,name:"safe"},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class Wn{}e("RulenodeCoreConfigExternalModule",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Wn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Wn,declarations:[Jn,Yn,_n,Bn,Kn,Un,zn,Hn,jn,On,Qn,$n],imports:[K,I,Ve,In],exports:[Jn,Yn,_n,Bn,Kn,Un,zn,Hn,jn,On,Qn,$n]}),Wn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,imports:[K,I,Ve,In]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:l,args:[{declarations:[Jn,Yn,_n,Bn,Kn,Un,zn,Hn,jn,On,Qn,$n],imports:[K,I,Ve,In],exports:[Jn,Yn,_n,Bn,Kn,Un,zn,Hn,jn,On,Qn,$n]}]}]});class Xn extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ee(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[D.required]]})}}e("CheckAlarmStatusComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:G.Store},{token:E.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n'],dependencies:[{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Tn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n']}]}],ctorParameters:function(){return[{type:G.Store},{type:E.FormBuilder}]}});class Zn extends s{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ee(e?.messageNames)?e.messageNames:null,metadataNames:ee(e?.metadataNames)?e.metadataNames:null,checkAllKeys:!!ee(e?.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(D.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:G.Store},{token:E.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n'],dependencies:[{kind:"component",type:Ue.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:le.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:z.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:se.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:J.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Y.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n']}]}],ctorParameters:function(){return[{type:G.Store},{type:E.FormBuilder}]}});class er extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(g),this.entitySearchDirectionTranslationsMap=y}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ee(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ee(e?.direction)?e.direction:null,entityType:ee(e?.entityType)?e.entityType:null,entityId:ee(e?.entityId)?e.entityId:null,relationType:ee(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[D.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[D.required]:[]],relationType:[e.relationType,[D.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[D.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[D.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n'],dependencies:[{kind:"directive",type:B.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:We.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:ge.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Re.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatLabel,selector:"mat-label"},{kind:"component",type:Q.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:$.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:J.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:H.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:H.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Y.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n']}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class tr extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=ct,this.perimeterTypes=Object.values(ct),this.perimeterTypeTranslationMap=ft,this.rangeUnits=Object.values(xt),this.rangeUnitTranslationMap=bt,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ee(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ee(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ee(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ee(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ee(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ee(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ee(e?.centerLongitude)?e.centerLongitude:null,range:ee(e?.range)?e.range:null,rangeUnit:ee(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ee(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[D.required]],longitudeKeyName:[e.longitudeKeyName,[D.required]],perimeterType:[e.perimeterType,[D.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([D.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==ct.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([D.required,D.min(-90),D.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([D.required,D.min(-180),D.max(180)]),this.geoFilterConfigForm.get("range").setValidators([D.required,D.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([D.required]),this.defaultPaddingEnable=!1),t||n!==ct.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([D.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:G.Store},{token:E.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n'],dependencies:[{kind:"directive",type:B.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatLabel,selector:"mat-label"},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Q.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:$.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:J.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:H.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:H.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:E.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:E.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:E.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Y.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n']}]}],ctorParameters:function(){return[{type:G.Store},{type:E.FormBuilder}]}});class nr extends s{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ee(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[D.required]]})}}e("MessageTypeConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:hn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class rr extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[x.DEVICE,x.ASSET,x.ENTITY_VIEW,x.TENANT,x.CUSTOMER,x.USER,x.DASHBOARD,x.RULE_CHAIN,x.RULE_NODE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ee(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[D.required]]})}}e("OriginatorTypeConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n'],dependencies:[{kind:"component",type:Xe.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:le.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:z.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:se.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:H.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}\n']}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class or extends s{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=X(this.store).tbelEnabled,this.scriptLanguage=d,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[D.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==d.TBEL||this.tbelEnabled||(t=d.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===d.JS?[D.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===d.TBEL?[D.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=d.JS)),{scriptLang:ee(e?.scriptLang)?e.scriptLang:d.JS,jsScript:ee(e?.jsScript)?e.jsScript:null,tbelScript:ee(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===d.JS?"jsScript":"tbelScript",r=t===d.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===d.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:G.Store},{token:E.UntypedFormBuilder},{token:Z.NodeScriptTestService},{token:j.TranslateService}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ae.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:ie.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ie.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:le.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:se.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:me.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder},{type:Z.NodeScriptTestService},{type:j.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class ar extends s{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=X(this.store).tbelEnabled,this.scriptLanguage=d,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[D.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==d.TBEL||this.tbelEnabled||(t=d.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===d.JS?[D.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===d.TBEL?[D.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=d.JS)),{scriptLang:ee(e?.scriptLang)?e.scriptLang:d.JS,jsScript:ee(e?.jsScript)?e.jsScript:null,tbelScript:ee(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===d.JS?"jsScript":"tbelScript",r=t===d.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===d.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:G.Store},{token:E.UntypedFormBuilder},{token:Z.NodeScriptTestService},{token:j.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ae.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:ie.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ie.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:le.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:se.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:me.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder},{type:Z.NodeScriptTestService},{type:j.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class ir{}e("RuleNodeCoreConfigFilterModule",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[],target:t.ɵɵFactoryTarget.NgModule}),ir.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:ir,declarations:[Zn,er,tr,nr,rr,or,ar,Xn],imports:[K,I,In],exports:[Zn,er,tr,nr,rr,or,ar,Xn]}),ir.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,imports:[K,I,In]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:l,args:[{declarations:[Zn,er,tr,nr,rr,or,ar,Xn],imports:[K,I,In],exports:[Zn,er,tr,nr,rr,or,ar,Xn]}]}]});class lr extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=mt,this.originatorSources=Object.keys(mt),this.originatorSourceTranslationMap=ut,this.allowedEntityTypes=[x.DEVICE,x.ASSET,x.ENTITY_VIEW,x.USER,x.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[D.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===mt.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([D.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===mt.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([D.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([D.required,D.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.originator-source\n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n
\n \n \n \n
\n
\n',dependencies:[{kind:"directive",type:B.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ge.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatLabel,selector:"mat-label"},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Q.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:$.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:H.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:H.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:E.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:kn,selector:"tb-relations-query-config-old",inputs:["disabled","required"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
\n \n tb.rulenode.originator-source\n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n
\n \n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class sr extends s{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=X(this.store).tbelEnabled,this.scriptLanguage=d,this.changeScript=new r,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:d.JS,[D.required]],jsScript:[e?e.jsScript:null,[D.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==d.TBEL||this.tbelEnabled||(t=d.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===d.JS?[D.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===d.TBEL?[D.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=d.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===d.JS?"jsScript":"tbelScript",r=t===d.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===d.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:G.Store},{token:E.UntypedFormBuilder},{token:Z.NodeScriptTestService},{token:j.TranslateService}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ae.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:ie.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ie.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:le.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:se.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:me.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder},{type:Z.NodeScriptTestService},{type:j.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class mr extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",value:"false"},{name:"tb.mail-body-type.html",value:"true"},{name:"tb.mail-body-type.dynamic",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[D.required]],toTemplate:[e?e.toTemplate:null,[D.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[D.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[D.required]],bodyTemplate:[e?e.bodyTemplate:null,[D.required]]})}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"]}}e("ToEmailConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.cc-template\n \n \n \n \n tb.rulenode.bcc-template\n \n \n \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.mail-body-type\n \n \n {{ type.name | translate }}\n \n \n \n \n tb.rulenode.dynamic-mail-body-type\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n',dependencies:[{kind:"directive",type:B.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatLabel,selector:"mat-label"},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Q.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:$.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:E.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:fe.SafePipe,name:"safe"},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.cc-template\n \n \n \n \n tb.rulenode.bcc-template\n \n \n \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.mail-body-type\n \n \n {{ type.name | translate }}\n \n \n \n \n tb.rulenode.dynamic-mail-body-type\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class ur extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.separatorKeysCodes=[ue,pe,de]}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({fromMetadata:[e?e.fromMetadata:null,[D.required]],keys:[e?e.keys:null,[D.required]]})}configForm(){return this.copyKeysConfigForm}removeKey(e){const t=this.copyKeysConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.copyKeysConfigForm.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.copyKeysConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.copyKeysConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("CopyKeysConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
\n
{{\'tb.rulenode.copy-from\' | translate}}
\n \n \n {{\'tb.rulenode.data-to-metadata\' | translate}}\n \n \n {{\'tb.rulenode.metadata-to-data\' | translate}}\n \n \n \n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.keys-required\' | translate }}\n tb.rulenode.use-regular-expression-hint\n \n
\n',dependencies:[{kind:"directive",type:B.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:le.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Je.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:Je.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"component",type:ce.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:ce.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:ce.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:ce.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:H.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
\n
{{\'tb.rulenode.copy-from\' | translate}}
\n \n \n {{\'tb.rulenode.data-to-metadata\' | translate}}\n \n \n {{\'tb.rulenode.metadata-to-data\' | translate}}\n \n \n \n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.keys-required\' | translate }}\n tb.rulenode.use-regular-expression-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class pr extends s{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({fromMetadata:[e?e.fromMetadata:null,[D.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[D.required]]})}}e("RenameKeysConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
\n
{{ \'tb.rulenode.rename-keys-in\' | translate }}
\n \n \n {{\'tb.rulenode.data\' | translate}}\n \n \n {{\'tb.rulenode.metadata\' | translate}}\n \n \n \n \n
\n',dependencies:[{kind:"directive",type:Je.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:Je.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:H.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:on,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
\n
{{ \'tb.rulenode.rename-keys-in\' | translate }}
\n \n \n {{\'tb.rulenode.data\' | translate}}\n \n \n {{\'tb.rulenode.metadata\' | translate}}\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class dr extends s{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,[D.required]]})}}e("NodeJsonPathConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n\n",dependencies:[{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatLabel,selector:"mat-label"},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:E.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n\n"}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class cr extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.separatorKeysCodes=[ue,pe,de]}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({fromMetadata:[e?e.fromMetadata:null,[D.required]],keys:[e?e.keys:null,[D.required]]})}configForm(){return this.deleteKeysConfigForm}removeKey(e){const t=this.deleteKeysConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteKeysConfigForm.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.deleteKeysConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteKeysConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteKeysConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
\n
{{\'tb.rulenode.delete-from\' | translate}}
\n \n \n {{\'tb.rulenode.data\' | translate}}\n \n \n {{\'tb.rulenode.metadata\' | translate}}\n \n \n \n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.keys-required\' | translate }}\n tb.rulenode.use-regular-expression-delete-hint\n \n
\n',dependencies:[{kind:"directive",type:B.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:B.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:le.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:_.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:z.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:z.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:z.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Je.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:Je.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"component",type:ce.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:ce.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:ce.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:ce.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:H.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:j.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
\n
{{\'tb.rulenode.delete-from\' | translate}}
\n \n \n {{\'tb.rulenode.data\' | translate}}\n \n \n {{\'tb.rulenode.metadata\' | translate}}\n \n \n \n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.keys-required\' | translate }}\n tb.rulenode.use-regular-expression-delete-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class fr{}e("RulenodeCoreConfigTransformModule",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),fr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:fr,declarations:[lr,sr,mr,ur,pr,dr,cr],imports:[K,I,In],exports:[lr,sr,mr,ur,pr,dr,cr]}),fr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,imports:[K,I,In]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:l,args:[{declarations:[lr,sr,mr,ur,pr,dr,cr],imports:[K,I,In],exports:[lr,sr,mr,ur,pr,dr,cr]}]}]});class gr extends s{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=x}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({ruleChainId:[e?e.ruleChainId:null,[D.required]]})}}e("RuleChainInputComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"component",type:We.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:E.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:E.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class yr extends s{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:G.Store},{token:E.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n',dependencies:[{kind:"directive",type:H.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:E.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:E.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:j.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
\n
\n
\n'}]}],ctorParameters:function(){return[{type:G.Store},{type:E.UntypedFormBuilder}]}});class xr{}e("RuleNodeCoreConfigFlowModule",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),xr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:xr,declarations:[gr,yr],imports:[K,I,In],exports:[gr,yr]}),xr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,imports:[K,I,In]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:l,args:[{declarations:[gr,yr],imports:[K,I,In],exports:[gr,yr]}]}]});class br{constructor(e){!function(e){e.setTranslation("en_US",{tb:{rulenode:{id:"Id","additional-info":"Additional Info","create-entity-if-not-exists":"Create new entity if not exists","create-entity-if-not-exists-hint":"Create a new entity set above if it does not exist.","entity-name-pattern":"Name pattern","entity-name-pattern-required":"Name pattern is required","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","output-message-type":"Output message type","output-message-type-required":"Output message type is required","output-message-type-max-length":"Output message type should be less than 256","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 name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","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","notify-device":"Notify 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-hint":"If the message arrives from the device, we will push it back to the device by default.","notify-device-delete-hint":"Send notification about deleted attributes to device.","latest-timeseries":"Latest time-series data keys","timeseries-keys":"Timeseries keys","timeseries-keys-required":"At least one timeseries key should be selected.","add-timeseries-key":"Add timeseries key","add-message-field":"Add message field","relation-search-parameters":"Relation search 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",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","key-name":"Key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","add-device-profile":"Add device profile","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","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From Template","from-template-required":"From Template is required","to-template":"To Template","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 Template","bcc-template":"Bcc Template","subject-template":"Subject Template","subject-template-required":"Subject Template is required","body-template":"Body Template","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-to-specific-entity":"Delete relation to specific entity","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries 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","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"use-redis-queue":"Use redis queue for message persistence","ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","trim-redis-queue":"Trim redis queue","redis-queue-max-size":"Redis queue max size","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.","persist-alarm-rules":"Persist state of alarm rules","fetch-alarm-rules":"Fetch state of alarm rules","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","use-server-ts":"Use server ts","use-server-ts-hint":"Enable this setting to use the timestamp of the 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.","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","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.","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":"timeseries 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 timeseries from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch timeseries 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"},"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","unique-key-value-pair-error":"'{{valText}}' must be different from the current '{{keyText}}'"},"mail-body-type":{"plain-text":"Plain Text",html:"HTML",dynamic:"Dynamic"}}},!0)}(e)}}e("RuleNodeCoreConfigModule",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:j.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:br,declarations:[Ze],imports:[K,I],exports:[Nn,ir,Rn,Wn,fr,xr,Ze]}),br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,imports:[K,I,Nn,ir,Rn,Wn,fr,xr]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:l,args:[{declarations:[Ze],imports:[K,I],exports:[Nn,ir,Rn,Wn,fr,xr,Ze]}]}],ctorParameters:function(){return[{type:j.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map +System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/checkbox","@angular/material/input","@angular/material/form-field","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/select","@angular/material/core","@angular/material/slide-toggle","@shared/components/hint-tooltip-icon.component","@core/public-api","@shared/components/js-func.component","@angular/material/button","@angular/material/icon","@angular/material/tooltip","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/chips","@shared/pipe/safe.pipe","@shared/components/entity/entity-type-select.component","@shared/components/entity/entity-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","rxjs","@shared/components/help-popup.component","@shared/components/entity/entity-subtype-list.component","@shared/components/relation/relation-type-autocomplete.component","@home/components/relation/relation-filters.component","@angular/material/expansion","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,f,g,y,x,b,h,v,C,F,k,L,T,I,N,S,q,A,M,E,G,D,w,V,P,R,O,_,B,K,z,U,H,j,$,Q,J,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,fe,ge,ye,xe,be,he,ve,Ce,Fe,ke,Le,Te,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,De,we,Ve,Pe,Re,Oe,_e,Be,Ke,ze,Ue,He,je,$e,Qe,Je,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.EventEmitter,o=e.ViewChild,a=e.forwardRef,i=e.Input,l=e.InjectionToken,s=e.Injectable,m=e.Inject,p=e.Optional,d=e.Directive,u=e.Output,c=e.NgModule},function(e){f=e.RuleNodeConfigurationComponent,g=e.AttributeScope,y=e.telemetryTypeTranslations,x=e.ScriptLanguage,b=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.entitySearchDirectionTranslations,F=e.EntityType,k=e.entityFields,L=e.PageComponent,T=e.coerceBoolean,I=e.MessageType,N=e.messageTypeNames,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,D=e.NotificationType,w=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,U=e.FormGroup},function(e){H=e,j=e.DOCUMENT,$=e.CommonModule},function(e){Q=e},function(e){J=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e.getCurrentAuthState,oe=e,ae=e.isEqual,ie=e.isDefinedAndNotNull,le=e.deepTrim,se=e.isObject,me=e.isNotEmptyStr},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e},function(e){fe=e},function(e){ge=e.ENTER,ye=e.COMMA,xe=e.SEMICOLON},function(e){be=e},function(e){he=e},function(e){ve=e},function(e){Ce=e},function(e){Fe=e.coerceBooleanProperty,ke=e.coerceElement,Le=e.coerceNumberProperty},function(e){Te=e},function(e){Ie=e},function(e){Ne=e},function(e){Se=e},function(e){qe=e.tap,Ae=e.map,Me=e.startWith,Ee=e.mergeMap,Ge=e.share,De=e.takeUntil,we=e.auditTime},function(e){Ve=e},function(e){Pe=e},function(e){Re=e.HomeComponentsModule},function(e){Oe=e.__decorate},function(e){_e=e.Subject,Be=e.takeUntil,Ke=e.of,ze=e.EMPTY,Ue=e.fromEvent},function(e){He=e},function(e){je=e},function(e){$e=e},function(e){Qe=e},function(e){Je=e},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ct extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===g.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ct),ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ct,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
\n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ft extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===x.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===x.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",ft),ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ft,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gt extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.alarmSeverities=Object.keys(b),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[ge,ye,xe],this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==x.TBEL||this.tbelEnabled||(r=x.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===x.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===x.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",gt),gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),gt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gt,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class yt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["entityType"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==F.DEVICE&&t!==F.ASSET?this.createRelationConfigForm.get("entityTypePattern").setValidators([]):this.createRelationConfigForm.get("entityTypePattern").setValidators([O.required,O.pattern(/.*\S.*/)]),this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",yt),yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yt,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
tb.rulenode.create-entity-if-not-exists-hint
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
tb.rulenode.remove-current-relations-hint
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
tb.rulenode.change-originator-to-related-entity-hint
\n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
tb.rulenode.create-entity-if-not-exists-hint
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
tb.rulenode.remove-current-relations-hint
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
tb.rulenode.change-originator-to-related-entity-hint
\n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
tb.rulenode.delete-relation-hint
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
\n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
tb.rulenode.delete-relation-hint
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bt extends f{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,O.required],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart,O.required]})}}e("DeviceProfileConfigComponent",bt),bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
\n',dependencies:[{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
\n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ht extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}var vt;e("GeneratorConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n \n \n \n
\n\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n \n \n \n
\n\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(vt||(vt={}));const Ct=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer"],[vt.TENANT,"tb.rulenode.originator-tenant"],[vt.RELATED,"tb.rulenode.originator-related"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[vt.ENTITY,"tb.rulenode.originator-entity"]]),Ft=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer-desc"],[vt.TENANT,"tb.rulenode.originator-tenant-desc"],[vt.RELATED,"tb.rulenode.originator-related-entity-desc"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[vt.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),kt=[k.createdTime,k.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},k.firstName,k.lastName,k.email,k.title,k.country,k.state,k.city,k.address,k.address2,k.zip,k.phone,k.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],Lt=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 Tt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Tt||(Tt={}));const It=new Map([[Tt.CIRCLE,"tb.rulenode.perimeter-circle"],[Tt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Nt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Nt||(Nt={}));const St=new Map([[Nt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Nt.SECONDS,"tb.rulenode.time-unit-seconds"],[Nt.MINUTES,"tb.rulenode.time-unit-minutes"],[Nt.HOURS,"tb.rulenode.time-unit-hours"],[Nt.DAYS,"tb.rulenode.time-unit-days"]]);var qt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(qt||(qt={}));const At=new Map([[qt.METER,"tb.rulenode.range-unit-meter"],[qt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[qt.FOOT,"tb.rulenode.range-unit-foot"],[qt.MILE,"tb.rulenode.range-unit-mile"],[qt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Mt;!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"}(Mt||(Mt={}));const Et=new Map([[Mt.ID,"tb.rulenode.entity-details-id"],[Mt.TITLE,"tb.rulenode.entity-details-title"],[Mt.COUNTRY,"tb.rulenode.entity-details-country"],[Mt.STATE,"tb.rulenode.entity-details-state"],[Mt.CITY,"tb.rulenode.entity-details-city"],[Mt.ZIP,"tb.rulenode.entity-details-zip"],[Mt.ADDRESS,"tb.rulenode.entity-details-address"],[Mt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Mt.PHONE,"tb.rulenode.entity-details-phone"],[Mt.EMAIL,"tb.rulenode.entity-details-email"],[Mt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Gt;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Gt||(Gt={}));const Dt=new Map([[Gt.FIRST,"tb.rulenode.first"],[Gt.LAST,"tb.rulenode.last"],[Gt.ALL,"tb.rulenode.all"]]),wt=new Map([[Gt.FIRST,"tb.rulenode.first-mode-hint"],[Gt.LAST,"tb.rulenode.last-mode-hint"],[Gt.ALL,"tb.rulenode.all-mode-hint"]]);var Vt,Pt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Vt||(Vt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(Pt||(Pt={}));const Rt=new Map([[Pt.ATTRIBUTES,"tb.rulenode.attributes"],[Pt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[Pt.FIELDS,"tb.rulenode.fields"]]),Ot=new Map([[Pt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[Pt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[Pt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),_t=new Map([[Vt.ASC,"tb.rulenode.ascending"],[Vt.DESC,"tb.rulenode.descending"]]);var Bt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Bt||(Bt={}));const Kt=new Map([[Bt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Bt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),zt=["anonymous","basic","cert.PEM"],Ut=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Ht=["sas","cert.PEM"],jt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var $t;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}($t||($t={}));const Qt=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],Jt=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 Yt;!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"}(Yt||(Yt={}));const Wt=new Map([[Yt.CUSTOM,{value:Yt.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[Yt.ADD,{value:Yt.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[Yt.SUB,{value:Yt.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[Yt.MULT,{value:Yt.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[Yt.DIV,{value:Yt.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[Yt.SIN,{value:Yt.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.SINH,{value:Yt.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[Yt.COS,{value:Yt.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.COSH,{value:Yt.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[Yt.TAN,{value:Yt.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[Yt.TANH,{value:Yt.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ACOS,{value:Yt.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[Yt.ASIN,{value:Yt.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN,{value:Yt.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN2,{value:Yt.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}],[Yt.EXP,{value:Yt.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[Yt.EXPM1,{value:Yt.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[Yt.SQRT,{value:Yt.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[Yt.CBRT,{value:Yt.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[Yt.GET_EXP,{value:Yt.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[Yt.HYPOT,{value:Yt.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[Yt.LOG,{value:Yt.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG10,{value:Yt.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG1P,{value:Yt.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[Yt.CEIL,{value:Yt.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR,{value:Yt.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR_DIV,{value:Yt.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[Yt.FLOOR_MOD,{value:Yt.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[Yt.ABS,{value:Yt.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[Yt.MIN,{value:Yt.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[Yt.MAX,{value:Yt.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[Yt.POW,{value:Yt.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}],[Yt.SIGNUM,{value:Yt.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[Yt.RAD,{value:Yt.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[Yt.DEG,{value:Yt.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var Zt,Xt,en;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(Zt||(Zt={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(Xt||(Xt={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(en||(en={}));const tn=new Map([[en.DATA,"tb.rulenode.message-to-metadata"],[en.METADATA,"tb.rulenode.metadata-to-message"]]),nn=(new Map([[en.DATA,"tb.rulenode.from-message"],[en.METADATA,"tb.rulenode.from-metadata"]]),new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.metadata"]])),rn=new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.message-metadata"]]),on=new Map([[Zt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[Zt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[Zt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[Zt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[Zt.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),an=new Map([[Xt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[Xt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[Xt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[Xt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),ln=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var sn,mn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(sn||(sn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(mn||(mn={}));const pn=new Map([[sn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[sn.SERVER_SCOPE,"tb.rulenode.server-scope"],[sn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);class dn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.keys(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.keys(qt),this.rangeUnitTranslationMap=At,this.timeUnits=Object.keys(Nt),this.timeUnitsTranslationMap=St}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([])):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required])),t||n!==Tt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",dn),dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.latitude-key-name\n \n \n {{ \'tb.rulenode.latitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.longitude-key-name\n \n \n {{ \'tb.rulenode.longitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.perimeter-type\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n \n tb.rulenode.perimeter-key-name\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n \n
\n
\n \n tb.rulenode.circle-center-latitude\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n tb.rulenode.circle-center-longitude\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n tb.rulenode.range\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n tb.rulenode.range-units\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
\n \n tb.rulenode.latitude-key-name\n \n \n {{ \'tb.rulenode.latitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.longitude-key-name\n \n \n {{ \'tb.rulenode.longitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.perimeter-type\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n \n tb.rulenode.perimeter-key-name\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n \n
\n
\n \n tb.rulenode.circle-center-latitude\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n tb.rulenode.circle-center-longitude\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n tb.rulenode.range\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n tb.rulenode.range-units\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class un extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",un),un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:un,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:un,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:un,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",cn),cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",fn),fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",gn),gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
\n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
\n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",yn),yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
\n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
\n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",xn),xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xn,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
\n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",bn),bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bn,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:a((()=>hn)),multi:!0},{provide:K,useExisting:a((()=>hn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Te.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ie.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:a((()=>hn)),multi:!0},{provide:K,useExisting:a((()=>hn)),multi:!0}],template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],required:[{type:i}]}});class vn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
tb.rulenode.use-server-ts-hint
\n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
\n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
tb.rulenode.use-server-ts-hint
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
tb.rulenode.send-attributes-deleted-notification-hint
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
tb.rulenode.notify-device-on-delete-hint
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
\n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
tb.rulenode.send-attributes-deleted-notification-hint
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
tb.rulenode.notify-device-on-delete-hint
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:o,args:["attributeChipList"]}]}});class Ln extends L{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=Wt,this.ArgumentType=Zt,this.attributeScopeMap=pn,this.argumentTypeMap=on,this.arguments=Object.values(Zt),this.attributeScope=Object.values(sn),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===Yt.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===Zt.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==Zt.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(ln[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:a((()=>Ln)),multi:!0},{provide:K,useExisting:a((()=>Ln)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ne.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:Ne.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Se.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Se.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Se.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ie.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:a((()=>Ln)),multi:!0},{provide:K,useExisting:a((()=>Ln)),multi:!0}],template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],function:[{type:i}]}});class Tn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(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=[...Wt.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(qe((e=>{let t;t="string"==typeof e&&Yt[e]?Yt[e]:null,this.updateView(t)})),Ae((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=Wt.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Tn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Ve.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Ve.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Pe.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:a((()=>Tn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:i}],disabled:[{type:i}],operationInput:[{type:o,args:["operationInput",{static:!0}]}]}});class In extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=Yt,this.ArgumentTypeResult=Xt,this.argumentTypeResultMap=an,this.attributeScopeMap=pn,this.argumentsResult=Object.values(Xt),this.attributeScopeResult=Object.values(mn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===Yt.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===Xt.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ln,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:Tn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nn{constructor(){this.textAlign="left"}}e("ExampleHintComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:He.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:i}],popupHelpLink:[{type:i}],textAlign:[{type:i}]}});class Sn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new _e,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ae(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(Be(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>Sn)),multi:!0},{provide:K,useExisting:a((()=>Sn)),multi:!0}],ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Oe([T()],Sn.prototype,"disabled",void 0),Oe([T()],Sn.prototype,"uniqueKeyValuePairValidator",void 0),Oe([T()],Sn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:a((()=>Sn)),multi:!0},{provide:K,useExisting:a((()=>Sn)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class qn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.entityType=F,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>qn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:je.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:$e.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:a((()=>qn)),multi:!0}],template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class An extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>An)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Qe.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:a((()=>An)),multi:!0}],template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Mn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(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=[ge,ye,xe],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(I))this.messageTypesList.push({name:N.get(I[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Me(""),Ae((e=>e||"")),Ee((e=>this.fetchMessageTypes(e))),Ge())}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 Ke(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return Ke(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ve.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Ve.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:Ve.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Pe.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],label:[{type:i}],placeholder:[{type:i}],disabled:[{type:i}],chipList:[{type:o,args:["chipList",{static:!1}]}],matAutocomplete:[{type:o,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:o,args:["messageTypeInput",{static:!1}]}]}});class En extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=zt,this.credentialsTypeTranslationsMap=Ut,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){ie(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:a((()=>En)),multi:!0},{provide:K,useExisting:a((()=>En)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Je.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:Je.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:Je.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:Je.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:Je.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ye.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:a((()=>En)),multi:!0},{provide:K,useExisting:a((()=>En)),multi:!0}],template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],disableCertPemCredentials:[{type:i}],passwordFieldRequired:[{type:i}]}});const Gn=new l("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class Dn{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new _e,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Dn,deps:[{token:t.NgZone},{token:j},{token:Gn,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),Dn.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Dn,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Dn,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:m,args:[j]}]},{type:void 0,decorators:[{type:p},{type:m,args:[Gn]}]}]}});class wn{constructor(e,t,n,o){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=o,this.cbOnSuccess=new r,this.cbOnError=new r,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:wn,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:Dn}],target:t.ɵɵFactoryTarget.Directive}),wn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:wn,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:wn,decorators:[{type:d,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:Dn}]},propDecorators:{targetElm:[{type:i,args:["ngxClipboard"]}],container:[{type:i}],cbContent:[{type:i}],cbSuccessMsg:[{type:i}],cbOnSuccess:[{type:u}],cbOnError:[{type:u}]}});class Vn{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Vn,deps:[{token:Dn},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),Vn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:Vn,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Vn,decorators:[{type:d,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:Dn},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class Pn{}Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Pn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,declarations:[wn,Vn],imports:[$],exports:[wn,Vn]}),Pn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,decorators:[{type:c,args:[{imports:[$],declarations:[wn,Vn],exports:[wn,Vn]}]}]});class Rn{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 _e,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(Be(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(Be(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Rn),Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Rn)),multi:!0},{provide:K,useExisting:a((()=>Rn)),multi:!0}],ngImport:t,template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:wn,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Oe([T()],Rn.prototype,"disabled",void 0),Oe([T()],Rn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:a((()=>Rn)),multi:!0},{provide:K,useExisting:a((()=>Rn)),multi:!0}],template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:i}],disabled:[{type:i}],required:[{type:i}]}});class On{constructor(e,t){this.fb=e,this.translate=t,this.translation=nn,this.propagateChange=()=>{},this.destroy$=new _e,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(De(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",On),On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),On.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:On,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:a((()=>On)),multi:!0}],ngImport:t,template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:a((()=>On)),multi:!0}],template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:i}],translation:[{type:i}]}});class _n extends L{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new _e,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ae(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(De(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)ie(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(De(this.destroy$)).subscribe((t=>{const n=Lt.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>_n)),multi:!0},{provide:K,useExisting:a((()=>_n)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Ie.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Oe([T()],_n.prototype,"disabled",void 0),Oe([T()],_n.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:a((()=>_n)),multi:!0},{provide:K,useExisting:a((()=>_n)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:i}],disabled:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],targetKeyPrefix:[{type:i}],selectText:[{type:i}],selectRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class Bn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Qe.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0}],template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Kn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new _e,this.separatorKeysCodes=[ge,ye,xe],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(De(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||ie(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0},{provide:K,useExisting:Kn,multi:!0}],ngImport:t,template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0},{provide:K,useExisting:Kn,multi:!0}],template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:i}]}});class zn extends L{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new _e,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(De(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0}],template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Un{}e("RulenodeCoreConfigCommonModule",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Un.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Un,declarations:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn],imports:[$,M,Re],exports:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn]}),Un.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,imports:[$,M,Re]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:c,args:[{declarations:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn],imports:[$,M,Re],exports:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn]}]}]});class Hn{}e("RuleNodeCoreConfigActionModule",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Hn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Hn,declarations:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In],imports:[$,M,Re,Un],exports:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In]}),Hn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,imports:[$,M,Re,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:c,args:[{declarations:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In],imports:[$,M,Re,Un],exports:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In]}]}]});class jn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]]})}prepareInputConfig(e){return{inputValueKey:ie(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:ie(e?.outputValueKey)?e.outputValueKey:null,useCache:!ie(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!ie(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:ie(e?.periodValueKey)?e.periodValueKey:null,round:ie(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!ie(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative}}prepareOutputConfig(e){return le(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n
\n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n
\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class $n extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.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,le(e)}prepareInputConfig(e){let t,n;return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Qn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return se(e)&&(e.attributesControl={clientAttributeNames:ie(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ie(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ie(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ie(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:ie(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!ie(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Qn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:qn,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Kn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Jn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Mt))this.predefinedValues.push({value:Mt[e],name:this.translate.instant(Et.get(Mt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=ie(e?.addToMetadata)?e.addToMetadata?en.METADATA:en.DATA:e?.fetchTo?e.fetchTo:en.DATA,{detailsList:ie(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Yn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Gt,this.samplingOrders=Object.values(Vt),this.samplingOrdersTranslate=_t,this.timeUnits=Object.values(Nt),this.timeUnitsTranslationMap=St,this.deduplicationStrategiesHintTranslations=wt,this.headerOptions=[],this.timeUnitMap={[Nt.MILLISECONDS]:1,[Nt.SECONDS]:1e3,[Nt.MINUTES]:6e4,[Nt.HOURS]:36e5,[Nt.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 Dt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Dt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,le(e)}prepareInputConfig(e){return se(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:ie(e?.aggregation)?e.aggregation:E.NONE,fetchMode:ie(e?.fetchMode)?e.fetchMode:Gt.FIRST,orderBy:ie(e?.orderBy)?e.orderBy:Vt.ASC,limit:ie(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!ie(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:ie(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:ie(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Nt.MINUTES,endInterval:ie(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:ie(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Nt.MINUTES},startIntervalPattern:ie(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:ie(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Gt.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Gt.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:He.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Wn extends f{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 se(e)&&(e.attributesControl={clientAttributeNames:ie(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ie(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ie(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ie(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA,tellFailureIfAbsent:!!ie(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:ie(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Kn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Zn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of kt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return le(e)}prepareInputConfig(e){return{dataMapping:ie(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:ie(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n',dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:_n,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Xn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=Pt,this.msgMetadataLabelTranslations=Ot,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(kt))this.originatorFields.push({value:kt[e].value,name:this.translate.instant(kt[e].name)});for(const e of Rt.keys())this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===Pt.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,le(e)}prepareInputConfig(e){let t,n,r={[k.name.value]:`relatedEntity${this.translate.instant(k.name.name)}`},o={serialNumber:"sn"};return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,t===Pt.FIELDS?r=n:o=n,{relationsQuery:ie(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:An,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:_n,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class er extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class tr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class nr{}e("RulenodeCoreConfigEnrichmentModule",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),nr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:nr,declarations:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr],imports:[$,M,Un],exports:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr]}),nr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:c,args:[{declarations:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr],imports:[$,M,Un],exports:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr]}]}]});class rr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Ht,this.azureIotHubCredentialsTypeTranslationsMap=jt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Je.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:Je.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:Je.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:Je.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:Je.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ye.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class or extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=Qt,this.ToByteStandartCharsetTypeTranslationMap=Jt}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ar extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&me(e.clientId))},[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){me(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:En,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ir extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=D,this.entityType=F}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ir,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ye.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys($t)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],useRedisQueueForMsgPersistence:[!!e&&e.useRedisQueueForMsgPersistence,[]],trimQueue:[!!e&&e.trimQueue,[]],maxQueueSize:[e?e.maxQueueSize:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","useRedisQueueForMsgPersistence","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("useRedisQueueForMsgPersistence").value,r=this.restApiCallConfigForm.get("enableProxy").value,o=this.restApiCallConfigForm.get("useSystemProxyProperties").value;r&&!o?(this.restApiCallConfigForm.get("proxyHost").setValidators(r?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(r?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),n?this.restApiCallConfigForm.get("maxQueueSize").setValidators([O.min(0)]):this.restApiCallConfigForm.get("maxQueueSize").setValidators([]),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("maxQueueSize").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
\n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
\n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
\n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:En,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
\n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
\n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class dr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(w),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Bt,this.sqsQueueTypes=Object.keys(Bt),this.sqsQueueTypeTranslationsMap=Kt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr{}e("RulenodeCoreConfigExternalModule",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),gr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:gr,declarations:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur],imports:[$,M,Re,Un],exports:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur]}),gr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,imports:[$,M,Re,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:c,args:[{declarations:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur],imports:[$,M,Re,Un],exports:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur]}]}]});class yr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ie(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:zn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class xr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ie(e?.messageNames)?e.messageNames:[],metadataNames:ie(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!ie(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:ie(e?.messageNames)?e.messageNames:[],metadataNames:ie(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class br extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=C}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ie(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ie(e?.direction)?e.direction:null,entityType:ie(e?.entityType)?e.entityType:null,entityId:ie(e?.entityId)?e.entityId:null,relationType:ie(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:$e.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.values(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.values(qt),this.rangeUnitTranslationMap=At,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ie(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ie(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ie(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ie(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ie(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ie(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ie(e?.centerLongitude)?e.centerLongitude:null,range:ie(e?.range)?e.range:null,rangeUnit:ie(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ie(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class vr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ie(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Mn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.TENANT,F.CUSTOMER,F.USER,F.DASHBOARD,F.RULE_CHAIN,F.RULE_NODE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ie(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ie(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ie(e?.jsScript)?e.jsScript:null,tbelScript:ie(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class kr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ie(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ie(e?.jsScript)?e.jsScript:null,tbelScript:ie(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Lr{}e("RuleNodeCoreConfigFilterModule",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Lr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Lr,declarations:[xr,br,hr,vr,Cr,Fr,kr,yr],imports:[$,M,Un],exports:[xr,br,hr,vr,Cr,Fr,kr,yr]}),Lr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:c,args:[{declarations:[xr,br,hr,vr,Cr,Fr,kr,yr],imports:[$,M,Un],exports:[xr,br,hr,vr,Cr,Fr,kr,yr]}]}]});class Tr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=vt,this.originatorSources=Object.keys(vt),this.originatorSourceTranslationMap=Ct,this.originatorSourceDescTranslationMap=Ft,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.USER,F.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===vt.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===vt.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Ne.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Ne.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Ir extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.FormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + const Nr=mt({passive:!0});class Sr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return ze;const t=ke(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new _e,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Nr),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Nr)}}),r}stopMonitoring(e){const t=ke(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Sr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Sr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Sr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Sr,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class qr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new r}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:qr,deps:[{token:t.ElementRef},{token:Sr}],target:t.ɵɵFactoryTarget.Directive}),qr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:qr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:qr,decorators:[{type:d,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Sr}]},propDecorators:{cdkAutofill:[{type:u}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Ar{get minRows(){return this._minRows}set minRows(e){this._minRows=Le(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=Le(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Fe(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new _e,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();Ue(e,"resize").pipe(we(16),De(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Ar,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Ar.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Ar,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Ar,decorators:[{type:d,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:p},{type:m,args:[j]}]}]},propDecorators:{minRows:[{type:i,args:["cdkAutosizeMinRows"]}],maxRows:[{type:i,args:["cdkAutosizeMaxRows"]}],enabled:[{type:i,args:["cdkTextareaAutosize"]}],placeholder:[{type:i}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Mr{}Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Mr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,declarations:[qr,Ar],exports:[qr,Ar]}),Mr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,decorators:[{type:c,args:[{declarations:[qr,Ar],exports:[qr,Ar]}]}]});class Er extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:ie(e?.fromTemplate)?e.fromTemplate:null,toTemplate:ie(e?.toTemplate)?e.toTemplate:null,ccTemplate:ie(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:ie(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:ie(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:ie(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:ie(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:ie(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Er),Er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Er,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:He.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Ar,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Ne.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Ne.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Gr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=tn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.copyFrom?en.METADATA:en.DATA:ie(e?.copyFrom)?e.copyFrom:en.DATA,{keys:ie(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Gr),Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Dr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=rn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ie(e?.renameIn)?e?.renameIn:en.DATA,{renameKeysMapping:ie(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Dr),Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dr,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dr,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class wr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",wr),wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),wr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wr,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Vr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=nn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ie(e?.deleteFrom)?e?.deleteFrom:en.DATA,{keys:ie(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Vr),Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vr,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Gt,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Dt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[ie(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[ie(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[ie(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[ie(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[ie(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Je.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:Je.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:Je.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Rn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Rr{}e("RulenodeCoreConfigTransformModule",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Rr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Rr,declarations:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr],imports:[$,M,Un],exports:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr]}),Rr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:c,args:[{declarations:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr],imports:[$,M,Un],exports:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr]}]}]});class Or extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=F}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class _r extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Br{}e("RuleNodeCoreConfigFlowModule",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Br,declarations:[Or,_r],imports:[$,M,Un],exports:[Or,_r]}),Br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:c,args:[{declarations:[Or,_r],imports:[$,M,Un],exports:[Or,_r]}]}]});class Kr{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 not exists","create-entity-if-not-exists-hint":"Create a new entity set above if it does not exist.","entity-name-pattern":"Name pattern","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 name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","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","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":"Timeseries keys","timeseries-keys-required":"At least one timeseries key should be selected.","add-timeseries-key":"Add timeseries key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-to-specific-entity":"Delete relation to specific entity","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"use-redis-queue":"Use redis queue for message persistence","ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","trim-redis-queue":"Trim redis queue","redis-queue-max-size":"Redis queue max size","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.","persist-alarm-rules":"Persist state of alarm rules","fetch-alarm-rules":"Fetch state of alarm rules","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","use-server-ts":"Use server ts","use-server-ts-hint":"Enable this setting to use the timestamp of the 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.","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.","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":"timeseries 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 timeseries from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch timeseries 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 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."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),Kr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Kr,declarations:[dt],imports:[$,M],exports:[Hn,Lr,nr,gr,Rr,Br,dt]}),Kr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,imports:[$,M,Hn,Lr,nr,gr,Rr,Br]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:c,args:[{declarations:[dt],imports:[$,M],exports:[Hn,Lr,nr,gr,Rr,Br,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/AbstractRuleNodeUpgradeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/AbstractRuleNodeUpgradeTest.java new file mode 100644 index 0000000000..f2509a9d68 --- /dev/null +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/AbstractRuleNodeUpgradeTest.java @@ -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. + */ +package org.thingsboard.rule.engine; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.server.common.data.util.TbPair; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.BDDMockito.willCallRealMethod; + +public abstract class AbstractRuleNodeUpgradeTest { + + protected abstract TbNode getTestNode(); + + @ParameterizedTest + @MethodSource + public void givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig(int givenVersion, String givenConfigStr, boolean hasChanges, String expectedConfigStr) throws TbNodeException { + // GIVEN + willCallRealMethod().given(getTestNode()).upgrade(anyInt(), any()); + JsonNode givenConfig = JacksonUtil.toJsonNode(givenConfigStr); + JsonNode expectedConfig = JacksonUtil.toJsonNode(expectedConfigStr); + + // WHEN + TbPair upgradeResult = getTestNode().upgrade(givenVersion, givenConfig); + + // THEN + assertThat(upgradeResult.getFirst()).isEqualTo(hasChanges); + ObjectNode upgradedConfig = (ObjectNode) upgradeResult.getSecond(); + assertThat(upgradedConfig).isEqualTo(expectedConfig); + } +} diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/TestDbCallbackExecutor.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/TestDbCallbackExecutor.java index ed9053e2e2..0b456e1e90 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/TestDbCallbackExecutor.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/TestDbCallbackExecutor.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbAlarmNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbAlarmNodeTest.java index 33c6071769..d323863b39 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbAlarmNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbAlarmNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeTest.java index f36cc94540..ec2b4a581f 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbLogNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbLogNodeTest.java index 885002a694..7d915f1cc9 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbLogNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbLogNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java index 2cecd1490d..6aa1b02fa9 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/credentials/CertPemCredentialsTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNodeTest.java new file mode 100644 index 0000000000..13f2b2ad42 --- /dev/null +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNodeTest.java @@ -0,0 +1,53 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.debug; + +import org.junit.jupiter.params.provider.Arguments; +import org.thingsboard.rule.engine.AbstractRuleNodeUpgradeTest; +import org.thingsboard.rule.engine.api.TbNode; + +import java.util.stream.Stream; + +import static org.mockito.Mockito.spy; + +public class TbMsgGeneratorNodeTest extends AbstractRuleNodeUpgradeTest { + + // Rule nodes upgrade + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() { + return Stream.of( + // default config for version 0 + Arguments.of(0, + "{\"msgCount\":0,\"periodInSeconds\":1,\"originatorId\":null,\"originatorType\":null, \"queueName\":null, \"scriptLang\":\"TBEL\",\"jsScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\",\"tbelScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\"}", + true, + "{\"msgCount\":0,\"periodInSeconds\":1,\"originatorId\":null,\"originatorType\":null, \"scriptLang\":\"TBEL\",\"jsScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\",\"tbelScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\"}"), + // default config for version 0 with queueName + Arguments.of(0, + "{\"msgCount\":0,\"periodInSeconds\":1,\"originatorId\":null,\"originatorType\":null, \"queueName\":\"Main\", \"scriptLang\":\"TBEL\",\"jsScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\",\"tbelScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\"}", + true, + "{\"msgCount\":0,\"periodInSeconds\":1,\"originatorId\":null,\"originatorType\":null, \"scriptLang\":\"TBEL\",\"jsScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\",\"tbelScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\"}"), + // default config for version 1 with upgrade from version 0 + Arguments.of(0, + "{\"msgCount\":0,\"periodInSeconds\":1,\"originatorId\":null,\"originatorType\":null, \"scriptLang\":\"TBEL\",\"jsScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\",\"tbelScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\"}", + false, + "{\"msgCount\":0,\"periodInSeconds\":1,\"originatorId\":null,\"originatorType\":null, \"scriptLang\":\"TBEL\",\"jsScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\",\"tbelScript\":\"var msg = { temp: 42, humidity: 77 };\\nvar metadata = { data: 40 };\\nvar msgType = \\\"POST_TELEMETRY_REQUEST\\\";\\n\\nreturn { msg: msg, metadata: metadata, msgType: msgType };\"}") + ); + } + + @Override + protected TbNode getTestNode() { + return spy(TbMsgGeneratorNode.class); + } +} diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNodeTest.java index f44326a8d5..5f57f7f5e3 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java index 785be659fd..f072eb1723 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java index a146b95ee1..c79f962818 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckMessageNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckMessageNodeTest.java index e69cc55d7e..ce8afbbe99 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckMessageNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckMessageNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckRelationNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckRelationNodeTest.java index bf7fa31f18..55372c0181 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckRelationNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckRelationNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java index a6f4a6e3cf..707df26d0f 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java index 639c1a7b1a..903944025a 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsFilterNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java index 3343c5fb92..d679e42ba0 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbJsSwitchNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNodeTest.java index 4e2e5dc430..c760a295e2 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNodeTest.java index 603c23cd05..cc771de1d1 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNodeTest.java index 3ed566b7e6..b1f6c59407 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNodeTest.java index 796a7106fc..fd67fa16b8 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbCheckpointNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbCheckpointNodeTest.java new file mode 100644 index 0000000000..545f6112d8 --- /dev/null +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/flow/TbCheckpointNodeTest.java @@ -0,0 +1,55 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.flow; + +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.params.provider.Arguments; +import org.thingsboard.rule.engine.AbstractRuleNodeUpgradeTest; +import org.thingsboard.rule.engine.api.TbNode; + +import java.util.stream.Stream; + +import static org.mockito.Mockito.spy; + +@Slf4j +public class TbCheckpointNodeTest extends AbstractRuleNodeUpgradeTest { + + // Rule nodes upgrade + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() { + return Stream.of( + // default config for version 0 + Arguments.of(0, + "{\"queueName\":null}", + true, + "{}"), + // default config for version 0 with queueName + Arguments.of(0, + "{\"queueName\":\"Main\"}", + true, + "{}"), + // default config for version 1 with upgrade from version 0 + Arguments.of(0, + "{}", + false, + "{}") + ); + } + + @Override + protected TbNode getTestNode() { + return spy(TbCheckpointNode.class); + } +} diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/GeoUtilTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/GeoUtilTest.java index f53a876954..2172288236 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/GeoUtilTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/GeoUtilTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNodeTest.java index f4585d0f96..10968516e6 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeTest.java index bf4d090c1c..5ea816a1eb 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,15 @@ */ package org.thingsboard.rule.engine.mail; -import com.datastax.oss.driver.api.core.uuid.Uuids; -import org.junit.Test; -import org.junit.runner.RunWith; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbEmail; @@ -28,85 +31,134 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; -import org.thingsboard.server.common.data.id.RuleChainId; -import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.msg.TbMsg; -import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; -import java.io.IOException; +import java.util.UUID; +import java.util.stream.Stream; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -@RunWith(MockitoJUnitRunner.class) public class TbMsgToEmailNodeTest { - private TbMsgToEmailNode emailNode; + private static final int EXPECTED_TEMPERATURE = 30; + private static final String EXPECTED_DEVICE_NAME = "TH-001"; + private static final String EXPECTED_DEVICE_TYPE = "thermostat"; + private static final String EXPECTED_SUBJECT = "Device " + EXPECTED_DEVICE_TYPE + " temperature high"; + private static final String EXPECTED_BODY = "Device " + EXPECTED_DEVICE_NAME + " has high temperature " + EXPECTED_TEMPERATURE; + private static final String EXPECTED_TO_EMAIL = "user@email.io"; + private static final String DYNAMIC_MAIL_BODY_TYPE = "dynamic"; + + private EntityId originator; + private TbMsgToEmailNode node; + private TbMsgToEmailNodeConfiguration config; + + private TbContext ctxMock; + + @BeforeEach + void setUp() throws TbNodeException { + ctxMock = mock(TbContext.class); + originator = new DeviceId(UUID.randomUUID()); + config = new TbMsgToEmailNodeConfiguration().defaultConfiguration(); + node = new TbMsgToEmailNode(); + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + } + + @AfterEach + void tearDown() { + node.destroy(); + } - @Mock - private TbContext ctx; + @Test + void givenDefaultConfig_whenVerify_thenOK() { + // GIVEN-WHEN-THEN + assertThat(config.getFromTemplate()).isEqualTo("info@testmail.org"); + assertThat(config.getToTemplate()).isEqualTo("${userEmail}"); + assertThat(config.getSubjectTemplate()).isEqualTo("Device ${deviceType} temperature high"); + assertThat(config.getBodyTemplate()).isEqualTo("Device ${deviceName} has high temperature $[temperature]"); + } - private EntityId originator = new DeviceId(Uuids.timeBased()); - private TbMsgMetaData metaData = new TbMsgMetaData(); - private String rawJson = "{\"name\": \"temp\", \"passed\": 5 , \"complex\": {\"val\":12, \"count\":100}}"; + @ParameterizedTest + @MethodSource("MailBodyTypeTestConfig") + public void givenMailBodyTypeTestConfig_whenOnMsg_thenVerify(MailBodyTypeTestConfig testConfig) throws TbNodeException { + // GIVEN + String mailBodyType = testConfig.getMailBodyType(); + config.setMailBodyType(mailBodyType); + if (DYNAMIC_MAIL_BODY_TYPE.equals(mailBodyType)) { + config.setIsHtmlTemplate("${html}"); + } + node.init(ctxMock, new TbNodeConfiguration(JacksonUtil.valueToTree(config))); + + var md = new TbMsgMetaData(); + md.putValue("userEmail", EXPECTED_TO_EMAIL); + md.putValue("deviceType", EXPECTED_DEVICE_TYPE); + md.putValue("deviceName", EXPECTED_DEVICE_NAME); + if (testConfig.getIsHtmlTemplateMdValue() != null) { + md.putValue("html", testConfig.getIsHtmlTemplateMdValue()); + } - private RuleChainId ruleChainId = new RuleChainId(Uuids.timeBased()); - private RuleNodeId ruleNodeId = new RuleNodeId(Uuids.timeBased()); + var msgDataStr = "{\"temperature\": " + EXPECTED_TEMPERATURE + "}"; + TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, originator, md, msgDataStr); + + // WHEN + node.onMsg(ctxMock, msg); + + // THEN + var msgCaptor = ArgumentCaptor.forClass(TbMsg.class); + var typeCaptor = ArgumentCaptor.forClass(TbMsgType.class); + var originatorCaptor = ArgumentCaptor.forClass(EntityId.class); + var metadataCaptor = ArgumentCaptor.forClass(TbMsgMetaData.class); + var dataCaptor = ArgumentCaptor.forClass(String.class); + verify(ctxMock).transformMsg( + msgCaptor.capture(), + typeCaptor.capture(), + originatorCaptor.capture(), + metadataCaptor.capture(), + dataCaptor.capture() + ); + verify(ctxMock, never()).tellFailure(any(), any()); + + Assertions.assertEquals(TbMsgType.SEND_EMAIL, typeCaptor.getValue()); + Assertions.assertEquals(originator, originatorCaptor.getValue()); + Assertions.assertNotSame(md, metadataCaptor.getValue()); + + var actual = JacksonUtil.fromBytes(dataCaptor.getValue().getBytes(), TbEmail.class); + var expected = getExpectedTbEmail(testConfig.isExpectedHtmlValue()); + + Assertions.assertEquals(expected, actual); + } - @Test - public void msgCanBeConverted() { - initWithScript(); - metaData.putValue("username", "oreo"); - metaData.putValue("userEmail", "user@email.io"); - metaData.putValue("name", "temp"); - metaData.putValue("passed", "5"); - metaData.putValue("count", "100"); - TbMsg msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, originator, metaData, TbMsgDataType.JSON, rawJson, ruleChainId, ruleNodeId); - - emailNode.onMsg(ctx, msg); - - ArgumentCaptor msgCaptor = ArgumentCaptor.forClass(TbMsg.class); - ArgumentCaptor typeCaptor = ArgumentCaptor.forClass(TbMsgType.class); - ArgumentCaptor originatorCaptor = ArgumentCaptor.forClass(EntityId.class); - ArgumentCaptor metadataCaptor = ArgumentCaptor.forClass(TbMsgMetaData.class); - ArgumentCaptor dataCaptor = ArgumentCaptor.forClass(String.class); - verify(ctx).transformMsg(msgCaptor.capture(), typeCaptor.capture(), originatorCaptor.capture(), metadataCaptor.capture(), dataCaptor.capture()); - - - assertEquals(TbMsgType.SEND_EMAIL, typeCaptor.getValue()); - assertEquals(originator, originatorCaptor.getValue()); - assertEquals("oreo", metadataCaptor.getValue().getValue("username")); - assertNotSame(metaData, metadataCaptor.getValue()); - - TbEmail actual = JacksonUtil.fromBytes(dataCaptor.getValue().getBytes(), TbEmail.class); - - TbEmail expected = TbEmail.builder() - .from("test@mail.org") - .to("user@email.io") - .subject("Hi oreo there") - .body("temp is to high. Current 5 and 100") + private TbEmail getExpectedTbEmail(boolean html) { + return TbEmail.builder() + .from(config.getFromTemplate()) + .to(EXPECTED_TO_EMAIL) + .subject(EXPECTED_SUBJECT) + .body(EXPECTED_BODY) + .html(html) .build(); - assertEquals(expected, actual); } - private void initWithScript() { - try { - TbMsgToEmailNodeConfiguration config = new TbMsgToEmailNodeConfiguration(); - config.setFromTemplate("test@mail.org"); - config.setToTemplate("${userEmail}"); - config.setSubjectTemplate("Hi ${username} there"); - config.setBodyTemplate("${name} is to high. Current ${passed} and ${count}"); - config.setMailBodyType("false"); - TbNodeConfiguration nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); - - emailNode = new TbMsgToEmailNode(); - emailNode.init(ctx, nodeConfiguration); - } catch (TbNodeException ex) { - throw new IllegalStateException(ex); - } + static Stream MailBodyTypeTestConfig() { + return Stream.of( + new MailBodyTypeTestConfig(false, "false", null), + new MailBodyTypeTestConfig(false, null, null), + new MailBodyTypeTestConfig(false, DYNAMIC_MAIL_BODY_TYPE, "false"), + new MailBodyTypeTestConfig(true, DYNAMIC_MAIL_BODY_TYPE, "true"), + new MailBodyTypeTestConfig(true, "true", null) + ); + } + + @Data + @RequiredArgsConstructor + static class MailBodyTypeTestConfig { + private final boolean expectedHtmlValue; + private final String mailBodyType; + private final String isHtmlTemplateMdValue; } } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathArgumentValueTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathArgumentValueTest.java index eccc9bb932..5a6fffbb18 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathArgumentValueTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathArgumentValueTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathNodeTest.java index 9eec38cfae..3028840186 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/math/TbMathNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNodeTest.java index 0fd8793e82..707de1741f 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbFetchDeviceCredentialsNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbFetchDeviceCredentialsNodeTest.java index c5044eab37..5cbe20fc5e 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbFetchDeviceCredentialsNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbFetchDeviceCredentialsNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNodeTest.java index 1b8c95ab22..9b870cc55b 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java index 291614464a..da08c0cd2c 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,6 +59,7 @@ import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.dao.user.UserService; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -119,7 +120,7 @@ public class TbGetCustomerAttributeNodeTest { var exception = assertThrows(TbNodeException.class, () -> node.init(ctxMock, nodeConfiguration)); // THEN - assertThat(exception.getMessage()).isEqualTo("FetchTo cannot be null!"); + assertThat(exception.getMessage()).isEqualTo("FetchTo option can't be null! Allowed values: " + Arrays.toString(TbMsgSource.values())); verify(ctxMock, never()).tellSuccess(any()); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNodeTest.java index 51625eafe7..fa4df10609 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,6 +57,7 @@ import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.user.UserService; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; @@ -127,7 +128,7 @@ public class TbGetCustomerDetailsNodeTest { var exception = assertThrows(TbNodeException.class, () -> node.init(ctxMock, nodeConfiguration)); // THEN - assertThat(exception.getMessage()).isEqualTo("FetchTo cannot be null!"); + assertThat(exception.getMessage()).isEqualTo("FetchTo option can't be null! Allowed values: " + Arrays.toString(TbMsgSource.values())); verify(ctxMock, never()).tellSuccess(any()); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNodeTest.java index 550cc6a884..f40ab2bed8 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java index d681deb9c0..fdb73279c0 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,7 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.dao.device.DeviceService; +import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.UUID; @@ -86,7 +87,7 @@ public class TbGetOriginatorFieldsNodeTest { var exception = assertThrows(TbNodeException.class, () -> node.init(ctxMock, nodeConfiguration)); // THEN - assertThat(exception.getMessage()).isEqualTo("FetchTo cannot be null!"); + assertThat(exception.getMessage()).isEqualTo("FetchTo option can't be null! Allowed values: " + Arrays.toString(TbMsgSource.values())); verify(ctxMock, never()).tellSuccess(any()); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java index dcf5c22ea5..28c9c45822 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -127,7 +127,7 @@ public class TbGetRelatedAttributeNodeTest { var exception = assertThrows(TbNodeException.class, () -> node.init(ctxMock, nodeConfiguration)); // THEN - assertThat(exception.getMessage()).isEqualTo("FetchTo cannot be null!"); + assertThat(exception.getMessage()).isEqualTo("FetchTo option can't be null! Allowed values: " + Arrays.toString(TbMsgSource.values())); verify(ctxMock, never()).tellSuccess(any()); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java index a8b1cfb18b..990688611e 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java index 87b34cffe0..71e8f208ee 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +50,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.timeseries.TimeseriesService; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -99,7 +100,7 @@ public class TbGetTenantAttributeNodeTest { var exception = assertThrows(TbNodeException.class, () -> node.init(ctxMock, nodeConfiguration)); // THEN - assertThat(exception.getMessage()).isEqualTo("FetchTo cannot be null!"); + assertThat(exception.getMessage()).isEqualTo("FetchTo option can't be null! Allowed values: " + Arrays.toString(TbMsgSource.values())); verify(ctxMock, never()).tellSuccess(any()); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java index bfbaa9a92e..6649cf49de 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.dao.tenant.TenantService; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.UUID; @@ -96,7 +97,7 @@ public class TbGetTenantDetailsNodeTest { var exception = assertThrows(TbNodeException.class, () -> node.init(ctxMock, nodeConfiguration)); // THEN - assertThat(exception.getMessage()).isEqualTo("FetchTo cannot be null!"); + assertThat(exception.getMessage()).isEqualTo("FetchTo option can't be null! Allowed values: " + Arrays.toString(TbMsgSource.values())); verify(ctxMock, never()).tellSuccess(any()); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmStateTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmStateTest.java index 50223ff262..7cc6781abb 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmStateTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmStateTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/DeviceStateTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/DeviceStateTest.java index eef77a5304..6058b7960d 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/DeviceStateTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/DeviceStateTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java index ad23b7492b..37277b70f8 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java index d71d4aacbe..b8e9aa3e38 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbHttpClientTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package org.thingsboard.rule.engine.rest; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; -import org.awaitility.Awaitility; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -41,6 +40,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; import java.net.URI; import java.util.List; import java.util.Map; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -169,21 +169,20 @@ public class TbHttpClientTest { capturedData.capture() )).thenReturn(successMsg); + CountDownLatch latch = new CountDownLatch(1); + httpClient.processMessage(ctx, msg, - m -> ctx.tellSuccess(msg), - ctx::tellFailure); - - Awaitility.await() - .atMost(30, TimeUnit.SECONDS) - .until(() -> { - try { - verify(ctx, times(1)).tellSuccess(any()); - return true; - } catch (Exception e) { - return false; - } + m -> { + ctx.tellSuccess(msg); + latch.countDown(); + }, + (m, t) -> { + ctx.tellFailure(m, t); + latch.countDown(); }); + latch.await(5, TimeUnit.SECONDS); + verify(ctx, times(1)).tellSuccess(any()); verify(ctx, times(0)).tellFailure(any(), any()); Assertions.assertEquals(successResponseBody, capturedData.getValue()); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java index 0a71a799fc..c3d0c5bd89 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rest/TbRestApiCallNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNodeTest.java index 7b12dbb2b1..454c1a9fe6 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeConfigurationTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeConfigurationTest.java index 2bc2c0ba0e..91c78d06f1 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeConfigurationTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeConfigurationTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat; class TbMsgAttributesNodeConfigurationTest { @Test - void testDefaultConfig_givenupdateAttributesOnlyOnValueChange_thenTrue_sinceVersion1() { + void testDefaultConfig_givenUpdateAttributesOnlyOnValueChange_thenTrue_sinceVersion1() { assertThat(new TbMsgAttributesNodeConfiguration().defaultConfiguration().isUpdateAttributesOnlyOnValueChange()).isTrue(); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java index 818c1bb97f..23e4b37c92 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,24 @@ */ package org.thingsboard.rule.engine.telemetry; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.rule.engine.AbstractRuleNodeUpgradeTest; +import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.server.common.data.DataConstants; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.BooleanDataEntry; @@ -28,27 +40,45 @@ import org.thingsboard.server.common.data.kv.DoubleDataEntry; import org.thingsboard.server.common.data.kv.JsonDataEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.kv.StringDataEntry; -import org.thingsboard.server.common.data.util.TbPair; +import org.thingsboard.server.common.data.msg.TbMsgType; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.UUID; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.willCallRealMethod; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.thingsboard.server.common.data.DataConstants.NOTIFY_DEVICE_METADATA_KEY; @Slf4j -class TbMsgAttributesNodeTest { +class TbMsgAttributesNodeTest extends AbstractRuleNodeUpgradeTest { - final String updateAttributesOnlyOnValueChangeKey = "updateAttributesOnlyOnValueChange"; + private TenantId tenantId; + private DeviceId deviceId; + private TbMsgAttributesNode node; + + @BeforeEach + void setUp() { + tenantId = new TenantId(UUID.fromString("6c18691e-4470-4766-9739-aface71d761f")); + deviceId = new DeviceId(UUID.fromString("b66159d7-c77e-45e8-bb41-a8f557f434c1")); + node = spy(TbMsgAttributesNode.class); + } @Test void testFilterChangedAttr_whenCurrentAttributesEmpty_thenReturnNewAttributes() { - TbMsgAttributesNode node = spy(TbMsgAttributesNode.class); List newAttributes = new ArrayList<>(); List filtered = node.filterChangedAttr(Collections.emptyList(), newAttributes); @@ -57,7 +87,6 @@ class TbMsgAttributesNodeTest { @Test void testFilterChangedAttr_whenCurrentAttributesContainsInAnyOrderNewAttributes_thenReturnEmptyList() { - TbMsgAttributesNode node = spy(TbMsgAttributesNode.class); List currentAttributes = List.of( new BaseAttributeKvEntry(1694000000L, new StringDataEntry("address", "Peremohy ave 1")), new BaseAttributeKvEntry(1694000000L, new BooleanDataEntry("valid", true)), @@ -78,7 +107,6 @@ class TbMsgAttributesNodeTest { @Test void testFilterChangedAttr_whenCurrentAttributesContainsInAnyOrderNewAttributes_thenReturnExpectedList() { - TbMsgAttributesNode node = spy(TbMsgAttributesNode.class); List currentAttributes = List.of( new BaseAttributeKvEntry(1694000000L, new StringDataEntry("address", "Peremohy ave 1")), new BaseAttributeKvEntry(1694000000L, new BooleanDataEntry("valid", true)), @@ -103,41 +131,100 @@ class TbMsgAttributesNodeTest { assertThat(filtered).containsExactlyInAnyOrderElementsOf(expected); } - @Test - void testUpgrade_fromVersion0() throws TbNodeException { + // Notify device backward-compatibility test arguments + private static Stream givenNotifyDeviceMdValue_whenSaveAndNotify_thenVerifyExpectedArgumentForNotifyDeviceInSaveAndNotifyMethod() { + return Stream.of( + Arguments.of(null, true), + Arguments.of("null", false), + Arguments.of("true", true), + Arguments.of("false", false) + ); + } + + // Notify device backward-compatibility test + @ParameterizedTest + @MethodSource + void givenNotifyDeviceMdValue_whenSaveAndNotify_thenVerifyExpectedArgumentForNotifyDeviceInSaveAndNotifyMethod(String mdValue, boolean expectedArgumentValue) throws TbNodeException { + var ctxMock = mock(TbContext.class); + var telemetryServiceMock = mock(RuleEngineTelemetryService.class); + ObjectNode defaultConfig = (ObjectNode) JacksonUtil.valueToTree(new TbMsgAttributesNodeConfiguration().defaultConfiguration()); + defaultConfig.put("notifyDevice", false); + var tbNodeConfiguration = new TbNodeConfiguration(defaultConfig); + + assertThat(defaultConfig.has("notifyDevice")).as("pre condition has notifyDevice").isTrue(); + + when(ctxMock.getTenantId()).thenReturn(tenantId); + when(ctxMock.getTelemetryService()).thenReturn(telemetryServiceMock); + willCallRealMethod().given(node).init(any(TbContext.class), any(TbNodeConfiguration.class)); + willCallRealMethod().given(node).saveAttr(any(), eq(ctxMock), any(TbMsg.class), anyString(), anyBoolean()); - TbMsgAttributesNode node = mock(TbMsgAttributesNode.class); - willCallRealMethod().given(node).upgrade(anyInt(), any()); + node.init(ctxMock, tbNodeConfiguration); - ObjectNode jsonNode = (ObjectNode) JacksonUtil.valueToTree(new TbMsgAttributesNodeConfiguration().defaultConfiguration()); - jsonNode.remove(updateAttributesOnlyOnValueChangeKey); - assertThat(jsonNode.has(updateAttributesOnlyOnValueChangeKey)).as("pre condition has no " + updateAttributesOnlyOnValueChangeKey).isFalse(); + TbMsgMetaData md = new TbMsgMetaData(); + if (mdValue != null) { + md.putValue(NOTIFY_DEVICE_METADATA_KEY, mdValue); + } + // dummy list with one ts kv to pass the empty list check. + var testTbMsg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, deviceId, md, TbMsg.EMPTY_STRING); + List testAttrList = List.of(new BaseAttributeKvEntry(0L, new StringDataEntry("testKey", "testValue"))); - TbPair upgradeResult = node.upgrade(0, jsonNode); + node.saveAttr(testAttrList, ctxMock, testTbMsg, DataConstants.SHARED_SCOPE, false); - ObjectNode resultNode = (ObjectNode) upgradeResult.getSecond(); - assertThat(upgradeResult.getFirst()).as("upgrade result has changes").isTrue(); - assertThat(resultNode.has(updateAttributesOnlyOnValueChangeKey)).as("upgrade result has key " + updateAttributesOnlyOnValueChangeKey).isTrue(); - assertThat(resultNode.get(updateAttributesOnlyOnValueChangeKey).asBoolean()).as("upgrade result value [false] for key " + updateAttributesOnlyOnValueChangeKey).isFalse(); + ArgumentCaptor notifyDeviceCaptor = ArgumentCaptor.forClass(Boolean.class); + + verify(telemetryServiceMock, times(1)).saveAndNotify( + eq(tenantId), eq(deviceId), eq(DataConstants.SHARED_SCOPE), + eq(testAttrList), notifyDeviceCaptor.capture(), any() + ); + boolean notifyDevice = notifyDeviceCaptor.getValue(); + assertThat(notifyDevice).isEqualTo(expectedArgumentValue); } - @Test - void testUpgrade_fromVersion0_alreadyHasupdateAttributesOnlyOnValueChange() throws TbNodeException { - TbMsgAttributesNode node = mock(TbMsgAttributesNode.class); - willCallRealMethod().given(node).upgrade(anyInt(), any()); - - ObjectNode jsonNode = (ObjectNode) JacksonUtil.valueToTree(new TbMsgAttributesNodeConfiguration().defaultConfiguration()); - jsonNode.remove(updateAttributesOnlyOnValueChangeKey); - jsonNode.put(updateAttributesOnlyOnValueChangeKey, true); - assertThat(jsonNode.has(updateAttributesOnlyOnValueChangeKey)).as("pre condition has no " + updateAttributesOnlyOnValueChangeKey).isTrue(); - assertThat(jsonNode.get(updateAttributesOnlyOnValueChangeKey).asBoolean()).as("pre condition has [true] for key " + updateAttributesOnlyOnValueChangeKey).isTrue(); - - TbPair upgradeResult = node.upgrade(0, jsonNode); - - ObjectNode resultNode = (ObjectNode) upgradeResult.getSecond(); - assertThat(upgradeResult.getFirst()).as("upgrade result has changes").isFalse(); - assertThat(resultNode.has(updateAttributesOnlyOnValueChangeKey)).as("upgrade result has key " + updateAttributesOnlyOnValueChangeKey).isTrue(); - assertThat(resultNode.get(updateAttributesOnlyOnValueChangeKey).asBoolean()).as("upgrade result value [true] for key " + updateAttributesOnlyOnValueChangeKey).isTrue(); + + // Rule nodes upgrade + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() { + return Stream.of( + // default config for version 0 + Arguments.of(0, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":\"false\",\"sendAttributesUpdatedNotification\":\"false\"}", + true, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":false,\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":false}"), + // default config for version 1 with upgrade from version 0 + Arguments.of(0, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":false,\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}", + false, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":false,\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}"), + // all flags are booleans + Arguments.of(1, + "{\"scope\":\"SHARED_SCOPE\",\"notifyDevice\":true,\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}", + false, + "{\"scope\":\"SHARED_SCOPE\",\"notifyDevice\":true,\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}"), + // no boolean flags set + Arguments.of(1, + "{\"scope\":\"CLIENT_SCOPE\"}", + true, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":true,\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}"), + // all flags are boolean strings + Arguments.of(1, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":\"false\",\"sendAttributesUpdatedNotification\":\"false\",\"updateAttributesOnlyOnValueChange\":\"true\"}", + true, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":false,\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}"), + // at least one flag is boolean string + Arguments.of(1, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":\"false\",\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}", + true, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":false,\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}"), + // notify device flag is null + Arguments.of(1, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":\"null\",\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}", + true, + "{\"scope\":\"CLIENT_SCOPE\",\"notifyDevice\":true,\"sendAttributesUpdatedNotification\":false,\"updateAttributesOnlyOnValueChange\":true}") + ); + } + + @Override + protected TbNode getTestNode() { + return node; } } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNodeTest.java index 632243676f..35069af08d 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNodeTest.java index 8ea7806ae2..e9803289bb 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbCopyKeysNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbCopyKeysNodeTest.java index e0ab34e35b..b680981e34 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbCopyKeysNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbCopyKeysNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,19 @@ package org.thingsboard.rule.engine.transform; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.util.TbMsgSource; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.msg.TbMsgType; @@ -35,13 +40,13 @@ import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; public class TbCopyKeysNodeTest { @@ -59,7 +64,7 @@ public class TbCopyKeysNodeTest { ctx = mock(TbContext.class); config = new TbCopyKeysNodeConfiguration().defaultConfiguration(); config.setKeys(Set.of("TestKey_1", "TestKey_2", "TestKey_3", "(\\w*)Data(\\w*)")); - config.setFromMetadata(true); + config.setCopyFrom(TbMsgSource.METADATA); nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); node = spy(new TbCopyKeysNode()); node.init(ctx, nodeConfiguration); @@ -74,7 +79,7 @@ public class TbCopyKeysNodeTest { void givenDefaultConfig_whenVerify_thenOK() { TbCopyKeysNodeConfiguration defaultConfig = new TbCopyKeysNodeConfiguration().defaultConfiguration(); assertThat(defaultConfig.getKeys()).isEqualTo(Collections.emptySet()); - assertThat(defaultConfig.isFromMetadata()).isEqualTo(false); + assertThat(defaultConfig.getCopyFrom()).isEqualTo(TbMsgSource.DATA); } @Test @@ -82,7 +87,7 @@ public class TbCopyKeysNodeTest { node.onMsg(ctx, getTbMsg(deviceId, TbMsg.EMPTY_JSON_OBJECT)); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); - verify(ctx, times(1)).tellSuccess(newMsgCaptor.capture()); + verify(ctx).tellSuccess(newMsgCaptor.capture()); verify(ctx, never()).tellFailure(any(), any()); TbMsg newMsg = newMsgCaptor.getValue(); @@ -95,23 +100,30 @@ public class TbCopyKeysNodeTest { @Test void givenMsgFromMsg_whenOnMsg_thenVerifyOutput() throws Exception { - config.setFromMetadata(false); + config.setCopyFrom(TbMsgSource.DATA); + config.setKeys(Set.of(".*Key$")); nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); node.init(ctx, nodeConfiguration); - String data = "{\"DigitData\":22.5,\"TempDataValue\":10.5}"; + String data = "{\"nullKey\":null,\"stringKey\":\"value1\",\"booleanKey\":true,\"doubleKey\":42.0,\"longKey\":73," + + "\"jsonKey\":{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}}"; node.onMsg(ctx, getTbMsg(deviceId, data)); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); - verify(ctx, times(1)).tellSuccess(newMsgCaptor.capture()); + verify(ctx).tellSuccess(newMsgCaptor.capture()); verify(ctx, never()).tellFailure(any(), any()); TbMsg newMsg = newMsgCaptor.getValue(); assertThat(newMsg).isNotNull(); Map metaDataMap = newMsg.getMetaData().getData(); - assertThat(metaDataMap.containsKey("DigitData")).isEqualTo(true); - assertThat(metaDataMap.containsKey("TempDataValue")).isEqualTo(true); + assertThat(metaDataMap.get("nullKey")).isEqualTo("null"); + assertThat(metaDataMap.get("stringKey")).isEqualTo("value1"); + assertThat(metaDataMap.get("booleanKey")).isEqualTo("true"); + assertThat(metaDataMap.get("doubleKey")).isEqualTo("42.0"); + assertThat(metaDataMap.get("longKey")).isEqualTo("73"); + assertThat(metaDataMap.get("jsonKey")) + .isEqualTo("{\"someNumber\":42,\"someArray\":[1,2,3],\"someNestedObject\":{\"key\":\"value\"}}"); } @Test @@ -125,7 +137,7 @@ public class TbCopyKeysNodeTest { node.onMsg(ctx, msg); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); - verify(ctx, times(1)).tellSuccess(newMsgCaptor.capture()); + verify(ctx).tellSuccess(newMsgCaptor.capture()); verify(ctx, never()).tellFailure(any(), any()); TbMsg newMsg = newMsgCaptor.getValue(); @@ -140,7 +152,7 @@ public class TbCopyKeysNodeTest { node.onMsg(ctx, msg); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); - verify(ctx, times(1)).tellSuccess(newMsgCaptor.capture()); + verify(ctx).tellSuccess(newMsgCaptor.capture()); verify(ctx, never()).tellFailure(any(), any()); TbMsg newMsg = newMsgCaptor.getValue(); @@ -149,6 +161,34 @@ public class TbCopyKeysNodeTest { assertThat(newMsg).isSameAs(msg); } + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyUpgradeResultAndConfig() { + return Stream.of( + Arguments.of(0, "{\"fromMetadata\":false,\"keys\":[\"temperature\"]}", true, "{\"copyFrom\":\"DATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(0, "{\"fromMetadata\":true,\"keys\":[\"temperature\"]}", true, "{\"copyFrom\":\"METADATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(1, "{\"fromMetadata\":\"METADATA\",\"keys\":[\"temperature\"]}", true, "{\"copyFrom\":\"METADATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(1, "{\"fromMetadata\":\"DATA\",\"keys\":[\"temperature\"]}", true, "{\"copyFrom\":\"DATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(1, "{\"copyFrom\":\"METADATA\",\"keys\":[\"temperature\"]}", false, "{\"copyFrom\":\"METADATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(1, "{\"copyFrom\":\"DATA\",\"keys\":[\"temperature\"]}", false, "{\"copyFrom\":\"DATA\",\"keys\":[\"temperature\"]}") + ); + } + + @ParameterizedTest + @MethodSource + void givenFromVersionAndConfig_whenUpgrade_thenVerifyUpgradeResultAndConfig(int givenVersion, String givenConfigStr, + boolean hasChanges, String expectedConfigStr) throws Exception { + // GIVEN + JsonNode givenConfig = JacksonUtil.toJsonNode(givenConfigStr); + JsonNode expectedConfig = JacksonUtil.toJsonNode(expectedConfigStr); + + // WHEN + var upgradeResult = node.upgrade(givenVersion, givenConfig); + + // THEN + assertThat(upgradeResult.getFirst()).isEqualTo(hasChanges); + ObjectNode upgradedConfig = (ObjectNode) upgradeResult.getSecond(); + assertThat(upgradedConfig).isEqualTo(expectedConfig); + } + private TbMsg getTbMsg(EntityId entityId, String data) { final Map mdMap = Map.of( "TestKey_1", "Test", diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbDeleteKeysNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbDeleteKeysNodeTest.java index 6eee16e7d3..670b117a2c 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbDeleteKeysNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbDeleteKeysNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,19 @@ package org.thingsboard.rule.engine.transform; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.util.TbMsgSource; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.msg.TbMsgType; @@ -35,13 +40,13 @@ import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; public class TbDeleteKeysNodeTest { @@ -59,7 +64,7 @@ public class TbDeleteKeysNodeTest { ctx = mock(TbContext.class); config = new TbDeleteKeysNodeConfiguration().defaultConfiguration(); config.setKeys(Set.of("TestKey_1", "TestKey_2", "TestKey_3", "(\\w*)Data(\\w*)")); - config.setFromMetadata(true); + config.setDeleteFrom(TbMsgSource.METADATA); nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); node = spy(new TbDeleteKeysNode()); node.init(ctx, nodeConfiguration); @@ -74,15 +79,15 @@ public class TbDeleteKeysNodeTest { void givenDefaultConfig_whenVerify_thenOK() { TbDeleteKeysNodeConfiguration defaultConfig = new TbDeleteKeysNodeConfiguration().defaultConfiguration(); assertThat(defaultConfig.getKeys()).isEqualTo(Collections.emptySet()); - assertThat(defaultConfig.isFromMetadata()).isEqualTo(false); + assertThat(defaultConfig.getDeleteFrom()).isEqualTo(TbMsgSource.DATA); } @Test - void givenMsgFromMetadata_whenOnMsg_thenVerifyOutput() throws Exception { + void givenDeleteFromMetadata_whenOnMsg_thenVerifyOutput() throws Exception { node.onMsg(ctx, getTbMsg(deviceId, TbMsg.EMPTY_JSON_OBJECT)); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); - verify(ctx, times(1)).tellSuccess(newMsgCaptor.capture()); + verify(ctx).tellSuccess(newMsgCaptor.capture()); verify(ctx, never()).tellFailure(any(), any()); TbMsg newMsg = newMsgCaptor.getValue(); @@ -94,8 +99,8 @@ public class TbDeleteKeysNodeTest { } @Test - void givenMsgFromMsg_whenOnMsg_thenVerifyOutput() throws Exception { - config.setFromMetadata(false); + void givenDeleteFromMsgConfig_whenOnMsg_thenVerifyOutput() throws Exception { + config.setDeleteFrom(TbMsgSource.DATA); nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); node.init(ctx, nodeConfiguration); @@ -103,7 +108,7 @@ public class TbDeleteKeysNodeTest { node.onMsg(ctx, getTbMsg(deviceId, data)); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); - verify(ctx, times(1)).tellSuccess(newMsgCaptor.capture()); + verify(ctx).tellSuccess(newMsgCaptor.capture()); verify(ctx, never()).tellFailure(any(), any()); TbMsg newMsg = newMsgCaptor.getValue(); @@ -124,7 +129,7 @@ public class TbDeleteKeysNodeTest { node.onMsg(ctx, getTbMsg(deviceId, data)); ArgumentCaptor newMsgCaptor = ArgumentCaptor.forClass(TbMsg.class); - verify(ctx, times(1)).tellSuccess(newMsgCaptor.capture()); + verify(ctx).tellSuccess(newMsgCaptor.capture()); verify(ctx, never()).tellFailure(any(), any()); TbMsg newMsg = newMsgCaptor.getValue(); @@ -133,6 +138,34 @@ public class TbDeleteKeysNodeTest { assertThat(newMsg.getData()).isEqualTo(data); } + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyUpgradeResultAndConfig() { + return Stream.of( + Arguments.of(0, "{\"fromMetadata\":false,\"keys\":[\"temperature\"]}", true, "{\"deleteFrom\":\"DATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(0, "{\"fromMetadata\":true,\"keys\":[\"temperature\"]}", true, "{\"deleteFrom\":\"METADATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(1, "{\"dataToFetch\":\"METADATA\",\"keys\":[\"temperature\"]}", true, "{\"deleteFrom\":\"METADATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(1, "{\"dataToFetch\":\"DATA\",\"keys\":[\"temperature\"]}", true, "{\"deleteFrom\":\"DATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(1, "{\"deleteFrom\":\"METADATA\",\"keys\":[\"temperature\"]}", false, "{\"deleteFrom\":\"METADATA\",\"keys\":[\"temperature\"]}"), + Arguments.of(1, "{\"deleteFrom\":\"DATA\",\"keys\":[\"temperature\"]}", false, "{\"deleteFrom\":\"DATA\",\"keys\":[\"temperature\"]}") + ); + } + + @ParameterizedTest + @MethodSource + void givenFromVersionAndConfig_whenUpgrade_thenVerifyUpgradeResultAndConfig(int givenVersion, String givenConfigStr, + boolean hasChanges, String expectedConfigStr) throws Exception { + // GIVEN + JsonNode givenConfig = JacksonUtil.toJsonNode(givenConfigStr); + JsonNode expectedConfig = JacksonUtil.toJsonNode(expectedConfigStr); + + // WHEN + var upgradeResult = node.upgrade(givenVersion, givenConfig); + + // THEN + assertThat(upgradeResult.getFirst()).isEqualTo(hasChanges); + ObjectNode upgradedConfig = (ObjectNode) upgradeResult.getSecond(); + assertThat(upgradedConfig).isEqualTo(expectedConfig); + } + private TbMsg getTbMsg(EntityId entityId, String data) { final Map mdMap = Map.of( "TestKey_1", "Test", diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbJsonPathNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbJsonPathNodeTest.java index a86d902007..2c09bf555c 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbJsonPathNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbJsonPathNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbMsgDeduplicationNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbMsgDeduplicationNodeTest.java index be6aea6fa5..7832bbc1dc 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbMsgDeduplicationNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbMsgDeduplicationNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,12 +22,17 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; import org.mockito.stubbing.Answer; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.ThingsBoardThreadFactory; +import org.thingsboard.rule.engine.AbstractRuleNodeUpgradeTest; import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.deduplication.DeduplicationStrategy; @@ -55,6 +60,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; +import java.util.stream.Stream; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -68,7 +74,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @Slf4j -public class TbMsgDeduplicationNodeTest { +public class TbMsgDeduplicationNodeTest extends AbstractRuleNodeUpgradeTest { private TbContext ctx; @@ -139,13 +145,24 @@ public class TbMsgDeduplicationNodeTest { node.destroy(); } - @Test - public void given_100_messages_strategy_first_then_verifyOutput() throws TbNodeException, ExecutionException, InterruptedException { + private static Stream given_100_messages_strategy_first_then_verifyOutput() { + return Stream.of( + Arguments.of((String) null), + Arguments.of(DataConstants.MAIN_QUEUE_NAME), + Arguments.of(DataConstants.HP_QUEUE_NAME) + ); + } + + @ParameterizedTest + @MethodSource + public void given_100_messages_strategy_first_then_verifyOutput(String queueName) throws TbNodeException, ExecutionException, InterruptedException { int wantedNumberOfTellSelfInvocation = 2; int msgCount = 100; awaitTellSelfLatch = new CountDownLatch(wantedNumberOfTellSelfInvocation); invokeTellSelf(wantedNumberOfTellSelfInvocation); + when(ctx.getQueueName()).thenReturn(queueName); + config.setInterval(deduplicationInterval); config.setMaxPendingMsgs(msgCount); nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); @@ -182,6 +199,12 @@ public class TbMsgDeduplicationNodeTest { Assertions.assertEquals(firstMsg.getData(), actualMsg.getData()); Assertions.assertEquals(firstMsg.getMetaData(), actualMsg.getMetaData()); Assertions.assertEquals(firstMsg.getType(), actualMsg.getType()); + + if (queueName == null) { + Assertions.assertEquals(firstMsg.getQueueName(), actualMsg.getQueueName()); + } else { + Assertions.assertEquals(ctx.getQueueName(), actualMsg.getQueueName()); + } } @Test @@ -238,10 +261,10 @@ public class TbMsgDeduplicationNodeTest { awaitTellSelfLatch = new CountDownLatch(wantedNumberOfTellSelfInvocation); invokeTellSelf(wantedNumberOfTellSelfInvocation); + when(ctx.getQueueName()).thenReturn(DataConstants.HP_QUEUE_NAME); config.setInterval(deduplicationInterval); config.setStrategy(DeduplicationStrategy.ALL); config.setOutMsgType(TbMsgType.POST_ATTRIBUTES_REQUEST.name()); - config.setQueueName(DataConstants.HP_QUEUE_NAME); nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); node.init(ctx, nodeConfiguration); @@ -268,7 +291,7 @@ public class TbMsgDeduplicationNodeTest { Assertions.assertEquals(getMergedData(inputMsgs), outMessage.getData()); Assertions.assertEquals(deviceId, outMessage.getOriginator()); Assertions.assertEquals(config.getOutMsgType(), outMessage.getType()); - Assertions.assertEquals(config.getQueueName(), outMessage.getQueueName()); + Assertions.assertEquals(DataConstants.HP_QUEUE_NAME, outMessage.getQueueName()); } @Test @@ -278,10 +301,10 @@ public class TbMsgDeduplicationNodeTest { awaitTellSelfLatch = new CountDownLatch(wantedNumberOfTellSelfInvocation); invokeTellSelf(wantedNumberOfTellSelfInvocation, true, 3); + when(ctx.getQueueName()).thenReturn(DataConstants.HP_QUEUE_NAME); config.setInterval(deduplicationInterval); config.setStrategy(DeduplicationStrategy.ALL); config.setOutMsgType(TbMsgType.POST_ATTRIBUTES_REQUEST.name()); - config.setQueueName(DataConstants.HP_QUEUE_NAME); nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); node.init(ctx, nodeConfiguration); @@ -292,7 +315,7 @@ public class TbMsgDeduplicationNodeTest { for (TbMsg msg : firstMsgPack) { node.onMsg(ctx, msg); } - long firstPackDeduplicationPackEndTs = firstMsgPack.get(0).getMetaDataTs() + TimeUnit.SECONDS.toMillis(deduplicationInterval); + long firstPackDeduplicationPackEndTs = firstMsgPack.get(0).getMetaDataTs() + TimeUnit.SECONDS.toMillis(deduplicationInterval); List secondMsgPack = getTbMsgs(deviceId, msgCount / 2, firstPackDeduplicationPackEndTs, 500); for (TbMsg msg : secondMsgPack) { @@ -316,13 +339,13 @@ public class TbMsgDeduplicationNodeTest { Assertions.assertEquals(getMergedData(firstMsgPack), firstMsg.getData()); Assertions.assertEquals(deviceId, firstMsg.getOriginator()); Assertions.assertEquals(config.getOutMsgType(), firstMsg.getType()); - Assertions.assertEquals(config.getQueueName(), firstMsg.getQueueName()); + Assertions.assertEquals(DataConstants.HP_QUEUE_NAME, firstMsg.getQueueName()); TbMsg secondMsg = resultMsgs.get(1); Assertions.assertEquals(getMergedData(secondMsgPack), secondMsg.getData()); Assertions.assertEquals(deviceId, secondMsg.getOriginator()); Assertions.assertEquals(config.getOutMsgType(), secondMsg.getType()); - Assertions.assertEquals(config.getQueueName(), secondMsg.getQueueName()); + Assertions.assertEquals(DataConstants.HP_QUEUE_NAME, secondMsg.getQueueName()); } @Test @@ -385,6 +408,27 @@ public class TbMsgDeduplicationNodeTest { Assertions.assertEquals(msgWithLatestTsInSecondPack.getType(), actualMsg.getType()); } + // Rule nodes upgrade + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyHasChangesAndConfig() { + return Stream.of( + // default config for version 0 + Arguments.of(0, + "{\"interval\":60,\"strategy\":\"FIRST\",\"outMsgType\":null,\"maxPendingMsgs\":100,\"maxRetries\":3, \"queueName\":null}", + true, + "{\"interval\":60,\"strategy\":\"FIRST\",\"outMsgType\":null,\"maxPendingMsgs\":100,\"maxRetries\":3}"), + // default config for version 0 with queueName + Arguments.of(0, + "{\"interval\":60,\"strategy\":\"FIRST\",\"outMsgType\":null,\"maxPendingMsgs\":100,\"maxRetries\":3, \"queueName\":\"Main\"}", + true, + "{\"interval\":60,\"strategy\":\"FIRST\",\"outMsgType\":null,\"maxPendingMsgs\":100,\"maxRetries\":3}"), + // default config for version 1 with upgrade from version 0 + Arguments.of(0, + "{\"interval\":60,\"strategy\":\"FIRST\",\"outMsgType\":null,\"maxPendingMsgs\":100,\"maxRetries\":3}", + false, + "{\"interval\":60,\"strategy\":\"FIRST\",\"outMsgType\":null,\"maxPendingMsgs\":100,\"maxRetries\":3}") + ); + } + private TbMsg getMsgWithLatestTs(List firstMsgPack) { int indexOfLastMsgInArray = firstMsgPack.size() - 1; int indexToSetMaxTs = new Random().nextInt(indexOfLastMsgInArray) + 1; @@ -429,4 +473,9 @@ public class TbMsgDeduplicationNodeTest { return JacksonUtil.toString(mergedData); } + @Override + protected TbNode getTestNode() { + return node; + } + } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbRenameKeysNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbRenameKeysNodeTest.java index c602aab5df..03580920ce 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbRenameKeysNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbRenameKeysNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,14 +16,19 @@ package org.thingsboard.rule.engine.transform; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.util.TbMsgSource; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.msg.TbMsgType; @@ -33,6 +38,7 @@ import org.thingsboard.server.common.msg.queue.TbMsgCallback; import java.util.Map; import java.util.UUID; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -70,8 +76,8 @@ public class TbRenameKeysNodeTest { @Test void givenDefaultConfig_whenVerify_thenOK() { TbRenameKeysNodeConfiguration defaultConfig = new TbRenameKeysNodeConfiguration().defaultConfiguration(); - assertThat(defaultConfig.getRenameKeysMapping()).isEqualTo(Map.of("temp", "temperature")); - assertThat(defaultConfig.isFromMetadata()).isEqualTo(false); + assertThat(defaultConfig.getRenameKeysMapping()).isEqualTo(Map.of("temperatureCelsius", "temperature")); + assertThat(defaultConfig.getRenameIn()).isEqualTo(TbMsgSource.DATA); } @Test @@ -95,7 +101,7 @@ public class TbRenameKeysNodeTest { void givenMetadata_whenOnMsg_thenVerifyOutput() throws Exception { config = new TbRenameKeysNodeConfiguration().defaultConfiguration(); config.setRenameKeysMapping(Map.of("TestKey_1", "Attribute_1", "TestKey_2", "Attribute_2")); - config.setFromMetadata(true); + config.setRenameIn(TbMsgSource.METADATA); nodeConfiguration = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); node.init(ctx, nodeConfiguration); @@ -148,6 +154,34 @@ public class TbRenameKeysNodeTest { assertThat(newMsg).isSameAs(msg); } + private static Stream givenFromVersionAndConfig_whenUpgrade_thenVerifyUpgradeResultAndConfig() { + return Stream.of( + Arguments.of(0, "{\"fromMetadata\":false,\"renameKeysMapping\":{\"temp\":\"temperature\"}}", true, "{\"renameIn\":\"DATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}"), + Arguments.of(0, "{\"fromMetadata\":true,\"renameKeysMapping\":{\"temp\":\"temperature\"}}", true, "{\"renameIn\":\"METADATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}"), + Arguments.of(1, "{\"fromMetadata\":\"METADATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}", true, "{\"renameIn\":\"METADATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}"), + Arguments.of(1, "{\"fromMetadata\":\"DATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}", true, "{\"renameIn\":\"DATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}"), + Arguments.of(1, "{\"renameIn\":\"METADATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}", false, "{\"renameIn\":\"METADATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}"), + Arguments.of(1, "{\"renameIn\":\"DATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}", false, "{\"renameIn\":\"DATA\",\"renameKeysMapping\":{\"temp\":\"temperature\"}}") + ); + } + + @ParameterizedTest + @MethodSource + void givenFromVersionAndConfig_whenUpgrade_thenVerifyUpgradeResultAndConfig(int givenVersion, String givenConfigStr, + boolean hasChanges, String expectedConfigStr) throws Exception { + // GIVEN + JsonNode givenConfig = JacksonUtil.toJsonNode(givenConfigStr); + JsonNode expectedConfig = JacksonUtil.toJsonNode(expectedConfigStr); + + // WHEN + var upgradeResult = node.upgrade(givenVersion, givenConfig); + + // THEN + assertThat(upgradeResult.getFirst()).isEqualTo(hasChanges); + ObjectNode upgradedConfig = (ObjectNode) upgradeResult.getSecond(); + assertThat(upgradedConfig).isEqualTo(expectedConfig); + } + private TbMsg getTbMsg(EntityId entityId, String data) { final Map mdMap = Map.of( "TestKey_1", "Test", diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNodeTest.java index e7e2ae16b2..8abf83fa48 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java index 56c94fd4ff..a410b84532 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/transform/TbTransformMsgNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesCustomerIdAsyncLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesCustomerIdAsyncLoaderTest.java index c675b97d08..d04e170fc4 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesCustomerIdAsyncLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesCustomerIdAsyncLoaderTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoaderTest.java index d60f2256e1..5967023354 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesFieldsAsyncLoaderTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoaderTest.java index c54072fb53..43c46eee81 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedDeviceIdAsyncLoaderTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java index e51a3704d1..6265ec47b1 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/EntitiesRelatedEntityIdAsyncLoaderTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java index 0871a82550..5648b02454 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/util/TenantIdLoaderTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tools/pom.xml b/tools/pom.xml index 925946e8c5..9a2cfe21d2 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -1,6 +1,6 @@ - diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss index 3aed0ccb5e..505db79a36 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - .user-avatar { display: inline-flex; justify-content: center; diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts index 1fb1d3f689..0fc489fbfe 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-assignee.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.html b/ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.html index 8618592ae0..8145c31b06 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-comment-dialog.component.html @@ -1,6 +1,6 @@ -
- + {{ getSortDirectionIcon() }} + +
- - - - - Windows - - - - - - - - - - Linux - - - - - - - - - - MacOS - - - - - - - -
- -
-
device.connectivity.execute-following-command
+
+
gateway.launch-gateway
+
gateway.launch-docker-compose
- +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.scss index befa034375..6a1ea79a80 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,28 +14,35 @@ * limitations under the License. */ :host { - width: 100%; - height: 100%; - display: block; + .tb-commands-hint { + color: inherit; + font-weight: normal; + flex: 1; + } } :host ::ng-deep { .tb-markdown-view { .start-code { - code[class*="language-"] { - white-space: break-spaces; - word-break: break-all; - } - pre[class*="language-"] { - overflow: hidden; - background: #F3F6FA; - border-color: #305680; - } .code-wrapper { padding: 0; + + pre[class*=language-] { + margin: 0; + background: #F3F6FA; + border-color: #305680; + padding-right: 38px; + overflow: scroll; + padding-bottom: 4px; + + &::-webkit-scrollbar { + width: 4px; + height: 4px; + } + } } button.clipboard-btn { - right: 0; + right: -2px; p { color: #305680; } @@ -60,9 +67,5 @@ } } } - - .tb-form-panel.tb-tab-body { - margin-top: 16px; - } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.ts index d5516dd59b..8465b5879d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -14,11 +14,8 @@ /// limitations under the License. /// -import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { DeviceService } from '@core/http/device.service'; -import { helpBaseUrl } from '@shared/models/constants'; -import { getOS } from '@core/utils'; -import { PublishLaunchCommand } from '@shared/models/device.models'; @Component({ selector: 'tb-gateway-command', @@ -26,47 +23,20 @@ import { PublishLaunchCommand } from '@shared/models/device.models'; styleUrls: ['./device-gateway-command.component.scss'] }) -export class DeviceGatewayCommandComponent implements OnInit { - - @Input() - token: string; +export class DeviceGatewayCommandComponent { @Input() deviceId: string; - commands: PublishLaunchCommand; - - helpLink: string = helpBaseUrl + '/docs/iot-gateway/install/docker-installation/'; - - tabIndex = 0; - - constructor(private cd: ChangeDetectorRef, - private deviceService: DeviceService) { + constructor(private deviceService: DeviceService) { } - - ngOnInit(): void { - if (this.deviceId) { - this.deviceService.getDevicePublishLaunchCommands(this.deviceId).subscribe(commands => { - this.commands = commands; - this.cd.detectChanges(); - }); + download($event: Event) { + if ($event) { + $event.stopPropagation(); } - const currentOS = getOS(); - switch (currentOS) { - case 'linux': - case 'android': - this.tabIndex = 1; - break; - case 'macos': - case 'ios': - this.tabIndex = 2; - break; - case 'windows': - this.tabIndex = 0; - break; - default: - this.tabIndex = 1; + if (this.deviceId) { + this.deviceService.downloadGatewayDockerComposeFile(this.deviceId).subscribe(() => {}); } } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-configuration.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-configuration.component.html index 7ddf0c8cd9..153b6b0e14 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-configuration.component.html @@ -1,6 +1,6 @@ -
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-statistics.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-statistics.component.scss index e704120560..cd7722d12d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-statistics.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-statistics.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-statistics.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-statistics.component.ts index 503f5643bf..a3cb79e125 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-statistics.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-statistics.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 1d1c280053..e75bf97d23 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-doc-link-dialog.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-doc-link-dialog.component.html index 1eaf791577..7f86897f7e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-doc-link-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/home-page/add-doc-link-dialog.component.html @@ -1,6 +1,6 @@ -
+
@@ -25,7 +25,7 @@
+ [style.background-size]="vertical ? '100% ' + (batteryFillValue + 1) + '%' : (batteryFillValue + 1) + '% 100%'">
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.scss index fbf244a383..444417fb09 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts index 31f98aff6c..5251a0c602 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -46,6 +46,9 @@ import { BatteryLevelWidgetSettings } from '@home/components/widget/lib/indicator/battery-level-widget.models'; import { ResizeObserver } from '@juggle/resize-observer'; +import { Observable } from 'rxjs'; +import { ImagePipe } from '@shared/pipe/image.pipe'; +import { DomSanitizer } from '@angular/platform-browser'; const verticalBatteryDimensions = { shapeAspectRatio: 64 / 113, @@ -117,6 +120,8 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView value: number; + batteryFillValue: number; + batterySections: boolean[]; dividedBorderRadius: string; dividedGap: string; @@ -125,7 +130,7 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView batteryShapeColor: ColorProcessor; - backgroundStyle: ComponentStyle = {}; + backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; batteryBoxResize$: ResizeObserver; @@ -136,6 +141,8 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView private units = ''; constructor(private date: DatePipe, + private imagePipe: ImagePipe, + private sanitizer: DomSanitizer, private widgetComponent: WidgetComponent, private renderer: Renderer2, private cd: ChangeDetectorRef) { @@ -190,7 +197,7 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView this.batteryShapeColor = ColorProcessor.fromSettings(this.settings.batteryShapeColor); - this.backgroundStyle = backgroundStyle(this.settings.background); + this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); this.hasCardClickAction = this.ctx.actionsApi.getActionDescriptors('cardClick').length > 0; @@ -221,9 +228,10 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView public onDataUpdated() { const tsValue = getSingleTsValue(this.ctx.data); - this.value = 0; + this.batteryFillValue = 0; if (tsValue && isDefinedAndNotNull(tsValue[1]) && isNumeric(tsValue[1])) { this.value = tsValue[1]; + this.batteryFillValue = this.parseBatteryFillValue(this.value); this.valueText = formatValue(this.value, this.decimals, this.units, false); } else { this.valueText = 'N/A'; @@ -240,6 +248,16 @@ export class BatteryLevelWidgetComponent implements OnInit, OnDestroy, AfterView this.cd.detectChanges(); } + parseBatteryFillValue(value: number) { + if (value < 0) { + return 0; + } else if (value > 100) { + return 100; + } else { + return value; + } + } + public trackBySection(index: number): number { return index; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.models.ts index 34c00a4b92..081aae6558 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.models.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -78,22 +78,22 @@ export const batteryLevelDefaultSettings: BatteryLevelWidgetSettings = { }, valueColor: constantColor('rgba(0, 0, 0, 0.87)'), batteryLevelColor: { - color: 'rgba(92, 223, 144, 1)', + color: 'rgba(224, 224, 224, 1)', type: ColorType.range, rangeList: [ - {from: 0, to: 25, color: 'rgba(227, 71, 71, 1)'}, + {from: null, to: 25, color: 'rgba(227, 71, 71, 1)'}, {from: 25, to: 50, color: 'rgba(246, 206, 67, 1)'}, - {from: 50, to: 100, color: 'rgba(92, 223, 144, 1)'} + {from: 50, to: null, color: 'rgba(92, 223, 144, 1)'} ], colorFunction: defaultColorFunction }, batteryShapeColor: { - color: 'rgba(92, 223, 144, 0.32)', + color: 'rgba(224, 224, 224, 0.32)', type: ColorType.range, rangeList: [ - {from: 0, to: 25, color: 'rgba(227, 71, 71, 0.32)'}, + {from: null, to: 25, color: 'rgba(227, 71, 71, 0.32)'}, {from: 25, to: 50, color: 'rgba(246, 206, 67, 0.32)'}, - {from: 50, to: 100, color: 'rgba(92, 223, 144, 0.32)'} + {from: 50, to: null, color: 'rgba(92, 223, 144, 0.32)'} ], colorFunction: defaultColorFunction }, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.html index 4c14686b9c..5c247ca794 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.html @@ -1,6 +1,6 @@ -
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.scss index 046d1a7d3e..360a75f54c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts index 847937581b..3c79883bf3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -58,6 +58,9 @@ import { ResourcesService } from '@core/services/resources.service'; import { NULL_UUID } from '@shared/models/id/has-uuid'; import { TranslateService } from '@ngx-translate/core'; import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance; +import { ImagePipe } from '@shared/pipe/image.pipe'; +import { DomSanitizer } from '@angular/platform-browser'; +import { DataEntry } from '@shared/models/widget.models'; @Component({ selector: 'tb-liquid-level-widget', @@ -76,7 +79,7 @@ export class LiquidLevelWidgetComponent implements OnInit { @Input() widgetTitlePanel: TemplateRef; - backgroundStyle: ComponentStyle = {}; + backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; hasCardClickAction = false; @@ -106,7 +109,9 @@ export class LiquidLevelWidgetComponent implements OnInit { private capacityUnits = Object.values(CapacityUnits); - constructor(private cd: ChangeDetectorRef, + constructor(private imagePipe: ImagePipe, + private sanitizer: DomSanitizer, + private cd: ChangeDetectorRef, private resourcesService: ResourcesService, private translate: TranslateService) { } @@ -116,7 +121,7 @@ export class LiquidLevelWidgetComponent implements OnInit { this.settings = {...levelCardDefaultSettings, ...this.ctx.settings}; this.declareStyles(); - this.backgroundStyle = backgroundStyle(this.settings.background); + this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); this.hasCardClickAction = this.ctx.actionsApi.getActionDescriptors('cardClick').length > 0; @@ -395,7 +400,7 @@ export class LiquidLevelWidgetComponent implements OnInit { return limits.min + (percentage / 100) * (limits.max - limits.min); } - private updateTooltip(value: [number, any]): void { + private updateTooltip(value: DataEntry): void { this.tooltipContent = this.getTooltipContent(value); if (this.tooltip) { @@ -490,7 +495,7 @@ export class LiquidLevelWidgetComponent implements OnInit { } } - private getTooltipContent(value?: [number, any]): string { + private getTooltipContent(value?: DataEntry): string { const contentValue = value || [0, '']; let tooltipValue: string | number = 'N/A'; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.models.ts index cf526d6c97..954e228e79 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/liquid-level-widget.models.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -418,7 +418,7 @@ export const createAbsoluteLayout = (values?: {inputValue: number | string; volu export const createPercentLayout = (value: number | string = 50, valueTextStyle: string = valueTextStyleDefaults): string => `
- +
`; export const optionsFilter = (searchText: string): ((key: DataKey) => boolean) => diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.html index a2bf74e942..79f95c52d3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.html @@ -1,6 +1,6 @@ -
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.scss index c2c14ffb76..3af5baa58b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.ts index 8427cf362b..bee975bd1f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.component.ts @@ -1,3 +1,19 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + /// /// Copyright © 2016-2023 The Thingsboard Authors @@ -51,6 +67,9 @@ import { } from '@home/components/widget/lib/indicator/signal-strength-widget.models'; import tinycolor from 'tinycolor2'; import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { ImagePipe } from '@shared/pipe/image.pipe'; +import { DomSanitizer } from '@angular/platform-browser'; const shapeWidth = 149; const shapeHeight = 113; @@ -104,7 +123,7 @@ export class SignalStrengthWidgetComponent implements OnInit, OnDestroy, AfterVi }; tooltipDateStyle: ComponentStyle = {}; - backgroundStyle: ComponentStyle = {}; + backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; shapeResize$: ResizeObserver; @@ -128,6 +147,8 @@ export class SignalStrengthWidgetComponent implements OnInit, OnDestroy, AfterVi private noData = false; constructor(public widgetComponent: WidgetComponent, + private imagePipe: ImagePipe, + private sanitizer: DomSanitizer, private translate: TranslateService, private renderer: Renderer2, private cd: ChangeDetectorRef) { @@ -186,7 +207,7 @@ export class SignalStrengthWidgetComponent implements OnInit, OnDestroy, AfterVi this.tooltipDateLabelStyle = {...this.tooltipDateStyle, ...this.tooltipDateLabelStyle}; } - this.backgroundStyle = backgroundStyle(this.settings.background); + this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); this.hasCardClickAction = this.ctx.actionsApi.getActionDescriptors('cardClick').length > 0; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.models.ts index 59c782f5d4..144d9e891b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/signal-strength-widget.models.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.html index 40636a9d1b..b24ad37ede 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/json-input-widget.component.html @@ -1,6 +1,6 @@
- - +
widgets.label-widget.labels
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts index 191586b683..ff38162bbe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/label-widget-settings.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html index cf5415afe0..e33529a179 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.html @@ -1,6 +1,6 @@ + +
+
widgets.bar-chart.bar-chart-card-style
+
+ + {{ 'widgets.bar-chart.label-on-bar' | translate }} + +
+ + + + +
+
+
+ + {{ 'widgets.bar-chart.value-on-bar' | translate }} + +
+ + + + +
+
+
+ + + + + {{ 'widget-config.legend' | translate }} + + + + +
+
{{ 'legend.position' | translate }}
+ + + + {{ legendPositionTranslationMap.get(pos) | translate }} + + + +
+
+
{{ 'legend.label' | translate }}
+
+ + + + +
+
+
+
+
+
+ + + + + {{ 'widget-config.tooltip' | translate }} + + + + +
+
{{ 'tooltip.value' | translate }}
+
+ + + + +
+
+
+ + {{ 'tooltip.date' | translate }} + +
+ + + + + +
+
+
+
{{ 'tooltip.background-color' | translate }}
+ + +
+
+
{{ 'tooltip.background-blur' | translate }}
+ + +
px
+
+
+
+
+
+
+
{{ 'widgets.background.background' | translate }}
+ + +
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.ts new file mode 100644 index 0000000000..0d547922eb --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.ts @@ -0,0 +1,170 @@ +/// +/// 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, Injector } from '@angular/core'; +import { + legendPositions, + legendPositionTranslationMap, + WidgetSettings, + WidgetSettingsComponent +} from '@shared/models/widget.models'; +import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { formatValue } from '@core/utils'; +import { DateFormatProcessor, DateFormatSettings } from '@shared/models/widget-settings.models'; +import { + barChartWithLabelsDefaultSettings +} from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.models'; + +@Component({ + selector: 'tb-bar-chart-with-labels-widget-settings', + templateUrl: './bar-chart-with-labels-widget-settings.component.html', + styleUrls: [] +}) +export class BarChartWithLabelsWidgetSettingsComponent extends WidgetSettingsComponent { + + legendPositions = legendPositions; + + legendPositionTranslationMap = legendPositionTranslationMap; + + barChartWidgetSettingsForm: UntypedFormGroup; + + tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); + + tooltipDatePreviewFn = this._tooltipDatePreviewFn.bind(this); + + constructor(protected store: Store, + private $injector: Injector, + private fb: UntypedFormBuilder) { + super(store); + } + + protected settingsForm(): UntypedFormGroup { + return this.barChartWidgetSettingsForm; + } + + protected defaultSettings(): WidgetSettings { + return {...barChartWithLabelsDefaultSettings}; + } + + protected onSettingsSet(settings: WidgetSettings) { + this.barChartWidgetSettingsForm = this.fb.group({ + + showBarLabel: [settings.showBarLabel, []], + barLabelFont: [settings.barLabelFont, []], + barLabelColor: [settings.barLabelColor, []], + showBarValue: [settings.showBarValue, []], + barValueFont: [settings.barValueFont, []], + barValueColor: [settings.barValueColor, []], + + showLegend: [settings.showLegend, []], + legendPosition: [settings.legendPosition, []], + legendLabelFont: [settings.legendLabelFont, []], + legendLabelColor: [settings.legendLabelColor, []], + + showTooltip: [settings.showTooltip, []], + tooltipValueFont: [settings.tooltipValueFont, []], + tooltipValueColor: [settings.tooltipValueColor, []], + tooltipShowDate: [settings.tooltipShowDate, []], + tooltipDateFormat: [settings.tooltipDateFormat, []], + tooltipDateFont: [settings.tooltipDateFont, []], + tooltipDateColor: [settings.tooltipDateColor, []], + tooltipBackgroundColor: [settings.tooltipBackgroundColor, []], + tooltipBackgroundBlur: [settings.tooltipBackgroundBlur, []], + + background: [settings.background, []] + }); + } + + protected validatorTriggers(): string[] { + return ['showBarLabel', 'showBarValue', 'showLegend', 'showTooltip', 'tooltipShowDate']; + } + + protected updateValidators(emitEvent: boolean) { + const showBarLabel: boolean = this.barChartWidgetSettingsForm.get('showBarLabel').value; + const showBarValue: boolean = this.barChartWidgetSettingsForm.get('showBarValue').value; + const showLegend: boolean = this.barChartWidgetSettingsForm.get('showLegend').value; + const showTooltip: boolean = this.barChartWidgetSettingsForm.get('showTooltip').value; + const tooltipShowDate: boolean = this.barChartWidgetSettingsForm.get('tooltipShowDate').value; + + if (showBarLabel) { + this.barChartWidgetSettingsForm.get('barLabelFont').enable(); + this.barChartWidgetSettingsForm.get('barLabelColor').enable(); + } else { + this.barChartWidgetSettingsForm.get('barLabelFont').disable(); + this.barChartWidgetSettingsForm.get('barLabelColor').disable(); + } + + if (showBarValue) { + this.barChartWidgetSettingsForm.get('barValueFont').enable(); + this.barChartWidgetSettingsForm.get('barValueColor').enable(); + } else { + this.barChartWidgetSettingsForm.get('barValueFont').disable(); + this.barChartWidgetSettingsForm.get('barValueColor').disable(); + } + + if (showLegend) { + this.barChartWidgetSettingsForm.get('legendPosition').enable(); + this.barChartWidgetSettingsForm.get('legendLabelFont').enable(); + this.barChartWidgetSettingsForm.get('legendLabelColor').enable(); + } else { + this.barChartWidgetSettingsForm.get('legendPosition').disable(); + this.barChartWidgetSettingsForm.get('legendLabelFont').disable(); + this.barChartWidgetSettingsForm.get('legendLabelColor').disable(); + } + + if (showTooltip) { + this.barChartWidgetSettingsForm.get('tooltipValueFont').enable(); + this.barChartWidgetSettingsForm.get('tooltipValueColor').enable(); + this.barChartWidgetSettingsForm.get('tooltipShowDate').enable({emitEvent: false}); + this.barChartWidgetSettingsForm.get('tooltipBackgroundColor').enable(); + this.barChartWidgetSettingsForm.get('tooltipBackgroundBlur').enable(); + if (tooltipShowDate) { + this.barChartWidgetSettingsForm.get('tooltipDateFormat').enable(); + this.barChartWidgetSettingsForm.get('tooltipDateFont').enable(); + this.barChartWidgetSettingsForm.get('tooltipDateColor').enable(); + } else { + this.barChartWidgetSettingsForm.get('tooltipDateFormat').disable(); + this.barChartWidgetSettingsForm.get('tooltipDateFont').disable(); + this.barChartWidgetSettingsForm.get('tooltipDateColor').disable(); + } + } else { + this.barChartWidgetSettingsForm.get('tooltipValueFont').disable(); + this.barChartWidgetSettingsForm.get('tooltipValueColor').disable(); + this.barChartWidgetSettingsForm.get('tooltipShowDate').disable({emitEvent: false}); + this.barChartWidgetSettingsForm.get('tooltipDateFormat').disable(); + this.barChartWidgetSettingsForm.get('tooltipDateFont').disable(); + this.barChartWidgetSettingsForm.get('tooltipDateColor').disable(); + this.barChartWidgetSettingsForm.get('tooltipBackgroundColor').disable(); + this.barChartWidgetSettingsForm.get('tooltipBackgroundBlur').disable(); + } + } + + private _tooltipValuePreviewFn(): string { + const units: string = this.widgetConfig.config.units; + const decimals: number = this.widgetConfig.config.decimals; + return formatValue(22, decimals, units, false); + } + + private _tooltipDatePreviewFn(): string { + const dateFormat: DateFormatSettings = this.barChartWidgetSettingsForm.get('tooltipDateFormat').value; + const processor = DateFormatProcessor.fromSettings(this.$injector, dateFormat); + processor.update(Date.now()); + return processor.formatted; + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.html index d30182f73d..3922858711 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/chart-widget-settings.component.html @@ -1,6 +1,6 @@ + +
+
widgets.range-chart.range-chart-card-style
+
+ + {{ 'widgets.range-chart.data-zoom' | translate }} + +
+
+
{{ 'widgets.range-chart.range-colors' | translate }}
+ + +
+
+
{{ 'widgets.range-chart.out-of-range-color' | translate }}
+ + +
+
+ + {{ 'widgets.range-chart.fill-area' | translate }} + +
+
+ + + + + {{ 'widget-config.legend' | translate }} + + + + +
+
{{ 'legend.position' | translate }}
+ + + + {{ legendPositionTranslationMap.get(pos) | translate }} + + + +
+
+
{{ 'legend.label' | translate }}
+
+ + + + +
+
+
+
+
+
+ + + + + {{ 'widget-config.tooltip' | translate }} + + + + +
+
{{ 'tooltip.value' | translate }}
+
+ + + + +
+
+
+ + {{ 'tooltip.date' | translate }} + +
+ + + + + +
+
+
+
{{ 'tooltip.background-color' | translate }}
+ + +
+
+
{{ 'tooltip.background-blur' | translate }}
+ + +
px
+
+
+
+
+
+
+
{{ 'widgets.background.background' | translate }}
+ + +
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.ts new file mode 100644 index 0000000000..c0e043995d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.ts @@ -0,0 +1,147 @@ +/// +/// 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, Injector } from '@angular/core'; +import { + legendPositions, + legendPositionTranslationMap, + WidgetSettings, + WidgetSettingsComponent +} from '@shared/models/widget.models'; +import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { formatValue } from '@core/utils'; +import { rangeChartDefaultSettings } from '@home/components/widget/lib/chart/range-chart-widget.models'; +import { DateFormatProcessor, DateFormatSettings } from '@shared/models/widget-settings.models'; + +@Component({ + selector: 'tb-range-chart-widget-settings', + templateUrl: './range-chart-widget-settings.component.html', + styleUrls: [] +}) +export class RangeChartWidgetSettingsComponent extends WidgetSettingsComponent { + + legendPositions = legendPositions; + + legendPositionTranslationMap = legendPositionTranslationMap; + + rangeChartWidgetSettingsForm: UntypedFormGroup; + + tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); + + tooltipDatePreviewFn = this._tooltipDatePreviewFn.bind(this); + + constructor(protected store: Store, + private $injector: Injector, + private fb: UntypedFormBuilder) { + super(store); + } + + protected settingsForm(): UntypedFormGroup { + return this.rangeChartWidgetSettingsForm; + } + + protected defaultSettings(): WidgetSettings { + return {...rangeChartDefaultSettings}; + } + + protected onSettingsSet(settings: WidgetSettings) { + this.rangeChartWidgetSettingsForm = this.fb.group({ + dataZoom: [settings.dataZoom, []], + rangeColors: [settings.rangeColors, []], + outOfRangeColor: [settings.outOfRangeColor, []], + fillArea: [settings.fillArea, []], + + showLegend: [settings.showLegend, []], + legendPosition: [settings.legendPosition, []], + legendLabelFont: [settings.legendLabelFont, []], + legendLabelColor: [settings.legendLabelColor, []], + + showTooltip: [settings.showTooltip, []], + tooltipValueFont: [settings.tooltipValueFont, []], + tooltipValueColor: [settings.tooltipValueColor, []], + tooltipShowDate: [settings.tooltipShowDate, []], + tooltipDateFormat: [settings.tooltipDateFormat, []], + tooltipDateFont: [settings.tooltipDateFont, []], + tooltipDateColor: [settings.tooltipDateColor, []], + tooltipBackgroundColor: [settings.tooltipBackgroundColor, []], + tooltipBackgroundBlur: [settings.tooltipBackgroundBlur, []], + + background: [settings.background, []] + }); + } + + protected validatorTriggers(): string[] { + return ['showLegend', 'showTooltip', 'tooltipShowDate']; + } + + protected updateValidators(emitEvent: boolean) { + const showLegend: boolean = this.rangeChartWidgetSettingsForm.get('showLegend').value; + const showTooltip: boolean = this.rangeChartWidgetSettingsForm.get('showTooltip').value; + const tooltipShowDate: boolean = this.rangeChartWidgetSettingsForm.get('tooltipShowDate').value; + + if (showLegend) { + this.rangeChartWidgetSettingsForm.get('legendPosition').enable(); + this.rangeChartWidgetSettingsForm.get('legendLabelFont').enable(); + this.rangeChartWidgetSettingsForm.get('legendLabelColor').enable(); + } else { + this.rangeChartWidgetSettingsForm.get('legendPosition').disable(); + this.rangeChartWidgetSettingsForm.get('legendLabelFont').disable(); + this.rangeChartWidgetSettingsForm.get('legendLabelColor').disable(); + } + + if (showTooltip) { + this.rangeChartWidgetSettingsForm.get('tooltipValueFont').enable(); + this.rangeChartWidgetSettingsForm.get('tooltipValueColor').enable(); + this.rangeChartWidgetSettingsForm.get('tooltipShowDate').enable({emitEvent: false}); + this.rangeChartWidgetSettingsForm.get('tooltipBackgroundColor').enable(); + this.rangeChartWidgetSettingsForm.get('tooltipBackgroundBlur').enable(); + if (tooltipShowDate) { + this.rangeChartWidgetSettingsForm.get('tooltipDateFormat').enable(); + this.rangeChartWidgetSettingsForm.get('tooltipDateFont').enable(); + this.rangeChartWidgetSettingsForm.get('tooltipDateColor').enable(); + } else { + this.rangeChartWidgetSettingsForm.get('tooltipDateFormat').disable(); + this.rangeChartWidgetSettingsForm.get('tooltipDateFont').disable(); + this.rangeChartWidgetSettingsForm.get('tooltipDateColor').disable(); + } + } else { + this.rangeChartWidgetSettingsForm.get('tooltipValueFont').disable(); + this.rangeChartWidgetSettingsForm.get('tooltipValueColor').disable(); + this.rangeChartWidgetSettingsForm.get('tooltipShowDate').disable({emitEvent: false}); + this.rangeChartWidgetSettingsForm.get('tooltipDateFormat').disable(); + this.rangeChartWidgetSettingsForm.get('tooltipDateFont').disable(); + this.rangeChartWidgetSettingsForm.get('tooltipDateColor').disable(); + this.rangeChartWidgetSettingsForm.get('tooltipBackgroundColor').disable(); + this.rangeChartWidgetSettingsForm.get('tooltipBackgroundBlur').disable(); + } + } + + private _tooltipValuePreviewFn(): string { + const units: string = this.widgetConfig.config.units; + const decimals: number = this.widgetConfig.config.decimals; + return formatValue(22, decimals, units, false); + } + + private _tooltipDatePreviewFn(): string { + const dateFormat: DateFormatSettings = this.rangeChartWidgetSettingsForm.get('tooltipDateFormat').value; + const processor = DateFormatProcessor.fromSettings(this.$injector, dateFormat); + processor.update(Date.now()); + return processor.formatted; + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.html index 42c4472cca..6cca169f5a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.html @@ -1,6 +1,6 @@
widgets.background.background-settings
-
+
widgets.background.background
@@ -27,14 +27,8 @@
- -
-
widgets.background.image-url
- - - -
-
+ +
widgets.color.color
@@ -64,7 +58,7 @@
widgets.background.preview
-
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.scss index 258117512a..01297b9d12 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - @import '../../../../../../../../scss/constants'; .tb-background-settings-panel { @@ -31,6 +30,12 @@ letter-spacing: 0.25px; color: rgba(0, 0, 0, 0.87); } + .tb-background-form-panel { + height: 192px; + .tb-background-color-field { + height: auto; + } + } .tb-background-settings-preview { flex: 1; background: rgba(0, 0, 0, 0.04); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts index ab94b95800..c1c85a05e1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; import { PageComponent } from '@shared/components/page.component'; import { backgroundStyle, @@ -27,6 +27,9 @@ import { TbPopoverComponent } from '@shared/components/popover.component'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; +import { Observable } from 'rxjs'; +import { ImagePipe } from '@shared/pipe/image.pipe'; +import { DomSanitizer } from '@angular/platform-browser'; @Component({ selector: 'tb-background-settings-panel', @@ -54,11 +57,14 @@ export class BackgroundSettingsPanelComponent extends PageComponent implements O backgroundSettingsFormGroup: UntypedFormGroup; - backgroundStyle: ComponentStyle = {}; + backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; constructor(private fb: UntypedFormBuilder, - protected store: Store) { + private imagePipe: ImagePipe, + private sanitizer: DomSanitizer, + protected store: Store, + private cd: ChangeDetectorRef) { super(store); } @@ -66,7 +72,6 @@ export class BackgroundSettingsPanelComponent extends PageComponent implements O this.backgroundSettingsFormGroup = this.fb.group( { type: [this.backgroundSettings?.type, []], - imageBase64: [this.backgroundSettings?.imageBase64, []], imageUrl: [this.backgroundSettings?.imageUrl, []], color: [this.backgroundSettings?.color, []], overlay: this.fb.group({ @@ -101,11 +106,11 @@ export class BackgroundSettingsPanelComponent extends PageComponent implements O private updateValidators() { const overlayEnabled: boolean = this.backgroundSettingsFormGroup.get('overlay').get('enabled').value; if (overlayEnabled) { - this.backgroundSettingsFormGroup.get('overlay').get('color').enable(); - this.backgroundSettingsFormGroup.get('overlay').get('blur').enable(); + this.backgroundSettingsFormGroup.get('overlay').get('color').enable({emitEvent: false}); + this.backgroundSettingsFormGroup.get('overlay').get('blur').enable({emitEvent: false}); } else { - this.backgroundSettingsFormGroup.get('overlay').get('color').disable(); - this.backgroundSettingsFormGroup.get('overlay').get('blur').disable(); + this.backgroundSettingsFormGroup.get('overlay').get('color').disable({emitEvent: false}); + this.backgroundSettingsFormGroup.get('overlay').get('blur').disable({emitEvent: false}); } this.backgroundSettingsFormGroup.get('overlay').get('color').updateValueAndValidity({emitEvent: false}); this.backgroundSettingsFormGroup.get('overlay').get('blur').updateValueAndValidity({emitEvent: false}); @@ -113,8 +118,9 @@ export class BackgroundSettingsPanelComponent extends PageComponent implements O private updateBackgroundStyle() { const background: BackgroundSettings = this.backgroundSettingsFormGroup.value; - this.backgroundStyle = backgroundStyle(background); + this.backgroundStyle$ = backgroundStyle(background, this.imagePipe, this.sanitizer, true); this.overlayStyle = overlayStyle(background.overlay); + this.cd.markForCheck(); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.html index e9e1b99b0e..ea685bd85f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.html @@ -1,6 +1,6 @@
- - +
widgets.maps.image-map-background-from-entity-attribute
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.ts index e79735e70d..51cc5ae6d7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/image-map-provider-settings.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-editor-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-editor-settings.component.html index 8c0eb5e6b2..edea61f456 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-editor-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/map/map-editor-settings.component.html @@ -1,6 +1,6 @@ -
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.scss index eda98fe6ba..5f3b18a041 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts index bf43218f82..4ce5cf21d7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -47,6 +47,9 @@ import { formatValue, isDefinedAndNotNull, isNumeric } from '@core/utils'; import { ResizeObserver } from '@juggle/resize-observer'; import { Path, Svg, SVG, Text } from '@svgdotjs/svg.js'; import { DataKey } from '@shared/models/widget.models'; +import { Observable } from 'rxjs'; +import { ImagePipe } from '@shared/pipe/image.pipe'; +import { DomSanitizer } from '@angular/platform-browser'; const shapeSize = 180; const cx = shapeSize / 2; @@ -87,7 +90,7 @@ export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, Aft centerValueColor: ColorProcessor; - backgroundStyle: ComponentStyle = {}; + backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; shapeResize$: ResizeObserver; @@ -109,6 +112,8 @@ export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, Aft private centerValueText = 'N/A'; constructor(private widgetComponent: WidgetComponent, + private imagePipe: ImagePipe, + private sanitizer: DomSanitizer, private renderer: Renderer2, private cd: ChangeDetectorRef) { } @@ -135,7 +140,7 @@ export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, Aft this.centerValueColor = ColorProcessor.fromSettings(this.settings.centerValueColor); - this.backgroundStyle = backgroundStyle(this.settings.background); + this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); this.hasCardClickAction = this.ctx.actionsApi.getActionDescriptors('cardClick').length > 0; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts index 6359696f25..7801f80a17 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts index c29df7f243..56a1868227 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts index d4828a0190..851a469642 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -74,6 +74,10 @@ import { ValueChartCardWidgetComponent } from '@home/components/widget/lib/cards import { ProgressBarWidgetComponent } from '@home/components/widget/lib/cards/progress-bar-widget.component'; import { LiquidLevelWidgetComponent } from '@home/components/widget/lib/indicator/liquid-level-widget.component'; import { DoughnutWidgetComponent } from '@home/components/widget/lib/chart/doughnut-widget.component'; +import { RangeChartWidgetComponent } from '@home/components/widget/lib/chart/range-chart-widget.component'; +import { + BarChartWithLabelsWidgetComponent +} from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.component'; import { GatewayServiceRPCConnectorTemplateDialogComponent } from '@home/components/widget/lib/gateway/gateway-service-rpc-connector-template-dialog'; @@ -120,7 +124,9 @@ import { ValueChartCardWidgetComponent, ProgressBarWidgetComponent, LiquidLevelWidgetComponent, - DoughnutWidgetComponent + DoughnutWidgetComponent, + RangeChartWidgetComponent, + BarChartWithLabelsWidgetComponent ], imports: [ CommonModule, @@ -129,47 +135,49 @@ import { HomePageWidgetsModule, SharedHomeComponentsModule ], - exports: [ - EntitiesTableWidgetComponent, - AlarmsTableWidgetComponent, - TimeseriesTableWidgetComponent, - EntitiesHierarchyWidgetComponent, - EdgesOverviewWidgetComponent, - RpcWidgetsModule, - HomePageWidgetsModule, - DateRangeNavigatorWidgetComponent, - JsonInputWidgetComponent, - MultipleInputWidgetComponent, - TripAnimationComponent, - PhotoCameraInputWidgetComponent, - GatewayFormComponent, - NavigationCardsWidgetComponent, - NavigationCardWidgetComponent, - QrCodeWidgetComponent, - MarkdownWidgetComponent, - LegendComponent, - FlotWidgetComponent, - GatewayConnectorComponent, - GatewayLogsComponent, - GatewayServiceRPCConnectorComponent, - GatewayServiceRPCConnectorTemplatesComponent, - GatewayStatisticsComponent, - GatewayServiceRPCComponent, - DeviceGatewayCommandComponent, - GatewayConfigurationComponent, - GatewayRemoteConfigurationDialogComponent, - GatewayServiceRPCConnectorTemplateDialogComponent, - ValueCardWidgetComponent, - AggregatedValueCardWidgetComponent, - CountWidgetComponent, - BatteryLevelWidgetComponent, - WindSpeedDirectionWidgetComponent, - SignalStrengthWidgetComponent, - ValueChartCardWidgetComponent, - ProgressBarWidgetComponent, - LiquidLevelWidgetComponent, - DoughnutWidgetComponent - ], + exports: [ + EntitiesTableWidgetComponent, + AlarmsTableWidgetComponent, + TimeseriesTableWidgetComponent, + EntitiesHierarchyWidgetComponent, + EdgesOverviewWidgetComponent, + RpcWidgetsModule, + HomePageWidgetsModule, + DateRangeNavigatorWidgetComponent, + JsonInputWidgetComponent, + MultipleInputWidgetComponent, + TripAnimationComponent, + PhotoCameraInputWidgetComponent, + GatewayFormComponent, + NavigationCardsWidgetComponent, + NavigationCardWidgetComponent, + QrCodeWidgetComponent, + MarkdownWidgetComponent, + LegendComponent, + FlotWidgetComponent, + GatewayConnectorComponent, + GatewayLogsComponent, + GatewayServiceRPCConnectorComponent, + GatewayServiceRPCConnectorTemplatesComponent, + GatewayStatisticsComponent, + GatewayServiceRPCComponent, + DeviceGatewayCommandComponent, + GatewayConfigurationComponent, + GatewayRemoteConfigurationDialogComponent, + GatewayServiceRPCConnectorTemplateDialogComponent, + ValueCardWidgetComponent, + AggregatedValueCardWidgetComponent, + CountWidgetComponent, + BatteryLevelWidgetComponent, + WindSpeedDirectionWidgetComponent, + SignalStrengthWidgetComponent, + ValueChartCardWidgetComponent, + ProgressBarWidgetComponent, + LiquidLevelWidgetComponent, + DoughnutWidgetComponent, + RangeChartWidgetComponent, + BarChartWithLabelsWidgetComponent + ], providers: [ {provide: WIDGET_COMPONENTS_MODULE_TOKEN, useValue: WidgetComponentsModule} ] diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html index cdd1d8e2da..e49b769fee 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.html @@ -1,6 +1,6 @@
-
-
- -
{{ noFileText }}
-
{{ fileName }}
+
+ +
{{ noFileText }}
+
{{ fileName }}
+
dashboard.maximum-upload-file-size
+
diff --git a/ui-ngx/src/app/shared/components/file-input.component.scss b/ui-ngx/src/app/shared/components/file-input.component.scss index e172abd6e9..2aa4190823 100644 --- a/ui-ngx/src/app/shared/components/file-input.component.scss +++ b/ui-ngx/src/app/shared/components/file-input.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,9 +21,13 @@ $previewSize: 100px !default; .tb-container { margin-top: 0; + padding: 0 0 16px; + display: flex; + flex-direction: column; + gap: 8px; label.tb-title { display: flex; - padding-bottom: 8px; + padding-bottom: 0; } } @@ -78,19 +82,46 @@ $previewSize: 100px !default; text-align: center; .mat-icon { margin-right: 17px; + color: rgba(0,0,0,0.12); } } } + + .tb-file-info-container { + display: flex; + flex-direction: column; + gap: 8px; + font-size: 13px; + font-style: normal; + line-height: 16px; + letter-spacing: normal; + } + + .tb-file-name { + color: rgba(0, 0, 0, 0.54); + font-weight: 500; + overflow: hidden; + text-overflow: ellipsis; + } + + .tb-file-hint { + color: rgba(0, 0, 0, 0.38); + font-weight: 400; + overflow: hidden; + text-overflow: ellipsis; + } } :host ::ng-deep { - button.browse-file { + button.mat-mdc-button.mat-mdc-button-base.browse-file { padding: 0; + min-width: 0; + height: 24px; font-size: 16px; label { display: block; cursor: pointer; - padding: 0 16px; + padding: 0 8px; } } diff --git a/ui-ngx/src/app/shared/components/file-input.component.ts b/ui-ngx/src/app/shared/components/file-input.component.ts index 8e70ca88ba..b385cf109a 100644 --- a/ui-ngx/src/app/shared/components/file-input.component.ts +++ b/ui-ngx/src/app/shared/components/file-input.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -32,10 +32,12 @@ import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { Subscription } from 'rxjs'; -import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { FlowDirective } from '@flowjs/ngx-flow'; import { TranslateService } from '@ngx-translate/core'; import { UtilsService } from '@core/services/utils.service'; +import { DialogService } from '@core/services/dialog.service'; +import { FileSizePipe } from '@shared/pipe/file-size.pipe'; +import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ selector: 'tb-file-input', @@ -73,43 +75,28 @@ export class FileInputComponent extends PageComponent implements AfterViewInit, dropLabel: string; @Input() - contentConvertFunction: (content: string) => any; - - private requiredValue: boolean; - - get required(): boolean { - return this.requiredValue; - } + maxSizeByte: number; @Input() - set required(value: boolean) { - const newVal = coerceBooleanProperty(value); - if (this.requiredValue !== newVal) { - this.requiredValue = newVal; - } - } - - private requiredAsErrorValue: boolean; + contentConvertFunction: (content: string) => any; - get requiredAsError(): boolean { - return this.requiredAsErrorValue; - } + @Input() + @coerceBoolean() + required: boolean; @Input() - set requiredAsError(value: boolean) { - const newVal = coerceBooleanProperty(value); - if (this.requiredAsErrorValue !== newVal) { - this.requiredAsErrorValue = newVal; - } - } + @coerceBoolean() + requiredAsError: boolean; @Input() + @coerceBoolean() disabled: boolean; @Input() existingFileName: string; @Input() + @coerceBoolean() readAsBinary = false; @Input() @@ -148,7 +135,9 @@ export class FileInputComponent extends PageComponent implements AfterViewInit, constructor(protected store: Store, private utils: UtilsService, - public translate: TranslateService) { + private translate: TranslateService, + private dialog: DialogService, + private fileSize: FileSizePipe) { super(store); } @@ -156,11 +145,24 @@ export class FileInputComponent extends PageComponent implements AfterViewInit, this.autoUploadSubscription = this.flow.events$.subscribe(event => { if (event.type === 'filesAdded') { const readers = []; + let showMaxSizeAlert = false; (event.event[0] as flowjs.FlowFile[]).forEach(file => { if (this.filterFile(file)) { - readers.push(this.readerAsFile(file)); + if (this.checkMaxSize(file)) { + readers.push(this.readerAsFile(file)); + } else { + showMaxSizeAlert = true; + } } }); + + if (showMaxSizeAlert) { + this.dialog.alert( + this.translate.instant('dashboard.cannot-upload-file'), + this.translate.instant('dashboard.maximum-upload-file-size', {size: this.fileSize.transform(this.maxSizeByte)}) + ).subscribe(() => { }); + } + if (readers.length) { Promise.all(readers).then((files) => { files = files.filter(file => file.fileContent != null || file.files != null); @@ -218,6 +220,10 @@ export class FileInputComponent extends PageComponent implements AfterViewInit, }); } + private checkMaxSize(file: flowjs.FlowFile): boolean { + return !this.maxSizeByte || file.size <= this.maxSizeByte; + } + private filterFile(file: flowjs.FlowFile): boolean { if (this.allowedExtensions) { return this.allowedExtensions.split(',').indexOf(file.getExtension()) > -1; diff --git a/ui-ngx/src/app/shared/components/footer-fab-buttons.component.html b/ui-ngx/src/app/shared/components/footer-fab-buttons.component.html index 20820ac320..7d9c0c33d5 100644 --- a/ui-ngx/src/app/shared/components/footer-fab-buttons.component.html +++ b/ui-ngx/src/app/shared/components/footer-fab-buttons.component.html @@ -1,6 +1,6 @@ - - + +
-
+
- +
diff --git a/ui-ngx/src/app/modules/home/components/grid/scroll-grid.component.scss b/ui-ngx/src/app/shared/components/grid/scroll-grid.component.scss similarity index 93% rename from ui-ngx/src/app/modules/home/components/grid/scroll-grid.component.scss rename to ui-ngx/src/app/shared/components/grid/scroll-grid.component.scss index 8787e24eb5..47d7629f7a 100644 --- a/ui-ngx/src/app/modules/home/components/grid/scroll-grid.component.scss +++ b/ui-ngx/src/app/shared/components/grid/scroll-grid.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ .cdk-virtual-scroll-content-wrapper { display: flex; flex-direction: column; + width: 100%; } .cdk-virtual-scroll-spacer { height: auto !important; diff --git a/ui-ngx/src/app/modules/home/components/grid/scroll-grid.component.ts b/ui-ngx/src/app/shared/components/grid/scroll-grid.component.ts similarity index 54% rename from ui-ngx/src/app/modules/home/components/grid/scroll-grid.component.ts rename to ui-ngx/src/app/shared/components/grid/scroll-grid.component.ts index e0eea202ff..e876b06694 100644 --- a/ui-ngx/src/app/modules/home/components/grid/scroll-grid.component.ts +++ b/ui-ngx/src/app/shared/components/grid/scroll-grid.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -15,10 +15,10 @@ /// import { - AfterViewInit, + AfterViewInit, ChangeDetectorRef, Component, Input, - OnChanges, + OnChanges, OnDestroy, OnInit, Renderer2, SimpleChanges, @@ -30,10 +30,18 @@ import { GridEntitiesFetchFunction, ScrollGridColumns, ScrollGridDatasource -} from '@home/models/datasource/scroll-grid-datasource'; +} from '@shared/components/grid/scroll-grid-datasource'; import { BreakpointObserver } from '@angular/cdk/layout'; import { isObject } from '@app/core/utils'; import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; +import { ResizeObserver } from '@juggle/resize-observer'; + +export type ItemSizeFunction = (itemWidth: number) => number; + +export interface ItemSizeStrategy { + defaultItemSize: number; + itemSizeFunction: ItemSizeFunction; +} @Component({ selector: 'tb-scroll-grid', @@ -41,7 +49,7 @@ import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; styleUrls: ['./scroll-grid.component.scss'], encapsulation: ViewEncapsulation.None }) -export class ScrollGridComponent implements OnInit, AfterViewInit, OnChanges { +export class ScrollGridComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy { @ViewChild('viewport') viewport: CdkVirtualScrollViewport; @@ -56,7 +64,7 @@ export class ScrollGridComponent implements OnInit, AfterViewInit, OnChang filter: F; @Input() - itemSize = 200; + itemSize: number | ItemSizeStrategy = 200; @Input() gap = 12; @@ -75,17 +83,37 @@ export class ScrollGridComponent implements OnInit, AfterViewInit, OnChang dataSource: ScrollGridDatasource; + calculatedItemSize: number; + minBuffer: number; + maxBuffer: number; + + private contentResize$: ResizeObserver; + constructor(private breakpointObserver: BreakpointObserver, + private cd: ChangeDetectorRef, private renderer: Renderer2) { } ngOnInit(): void { + if (typeof this.itemSize === 'number') { + this.calculatedItemSize = this.itemSize; + } else { + this.calculatedItemSize = this.itemSize.defaultItemSize; + } + this.minBuffer = this.calculatedItemSize; + this.maxBuffer = this.calculatedItemSize * 2; this.dataSource = new ScrollGridDatasource(this.breakpointObserver, this.columns, this.fetchFunction, this.filter); } ngAfterViewInit() { this.renderer.setStyle(this.viewport._contentWrapper.nativeElement, 'gap', this.gap + 'px'); this.renderer.setStyle(this.viewport._contentWrapper.nativeElement, 'padding', this.gap + 'px'); + if (!(typeof this.itemSize === 'number')) { + this.contentResize$ = new ResizeObserver(() => { + this.onContentResize(); + }); + this.contentResize$.observe(this.viewport._contentWrapper.nativeElement); + } } ngOnChanges(changes: SimpleChanges): void { @@ -97,7 +125,43 @@ export class ScrollGridComponent implements OnInit, AfterViewInit, OnChang } } + ngOnDestroy() { + if (this.contentResize$) { + this.contentResize$.disconnect(); + } + } + isObject(value: any): boolean { return isObject(value); } + + trackByItemsRow(index: number, itemsRow: T[]): number { + return index; + } + + trackByItem(index: number, item: T): T { + return item; + } + + public update() { + this.dataSource.update(); + } + + public updateItem(index: number, item: T) { + this.dataSource.updateItem(index, item); + } + + public deleteItem(index: number) { + this.dataSource.deleteItem(index); + } + + private onContentResize() { + const contentWidth = this.viewport._contentWrapper.nativeElement.getBoundingClientRect().width; + const columns = this.dataSource.currentColumns; + const itemWidth = (contentWidth - this.gap * (columns + 1)) / columns; + this.calculatedItemSize = (this.itemSize as ItemSizeStrategy).itemSizeFunction(itemWidth); + this.minBuffer = this.calculatedItemSize; + this.maxBuffer = this.calculatedItemSize * 2; + this.cd.markForCheck(); + } } diff --git a/ui-ngx/src/app/shared/components/help-markdown.component.html b/ui-ngx/src/app/shared/components/help-markdown.component.html index cba58b60f4..55a8786d0e 100644 --- a/ui-ngx/src/app/shared/components/help-markdown.component.html +++ b/ui-ngx/src/app/shared/components/help-markdown.component.html @@ -1,6 +1,6 @@ + +

{{ 'image.embed-image' | translate }}

+ + +
+ + +
+
+
+ + + +
+ +
{{ 'image.embed-to-html' | translate }}
+
+
+
image.embed-to-html
+
+
+ +
+ +
+
+
+
+
image.embed-to-angular-template
+
+ +
+
diff --git a/ui-ngx/src/app/shared/components/image/embed-image-dialog.component.scss b/ui-ngx/src/app/shared/components/image/embed-image-dialog.component.scss new file mode 100644 index 0000000000..eeaff6e83c --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/embed-image-dialog.component.scss @@ -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. + */ +:host { + .mat-mdc-dialog-content { + display: flex; + flex-direction: column; + gap: 16px; + .tb-embed-image-text { + font-size: 14px; + font-weight: 400; + line-height: 20px; + color: rgba(0,0,0,0.54); + letter-spacing: 0.2px; + } + .tb-form-panel-title { + color: rgba(0, 0, 0, 0.87); + } + } +} + +:host ::ng-deep { + .tb-markdown-view { + max-width: 700px; + .tb-embed-image-code { + .code-wrapper { + padding: 0; + pre[class*=language-] { + margin: 0; + padding: 9px 38px 9px 16px; + } + code[class*="language-"], pre[class*="language-"] { + font-size: 12px; + overflow: hidden; + white-space: normal; + word-break: break-word; + } + button.clipboard-btn { + right: 0; + height: 36px; + p, div { + background: transparent; + } + p { + margin: 0; + padding: 6px; + font-size: 14px; + } + div { + top: 0; + padding: 8px; + height: 38px; + width: 38px; + } + } + } + } + } +} diff --git a/ui-ngx/src/app/shared/components/image/embed-image-dialog.component.ts b/ui-ngx/src/app/shared/components/image/embed-image-dialog.component.ts new file mode 100644 index 0000000000..f4d3e6d989 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/embed-image-dialog.component.ts @@ -0,0 +1,94 @@ +/// +/// 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 { ImageResourceInfo } from '@shared/models/resource.models'; +import { Component, Inject, OnInit } from '@angular/core'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { Router } from '@angular/router'; +import { ImageService } from '@core/http/image.service'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { FormControl, UntypedFormBuilder } from '@angular/forms'; + +export interface EmbedImageDialogData { + readonly: boolean; + image: ImageResourceInfo; +} + +@Component({ + selector: 'tb-embed-image-dialog', + templateUrl: './embed-image-dialog.component.html', + styleUrls: ['./embed-image-dialog.component.scss'] +}) +export class EmbedImageDialogComponent extends + DialogComponent implements OnInit { + + image = this.data.image; + + readonly = this.data.readonly; + + imageChanged = false; + + publicStatusControl = new FormControl(this.image.public); + + constructor(protected store: Store, + protected router: Router, + private imageService: ImageService, + @Inject(MAT_DIALOG_DATA) private data: EmbedImageDialogData, + public dialogRef: MatDialogRef, + public fb: UntypedFormBuilder) { + super(store, router, dialogRef); + } + + ngOnInit(): void { + if (!this.readonly) { + this.publicStatusControl.valueChanges.subscribe( + (isPublic) => { + this.updateImagePublicStatus(isPublic); + } + ); + } + } + + cancel(): void { + this.dialogRef.close(this.imageChanged ? this.image : null); + } + + embedToHtmlCode(): string { + return '```html\n' + + ''+this.image.title.replace(/' + + '{:copy-code}\n' + + '```'; + } + + embedToAngularTemplateCode(): string { + return '```html\n' + + '' + + '{:copy-code}\n' + + '```'; + } + + private updateImagePublicStatus(isPublic: boolean): void { + this.imageService.updateImagePublicStatus(this.image, isPublic).subscribe( + (image) => { + this.image = image; + this.imageChanged = true; + } + ); + } + +} diff --git a/ui-ngx/src/app/shared/components/image/gallery-image-input.component.html b/ui-ngx/src/app/shared/components/image/gallery-image-input.component.html new file mode 100644 index 0000000000..d97035c048 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/gallery-image-input.component.html @@ -0,0 +1,94 @@ + +
+ +
+
+ +
+
+
+
+
+ +
+ {{ imageResource.title }} +
+
+
{{ imageResource.descriptor.width }}x{{ imageResource.descriptor.height }}
+ +
{{ imageResource.descriptor.size | fileSize }}
+
+
+
+
+ + +
+ +
+
+ + +
+
+
+ + +
{{ (disabled ? 'image.no-image' : 'image.no-image-selected') | translate }}
+
+ + + diff --git a/ui-ngx/src/app/shared/components/image/gallery-image-input.component.scss b/ui-ngx/src/app/shared/components/image/gallery-image-input.component.scss new file mode 100644 index 0000000000..d1c9e953a7 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/gallery-image-input.component.scss @@ -0,0 +1,190 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@import "../../../../scss/constants"; + +$containerHeight: 96px !default; + +:host { + .tb-container { + margin-top: 0; + padding: 0 0 16px; + display: flex; + flex-direction: column; + gap: 8px; + label.tb-title { + display: block; + padding-bottom: 0; + } + } + + .tb-image-select-container { + width: 100%; + height: $containerHeight; + border-radius: 4px; + border: 1px solid rgba(0, 0, 0, 0.12); + display: flex; + align-items: center; + &.disabled { + width: $containerHeight; + .tb-image-container { + width: $containerHeight - 2px; + border-right: none; + } + } + } + + .tb-image-container { + width: $containerHeight - 1px; + height: $containerHeight - 2px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 4px; + border-right: 1px solid rgba(0, 0, 0, 0.12); + background: #fff; + overflow: hidden; + } + + .tb-image-preview { + width: auto; + max-width: $containerHeight - 2px; + height: auto; + max-height: $containerHeight - 2px; + } + + .tb-no-image { + text-align: center; + color: rgba(0, 0, 0, 0.38); + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: 0.4px; + } + + .tb-image-info-container { + display: flex; + flex: 1; + align-self: stretch; + padding: 0 8px; + justify-content: flex-end; + align-items: center; + gap: 4px; + .tb-base64-image-container, .tb-resource-image-container, .tb-external-image-container { + display: flex; + flex: 1; + align-self: stretch; + } + .tb-resource-image-container { + padding: 8px; + justify-content: center; + align-items: flex-start; + flex-direction: column; + gap: 4px; + .tb-resource-image-name { + color: rgba(0, 0, 0, 0.54); + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 2; + display: -webkit-box; + -webkit-box-orient: vertical; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + letter-spacing: 0.25px; + } + .tb-resource-image-details { + display: flex; + align-items: center; + gap: 8px; + color: rgba(0, 0, 0, 0.38); + font-size: 11px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: 0.017px; + .mat-divider.mat-divider-vertical { + height: 16px; + } + } + &.loading { + align-items: center; + } + } + + .tb-external-image-container { + padding: 16px 8px 0 16px; + flex-direction: column; + align-items: flex-start; + gap: 4px; + .tb-external-link-label { + color: rgba(0, 0, 0, 0.54); + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: 0.4px; + } + .tb-external-link-input-container { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 4px; + align-self: stretch; + .tb-inline-field { + width: 100%; + } + } + } + + .tb-image-clear-btn { + color: rgba(0,0,0,0.38); + } + } + + .tb-image-select-buttons-container { + display: flex; + flex: 1; + align-self: stretch; + padding: 8px; + gap: 8px; + justify-content: center; + align-items: flex-start; + .tb-image-select-button { + width: 100%; + height: 100%; + align-self: stretch; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 4px; + padding: 8px; + line-height: normal; + font-size: 12px; + @media #{$mat-gt-xs} { + padding: 16px; + } + .mat-icon { + width: 24px; + height: 24px; + font-size: 24px; + margin: 0; + } + } + } +} diff --git a/ui-ngx/src/app/shared/components/image/gallery-image-input.component.ts b/ui-ngx/src/app/shared/components/image/gallery-image-input.component.ts new file mode 100644 index 0000000000..9b81a0eaba --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/gallery-image-input.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 { ChangeDetectorRef, Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { PageComponent } from '@shared/components/page.component'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, } from '@angular/forms'; +import { coerceBoolean } from '@shared/decorators/coercion'; +import { + extractParamsFromImageResourceUrl, + ImageResourceInfo, + isBase64DataImageUrl, + isImageResourceUrl, + prependTbImagePrefix, + removeTbImagePrefix +} from '@shared/models/resource.models'; +import { ImageService } from '@core/http/image.service'; +import { MatDialog } from '@angular/material/dialog'; +import { ImageGalleryDialogComponent } from '@shared/components/image/image-gallery-dialog.component'; + +export enum ImageLinkType { + none = 'none', + base64 = 'base64', + external = 'external', + resource = 'resource' +} + +@Component({ + selector: 'tb-gallery-image-input', + templateUrl: './gallery-image-input.component.html', + styleUrls: ['./gallery-image-input.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => GalleryImageInputComponent), + multi: true + } + ] +}) +export class GalleryImageInputComponent extends PageComponent implements OnInit, OnDestroy, ControlValueAccessor { + + @Input() + label: string; + + @Input() + @coerceBoolean() + required = false; + + @Input() + disabled: boolean; + + imageUrl: string; + + imageResource: ImageResourceInfo; + + loadingImageResource = false; + + ImageLinkType = ImageLinkType; + + linkType: ImageLinkType = ImageLinkType.none; + + externalLinkControl = new FormControl(null); + + private propagateChange = null; + + constructor(protected store: Store, + private imageService: ImageService, + private dialog: MatDialog, + private cd: ChangeDetectorRef) { + super(store); + } + + ngOnInit() { + this.externalLinkControl.valueChanges.subscribe((value) => { + if (this.linkType === ImageLinkType.external) { + this.updateModel(value); + } + }); + } + + ngOnDestroy() { + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.detectLinkType(); + this.externalLinkControl.disable({emitEvent: false}); + } else { + this.externalLinkControl.enable({emitEvent: false}); + } + } + + writeValue(value: string): void { + value = removeTbImagePrefix(value); + if (this.imageUrl !== value) { + this.reset(); + this.imageUrl = value; + this.detectLinkType(); + if (this.linkType === ImageLinkType.resource) { + const params = extractParamsFromImageResourceUrl(this.imageUrl); + this.loadingImageResource = true; + this.imageService.getImageInfo(params.type, params.key, {ignoreLoading: true, ignoreErrors: true}).subscribe( + { + next: (res) => { + this.imageResource = res; + this.loadingImageResource = false; + this.cd.markForCheck(); + }, + error: () => { + this.reset(); + this.loadingImageResource = false; + this.cd.markForCheck(); + } + } + ); + } else if (this.linkType === ImageLinkType.base64) { + this.cd.markForCheck(); + } else if (this.linkType === ImageLinkType.external) { + this.externalLinkControl.setValue(this.imageUrl, {emitEvent: false}); + this.cd.markForCheck(); + } + } + } + + private detectLinkType() { + if (this.imageUrl) { + if (isImageResourceUrl(this.imageUrl)) { + this.linkType = ImageLinkType.resource; + } else if (isBase64DataImageUrl(this.imageUrl)) { + this.linkType = ImageLinkType.base64; + } else { + this.linkType = ImageLinkType.external; + } + } else { + this.linkType = ImageLinkType.none; + } + } + + private updateModel(value: string) { + this.cd.markForCheck(); + if (this.imageUrl !== value) { + this.imageUrl = value; + this.propagateChange(prependTbImagePrefix(this.imageUrl)); + } + } + + private reset() { + this.linkType = ImageLinkType.none; + this.imageResource = null; + this.externalLinkControl.setValue(null, {emitEvent: false}); + } + + clearImage() { + this.reset(); + this.updateModel(null); + } + + setLink($event: Event) { + if ($event) { + $event.stopPropagation(); + } + this.linkType = ImageLinkType.external; + } + + openGallery($event: Event): void { + if ($event) { + $event.stopPropagation(); + } + this.dialog.open(ImageGalleryDialogComponent, { + autoFocus: false, + disableClose: false, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'] + }).afterClosed().subscribe((image) => { + if (image) { + this.linkType = ImageLinkType.resource; + this.imageResource = image; + this.updateModel(image.link); + } + }); + } + +} diff --git a/ui-ngx/src/app/shared/components/image/image-dialog.component.html b/ui-ngx/src/app/shared/components/image/image-dialog.component.html new file mode 100644 index 0000000000..dc2043097a --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-dialog.component.html @@ -0,0 +1,107 @@ + + + +

{{ (readonly ? 'image.image-details' : 'image.edit-image') | translate }}

+ + +
+ + +
+
+
+ + image.name + + + {{ 'image.name-required' | translate }} + + + + +
+
+
+
+ + + +
+ +
+
+
+ +
+
+
{{ image.descriptor.width }}x{{ image.descriptor.height }}
+ +
{{ image.descriptor.size | fileSize }}
+
+
+
+
+
+ diff --git a/ui-ngx/src/app/shared/components/image/image-dialog.component.scss b/ui-ngx/src/app/shared/components/image/image-dialog.component.scss new file mode 100644 index 0000000000..86ec3b2486 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-dialog.component.scss @@ -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 '../../../../scss/constants'; + +:host { + .tb-image-dialog { + @media #{$mat-gt-xs} { + width: 50vh; + } + .mat-mdc-dialog-content { + max-height: 100%; + } + fieldset { + height: 100%; + display: flex; + flex-direction: column; + } + } + .tb-image-container { + height: 100%; + border-radius: 4px; + border: 1px solid rgba(0, 0, 0, 0.05); + padding: 12px; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; + + .tb-image-content { + height: 100%; + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + .tb-image-preview-container { + position: relative; + width: 100%; + height: 100%; + border: 1px solid rgba(0, 0, 0, 0.12); + border-radius: 4px; + background: #fff; + display: flex; + align-items: center; + justify-content: center; + z-index: 1; + .tb-image-preview-spacer { + @media #{$mat-gt-xs} { + margin-top: 100%; + } + } + .tb-image-preview { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: contain; + } + } + .tb-image-preview-details { + display: flex; + align-items: center; + gap: 8px; + color: rgba(0, 0, 0, 0.38); + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + .mat-divider.mat-divider-vertical { + height: 20px; + } + } + .tb-image-actions { + display: flex; + align-items: center; + align-self: stretch; + justify-content: space-between; + gap: 8px; + color: rgba(0,0,0,0.54); + } + } + } +} diff --git a/ui-ngx/src/app/shared/components/image/image-dialog.component.ts b/ui-ngx/src/app/shared/components/image/image-dialog.component.ts new file mode 100644 index 0000000000..434d76d74d --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-dialog.component.ts @@ -0,0 +1,163 @@ +/// +/// 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, Inject, OnInit, SkipSelf } from '@angular/core'; +import { ErrorStateMatcher } from '@angular/material/core'; +import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { Router } from '@angular/router'; +import { ImageService } from '@core/http/image.service'; +import { ImageResourceInfo, imageResourceType } from '@shared/models/resource.models'; +import { + UploadImageDialogComponent, + UploadImageDialogData +} from '@shared/components/image/upload-image-dialog.component'; +import { UrlHolder } from '@shared/pipe/image.pipe'; +import { ImportExportService } from '@shared/import-export/import-export.service'; +import { EmbedImageDialogComponent, EmbedImageDialogData } from '@shared/components/image/embed-image-dialog.component'; + +export interface ImageDialogData { + readonly: boolean; + image: ImageResourceInfo; +} + +@Component({ + selector: 'tb-image-dialog', + templateUrl: './image-dialog.component.html', + styleUrls: ['./image-dialog.component.scss'] +}) +export class ImageDialogComponent extends + DialogComponent implements OnInit { + + image: ImageResourceInfo; + + readonly: boolean; + + imageFormGroup: UntypedFormGroup; + + imageChanged = false; + + imagePreviewData: UrlHolder; + + constructor(protected store: Store, + protected router: Router, + private imageService: ImageService, + private dialog: MatDialog, + private importExportService: ImportExportService, + @Inject(MAT_DIALOG_DATA) private data: ImageDialogData, + public dialogRef: MatDialogRef, + public fb: UntypedFormBuilder) { + super(store, router, dialogRef); + this.image = data.image; + this.readonly = data.readonly; + this.imagePreviewData = { + url: this.image.public ? this.image.publicLink : this.image.link + }; + } + + ngOnInit(): void { + this.imageFormGroup = this.fb.group({ + title: [this.image.title, [Validators.required]] + }); + if (this.data.readonly) { + this.imageFormGroup.disable(); + } + } + + cancel(): void { + this.dialogRef.close(this.imageChanged ? this.image : null); + } + + revertInfo(): void { + this.imageFormGroup.get('title').setValue(this.image.title); + this.imageFormGroup.markAsPristine(); + } + + saveInfo(): void { + const title: string = this.imageFormGroup.get('title').value; + const image = {...this.image, ...{title}}; + this.imageService.updateImageInfo(image).subscribe( + (saved) => { + this.image = saved; + this.imageChanged = true; + this.imageFormGroup.markAsPristine(); + } + ); + } + + downloadImage($event) { + if ($event) { + $event.stopPropagation(); + } + this.imageService.downloadImage(imageResourceType(this.image), this.image.resourceKey).subscribe(); + } + + exportImage($event) { + if ($event) { + $event.stopPropagation(); + } + this.importExportService.exportImage(imageResourceType(this.image), this.image.resourceKey); + } + + embedImage($event: Event) { + if ($event) { + $event.stopPropagation(); + } + this.dialog.open(EmbedImageDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + image: this.image, + readonly: this.readonly + } + }).afterClosed().subscribe((result) => { + if (result) { + this.imageChanged = true; + this.image = result; + this.imagePreviewData = { + url: this.image.public ? this.image.publicLink : this.image.link + }; + } + }); + } + + updateImage($event): void { + if ($event) { + $event.stopPropagation(); + } + this.dialog.open(UploadImageDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + image: this.image + } + }).afterClosed().subscribe((result) => { + if (result) { + this.imageChanged = true; + this.image = result; + this.imagePreviewData = { + url: this.image.public ? this.image.publicLink : this.image.link + }; + } + }); + } + +} diff --git a/ui-ngx/src/app/shared/components/image/image-gallery-dialog.component.html b/ui-ngx/src/app/shared/components/image/image-gallery-dialog.component.html new file mode 100644 index 0000000000..8e24e2ffb2 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-gallery-dialog.component.html @@ -0,0 +1,32 @@ + + diff --git a/ui-ngx/src/app/shared/components/image/image-gallery-dialog.component.scss b/ui-ngx/src/app/shared/components/image/image-gallery-dialog.component.scss new file mode 100644 index 0000000000..6ebda09fb5 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-gallery-dialog.component.scss @@ -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 '../../../../scss/constants'; + +:host { + .tb-image-gallery-dialog { + position: relative; + padding: 24px 32px 16px 32px; + width: 100vw; + height: 100vh; + max-height: 100vh; + @media #{$mat-gt-xs} { + width: 80vw; + height: 80vh; + max-height: 80vh; + } + @media #{$mat-gt-sm} { + width: 700px; + } + @media #{$mat-gt-md} { + width: 900px; + } + @media #{$mat-gt-xl} { + width: 900px; + } + .tb-image-gallery-close { + position: absolute; + top: 12px; + right: 12px; + z-index: 1; + color: rgba(0, 0, 0, 0.38); + } + } +} diff --git a/ui-ngx/src/app/shared/components/image/image-gallery-dialog.component.ts b/ui-ngx/src/app/shared/components/image/image-gallery-dialog.component.ts new file mode 100644 index 0000000000..482fbe76a5 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-gallery-dialog.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, Inject, OnInit, SkipSelf } from '@angular/core'; +import { ErrorStateMatcher } from '@angular/material/core'; +import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { Router } from '@angular/router'; +import { ImageService } from '@core/http/image.service'; +import { ImageResourceInfo, imageResourceType } from '@shared/models/resource.models'; +import { + UploadImageDialogComponent, + UploadImageDialogData +} from '@shared/components/image/upload-image-dialog.component'; +import { UrlHolder } from '@shared/pipe/image.pipe'; +import { ImportExportService } from '@shared/import-export/import-export.service'; +import { EmbedImageDialogComponent, EmbedImageDialogData } from '@shared/components/image/embed-image-dialog.component'; + +@Component({ + selector: 'tb-image-gallery-dialog', + templateUrl: './image-gallery-dialog.component.html', + styleUrls: ['./image-gallery-dialog.component.scss'] +}) +export class ImageGalleryDialogComponent extends + DialogComponent implements OnInit { + + constructor(protected store: Store, + protected router: Router, + private imageService: ImageService, + private dialog: MatDialog, + public dialogRef: MatDialogRef) { + super(store, router, dialogRef); + } + + ngOnInit(): void { + } + + cancel(): void { + this.dialogRef.close(null); + } + + imageSelected(image: ImageResourceInfo): void { + this.dialogRef.close(image); + } + +} diff --git a/ui-ngx/src/app/shared/components/image/image-gallery.component.html b/ui-ngx/src/app/shared/components/image/image-gallery.component.html new file mode 100644 index 0000000000..21b10e8c66 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-gallery.component.html @@ -0,0 +1,397 @@ + +
+
+ +
+
+ image.gallery +
+
+ +
+
+ +
+
+ {{ 'image.include-system-images' | translate }} +
+
+ +
+ + + + +
+ +
+
+ {{ 'image.include-system-images' | translate }} +
+ +
+ + +   + + + +
+
+ +
+ + {{ translate.get('image.selected-images', {count: dataSource?.selection.selected.length}) | async }} + + + +
+
+
+
+ + + + + + + + + + + + + + +
+ {{ image.title }} +
+
+
+ + {{ 'image.name' | translate }} + + {{ image.title }} + + + + {{ 'image.created-time' | translate }} + + {{ image.createdTime | date:'yyyy-MM-dd HH:mm:ss' }} + + + + {{ 'image.resolution' | translate }} + + {{ image.descriptor.width }}x{{ image.descriptor.height }} + + + + {{ 'image.size' | translate }} + + {{ image.descriptor.size | fileSize }} + + + + {{ 'image.system' | translate }} + + {{isSystem(image) ? 'check_box' : 'check_box_outline_blank'}} + + + + + + +
+ + + + + +
+
+ + + + + + + + +
+
+
+ + + + + + + + +
+ + + + {{ 'common.loading' | translate }} +
+ + +
+
+ + +
+
+
+ +
+ + {{ 'common.loading' | translate }} + +
+
+ +
+
+
image.no-images
+
+
+ +
+
+
+ + + + +
+
+
+
+ + +
+
+ {{ item.title }} +
+
+
+
+ {{ item.title }} +
+
sys
+
+
+
{{ item.descriptor.width }}x{{ item.descriptor.height }}
+ +
{{ item.descriptor.size | fileSize }}
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/ui-ngx/src/app/shared/components/image/image-gallery.component.scss b/ui-ngx/src/app/shared/components/image/image-gallery.component.scss new file mode 100644 index 0000000000..cd81199053 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-gallery.component.scss @@ -0,0 +1,274 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@import "../../../../scss/constants"; + +$tb-button-selected-color: rgb(255, 110, 64) !default; + +.tb-images { + + &.tb-dialog-mode { + position: relative; + width: 100%; + height: 100%; + .mat-toolbar.mat-mdc-table-toolbar { + padding: 0; + } + } + + .tb-images-content { + width: 100%; + height: 100%; + background: #fff; + overflow: hidden; + + &.tb-outlined-border { + box-shadow: 0 0 0 0 rgb(0 0 0 / 20%), 0 0 0 0 rgb(0 0 0 / 14%), 0 0 0 0 rgb(0 0 0 / 12%); + border: solid 1px #e0e0e0; + border-radius: 4px; + } + + .mat-mdc-table-toolbar { + &.multi-row { + &.mat-toolbar-single-row { + height: 112px; + } + .mat-mdc-slide-toggle { + display: flex; + min-height: 48px; + } + } + } + + .tb-images-title { + padding-right: 20px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .tb-images-view-type-toolbar { + height: 55px; + min-height: 55px; + padding-right: 16px; + background-color: transparent; + box-shadow: none; + + .tb-toolbar-button { + height: 48px; + button.mat-mdc-icon-button { + margin: 0; + } + &.tb-selected { + background-color: rgba(255, 255, 255, .15); + border-bottom: $tb-button-selected-color solid 4px; + + button.mat-mdc-icon-button { + margin-bottom: -4px; + + .mat-icon { + color: $tb-button-selected-color; + fill: $tb-button-selected-color; + } + } + } + } + } + + .table-container, tb-scroll-grid { + position: relative; + } + + .tb-no-images { + position: absolute; + inset: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + + .tb-image-card { + position: relative; + height: 100%; + border-radius: 4px; + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.24); + padding: 8px; + display: flex; + gap: 8px; + flex-direction: column; + cursor: pointer; + + .tb-image-card-overlay { + position: absolute; + pointer-events: none; + inset: 0; + border-radius: 4px; + z-index: 2; + display: flex; + flex-direction: column; + .tb-image-card-overlay-buttons { + width: 100%; + display: flex; + justify-content: flex-end; + align-items: center; + color: rgba(0,0,0,0.78); + opacity: 0; + transition: opacity 0.5s; + } + } + + &:hover { + .tb-image-card-overlay { + .tb-image-card-overlay-buttons { + opacity: 1; + } + } + .tb-image-preview-container { + .tb-image-preview-overlay { + background: rgba(245,245,245,0.6); + backdrop-filter: blur(4px); + .mdc-button { + opacity: 1; + } + } + } + } + + .tb-image-preview-container { + position: relative; + .tb-image-preview-overlay { + position: absolute; + inset: 0; + z-index: 1; + background: rgba(245,245,245,0); + backdrop-filter: none; + transition: all 0.5s; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + .mdc-button { + opacity: 0; + transition: opacity 0.5s; + } + } + .tb-image-preview-spacer { + margin-top: 100%; + } + .tb-image-preview { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + } + } + + .tb-image-details { + min-height: 52px; + flex: 1; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; + gap: 4px; + align-self: stretch; + .tb-image-title-container { + display: flex; + align-items: center; + gap: 8px; + align-self: stretch; + .tb-image-title { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 2; + display: -webkit-box; + -webkit-box-orient: vertical; + color: rgba(0, 0, 0, 0.76); + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + } + .tb-image-sys { + padding: 1px 4px; + border-radius: 4px; + background: rgba(236, 236, 236, 0.64); + color: rgba(0, 0, 0, 0.54); + font-size: 11px; + font-style: normal; + font-weight: 500; + line-height: 16px; + letter-spacing: 0.017px; + } + } + .tb-image-info-container { + display: flex; + align-items: center; + gap: 8px; + align-self: stretch; + color: rgba(0, 0, 0, 0.38); + font-size: 10px; + font-style: normal; + font-weight: 400; + line-height: 16px; + .mat-divider.mat-divider-vertical { + height: 16px; + } + } + } + &.loading-cell { + .tb-image-preview-container, .tb-image-details { + background: linear-gradient(110deg, #ececec 8%, #f5f5f5 18%, #ececec 33%); + border-radius: 5px; + background-size: 200% 100%; + animation: 1s shine linear infinite; + } + } + } + + .table-container { + overflow: auto; + + .mat-sort-header-sorted .mat-sort-header-arrow { + opacity: 1 !important; + } + .mat-mdc-cell.mat-column-preview { + width: 50px; + height: 50px; + padding: 2px 12px; + } + } + + .tb-image-preview-cell { + width: 50px; + height: 50px; + } + + .tb-image-preview { + width: 50px; + height: 50px; + object-fit: contain; + border-radius: 4px; + } + } +} + +@keyframes shine { + to { + background-position-x: -200%; + } +} diff --git a/ui-ngx/src/app/shared/components/image/image-gallery.component.ts b/ui-ngx/src/app/shared/components/image/image-gallery.component.ts new file mode 100644 index 0000000000..d0451cebcd --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-gallery.component.ts @@ -0,0 +1,702 @@ +/// +/// 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 { + ImageResourceInfo, + ImageResourceInfoWithReferences, + imageResourceType, + toImageDeleteResult +} from '@shared/models/resource.models'; +import { forkJoin, merge, Observable, of, Subject, Subscription } from 'rxjs'; +import { ImageService } from '@core/http/image.service'; +import { TranslateService } from '@ngx-translate/core'; +import { PageLink, PageQueryParam } from '@shared/models/page/page-link'; +import { catchError, debounceTime, distinctUntilChanged, map, skip, takeUntil } from 'rxjs/operators'; +import { + AfterViewInit, + ChangeDetectorRef, + Component, + ElementRef, EventEmitter, HostBinding, + Input, + OnDestroy, + OnInit, Output, + ViewChild, + ViewEncapsulation +} from '@angular/core'; +import { PageComponent } from '@shared/components/page.component'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort, SortDirection } from '@angular/material/sort'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { DialogService } from '@core/services/dialog.service'; +import { FormBuilder } from '@angular/forms'; +import { Direction, SortOrder } from '@shared/models/page/sort-order'; +import { ResizeObserver } from '@juggle/resize-observer'; +import { hidePageSizePixelValue } from '@shared/models/constants'; +import { coerceBoolean } from '@shared/decorators/coercion'; +import { ActivatedRoute, QueryParamsHandling, Router } from '@angular/router'; +import { isEqual, isNotEmptyStr, parseHttpErrorMessage } from '@core/utils'; +import { BaseData, HasId } from '@shared/models/base-data'; +import { NULL_UUID } from '@shared/models/id/has-uuid'; +import { getCurrentAuthUser } from '@core/auth/auth.selectors'; +import { Authority } from '@shared/models/authority.enum'; +import { GridEntitiesFetchFunction, ScrollGridColumns } from '@shared/components/grid/scroll-grid-datasource'; +import { ItemSizeStrategy, ScrollGridComponent } from '@shared/components/grid/scroll-grid.component'; +import { MatDialog } from '@angular/material/dialog'; +import { + UploadImageDialogComponent, + UploadImageDialogData +} from '@shared/components/image/upload-image-dialog.component'; +import { ImageDialogComponent, ImageDialogData } from '@shared/components/image/image-dialog.component'; +import { ImportExportService } from '@shared/import-export/import-export.service'; +import { ActionNotificationShow } from '@core/notification/notification.actions'; +import { + ImagesInUseDialogComponent, + ImagesInUseDialogData +} from '@shared/components/image/images-in-use-dialog.component'; +import { ImagesDatasource } from '@shared/components/image/images-datasource'; +import { EmbedImageDialogComponent, EmbedImageDialogData } from '@shared/components/image/embed-image-dialog.component'; + +interface GridImagesFilter { + search: string; + includeSystemImages: boolean; +} + +const pageGridColumns: ScrollGridColumns = { + columns: 2, + breakpoints: { + 'screen and (min-width: 2320px)': 10, + 'screen and (min-width: 2000px)': 8, + 'gt-lg': 7, + 'screen and (min-width: 1600px)': 6, + 'gt-md': 5, + 'screen and (min-width: 1120px)': 4, + 'gt-xs': 3 + } +}; + +const dialogGridColumns: ScrollGridColumns = { + columns: 2, + breakpoints: { + 'gt-md': 4, + 'gt-xs': 3 + } +}; + +@Component({ + selector: 'tb-image-gallery', + templateUrl: './image-gallery.component.html', + styleUrls: ['./image-gallery.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class ImageGalleryComponent extends PageComponent implements OnInit, OnDestroy, AfterViewInit { + + @HostBinding('style.display') + private display = 'block'; + + @HostBinding('style.width') + private width = '100%'; + + @HostBinding('style.height') + private height = '100%'; + + @Input() + @coerceBoolean() + pageMode = true; + + @Input() + @coerceBoolean() + dialogMode = false; + + @Input() + mode: 'list' | 'grid' = 'list'; + + @Input() + @coerceBoolean() + selectionMode = false; + + @Output() + imageSelected = new EventEmitter(); + + @ViewChild('searchInput') searchInputField: ElementRef; + + @ViewChild(MatPaginator) paginator: MatPaginator; + @ViewChild(MatSort) sort: MatSort; + + @ViewChild(ScrollGridComponent) gridComponent: ScrollGridComponent; + + defaultPageSize = 10; + defaultSortOrder: SortOrder = { property: 'createdTime', direction: Direction.DESC }; + hidePageSize = false; + + displayedColumns: string[]; + pageSizeOptions: number[]; + pageLink: PageLink; + + textSearchMode = false; + + dataSource: ImagesDatasource; + + textSearch = this.fb.control('', {nonNullable: true}); + includeSystemImages = false; + + gridColumns: ScrollGridColumns; + + gridImagesFetchFunction: GridEntitiesFetchFunction; + gridImagesFilter: GridImagesFilter = { + search: '', + includeSystemImages: false + }; + + gridImagesItemSizeStrategy: ItemSizeStrategy = { + defaultItemSize: 200, + itemSizeFunction: itemWidth => itemWidth + 72 + }; + + authUser = getCurrentAuthUser(this.store); + + private updateDataSubscription: Subscription; + + private widgetResize$: ResizeObserver; + private destroy$ = new Subject(); + private destroyListMode$: Subject; + + constructor(protected store: Store, + private route: ActivatedRoute, + private router: Router, + private dialog: MatDialog, + public translate: TranslateService, + private imageService: ImageService, + private dialogService: DialogService, + private importExportService: ImportExportService, + private elementRef: ElementRef, + private cd: ChangeDetectorRef, + private fb: FormBuilder) { + super(store); + + this.gridImagesFetchFunction = (pageSize, page, filter) => { + const pageLink = new PageLink(pageSize, page, filter.search, { + property: 'createdTime', + direction: Direction.DESC + }); + return this.imageService.getImages(pageLink, filter.includeSystemImages); + }; + } + + ngOnInit(): void { + this.gridColumns = this.dialogMode ? dialogGridColumns : pageGridColumns; + this.displayedColumns = this.computeDisplayedColumns(); + let sortOrder: SortOrder = this.defaultSortOrder; + this.pageSizeOptions = [this.defaultPageSize, this.defaultPageSize * 2, this.defaultPageSize * 3]; + const routerQueryParams: PageQueryParam = this.route.snapshot.queryParams; + if (this.pageMode) { + if (routerQueryParams.hasOwnProperty('direction') + || routerQueryParams.hasOwnProperty('property')) { + sortOrder = { + property: routerQueryParams?.property || this.defaultSortOrder.property, + direction: routerQueryParams?.direction || this.defaultSortOrder.direction + }; + } + } + this.pageLink = new PageLink(this.defaultPageSize, 0, null, sortOrder); + if (this.pageMode) { + if (routerQueryParams.hasOwnProperty('page')) { + this.pageLink.page = Number(routerQueryParams.page); + } + if (routerQueryParams.hasOwnProperty('pageSize')) { + this.pageLink.pageSize = Number(routerQueryParams.pageSize); + } + const textSearchParam = routerQueryParams.textSearch; + if (isNotEmptyStr(textSearchParam)) { + const decodedTextSearch = decodeURI(textSearchParam); + this.textSearchMode = true; + this.pageLink.textSearch = decodedTextSearch.trim(); + this.textSearch.setValue(decodedTextSearch, {emitEvent: false}); + } + } + if (this.mode === 'list') { + this.dataSource = new ImagesDatasource(this.imageService, null, + entity => this.deleteEnabled(entity)); + } + } + + ngOnDestroy(): void { + if (this.widgetResize$) { + this.widgetResize$.disconnect(); + } + if (this.destroyListMode$) { + this.destroyListMode$.next(); + this.destroyListMode$.complete(); + } + this.destroy$.next(); + this.destroy$.complete(); + } + + ngAfterViewInit() { + this.textSearch.valueChanges.pipe( + debounceTime(150), + distinctUntilChanged((prev, current) => + ((this.mode === 'list' ? this.pageLink.textSearch : this.gridImagesFilter.search) ?? '') === current.trim()), + takeUntil(this.destroy$) + ).subscribe(value => { + if (this.mode === 'list') { + if (this.pageMode) { + const queryParams: PageQueryParam = { + textSearch: isNotEmptyStr(value) ? encodeURI(value) : null, + page: null + }; + this.updatedRouterParamsAndData(queryParams); + } else { + this.pageLink.textSearch = isNotEmptyStr(value) ? value.trim() : null; + this.paginator.pageIndex = 0; + this.updateData(); + } + } else { + this.gridImagesFilter = { + search: isNotEmptyStr(value) ? value.trim() : null, + includeSystemImages: this.includeSystemImages + }; + this.cd.markForCheck(); + } + }); + this.updateMode(); + } + + public includeSystemImagesChanged(value: boolean) { + this.includeSystemImages = value; + this.displayedColumns = this.computeDisplayedColumns(); + this.gridImagesFilter = { + search: this.gridImagesFilter.search, + includeSystemImages: this.includeSystemImages + }; + if (this.mode === 'list') { + this.paginator.pageIndex = 0; + this.updateData(); + } else { + this.cd.markForCheck(); + } + } + + public setMode(targetMode: 'list' | 'grid') { + if (this.mode !== targetMode) { + if (this.widgetResize$) { + this.widgetResize$.disconnect(); + this.widgetResize$ = null; + } + if (this.destroyListMode$) { + this.destroyListMode$.next(); + this.destroyListMode$.complete(); + this.destroyListMode$ = null; + } + this.mode = targetMode; + if (this.mode === 'list') { + this.dataSource = new ImagesDatasource(this.imageService, null, + entity => this.deleteEnabled(entity)); + } + setTimeout(() => { + this.updateMode(); + }); + } + } + + public get isSysAdmin(): boolean { + return this.authUser.authority === Authority.SYS_ADMIN; + } + + private computeDisplayedColumns(): string[] { + let columns: string[]; + if (this.selectionMode) { + columns = ['preview', 'title']; + if (!this.isSysAdmin && this.includeSystemImages) { + columns.push('system'); + } + columns.push('imageSelect'); + } else { + columns = ['select', 'preview', 'title', 'createdTime', 'resolution', 'size']; + if (!this.isSysAdmin && this.includeSystemImages) { + columns.push('system'); + } + columns.push('actions'); + } + return columns; + } + + private updateMode() { + if (this.mode === 'list') { + this.initListMode(); + } else { + this.initGridMode(); + } + } + + private initListMode() { + this.destroyListMode$ = new Subject(); + this.widgetResize$ = new ResizeObserver(() => { + const showHidePageSize = this.elementRef.nativeElement.offsetWidth < hidePageSizePixelValue; + if (showHidePageSize !== this.hidePageSize) { + this.hidePageSize = showHidePageSize; + this.cd.markForCheck(); + } + }); + this.widgetResize$.observe(this.elementRef.nativeElement); + if (this.pageMode) { + this.route.queryParams.pipe( + skip(1), + takeUntil(this.destroyListMode$) + ).subscribe((params: PageQueryParam) => { + this.paginator.pageIndex = Number(params.page) || 0; + this.paginator.pageSize = Number(params.pageSize) || this.defaultPageSize; + this.sort.active = params.property || this.defaultSortOrder.property; + this.sort.direction = (params.direction || this.defaultSortOrder.direction).toLowerCase() as SortDirection; + const textSearchParam = params.textSearch; + if (isNotEmptyStr(textSearchParam)) { + const decodedTextSearch = decodeURI(textSearchParam); + this.textSearchMode = true; + this.pageLink.textSearch = decodedTextSearch.trim(); + this.textSearch.setValue(decodedTextSearch, {emitEvent: false}); + } else { + this.pageLink.textSearch = null; + this.textSearch.reset('', {emitEvent: false}); + } + this.updateData(); + }); + } + this.updatePaginationSubscriptions(); + this.updateData(); + } + + private initGridMode() { + + } + + private updatePaginationSubscriptions() { + if (this.updateDataSubscription) { + this.updateDataSubscription.unsubscribe(); + this.updateDataSubscription = null; + } + const sortSubscription$: Observable = this.sort.sortChange.asObservable().pipe( + map((data) => { + const direction = data.direction.toUpperCase(); + const queryParams: PageQueryParam = { + direction: (this.defaultSortOrder.direction === direction ? null : direction) as Direction, + property: this.defaultSortOrder.property === data.active ? null : data.active + }; + queryParams.page = null; + this.paginator.pageIndex = 0; + return queryParams; + }) + ); + const paginatorSubscription$ = this.paginator.page.asObservable().pipe( + map((data) => ({ + page: data.pageIndex === 0 ? null : data.pageIndex, + pageSize: data.pageSize === this.defaultPageSize ? null : data.pageSize + })) + ); + this.updateDataSubscription = (merge(sortSubscription$, paginatorSubscription$) as Observable).pipe( + takeUntil(this.destroyListMode$) + ).subscribe(queryParams => this.updatedRouterParamsAndData(queryParams)); + } + + clearSelection() { + this.dataSource.selection.clear(); + this.cd.detectChanges(); + } + + updateData() { + if (this.mode === 'list') { + this.pageLink.page = this.paginator.pageIndex; + this.pageLink.pageSize = this.paginator.pageSize; + if (this.sort.active) { + this.pageLink.sortOrder = { + property: this.sort.active, + direction: Direction[this.sort.direction.toUpperCase()] + }; + } else { + this.pageLink.sortOrder = null; + } + this.dataSource.loadEntities(this.pageLink, this.includeSystemImages); + } else { + this.gridComponent.update(); + } + } + + private imageUpdated(image: ImageResourceInfo, index = -1) { + if (this.mode === 'list') { + this.updateData(); + } else { + this.gridComponent.updateItem(index, image); + } + } + + private imageDeleted(index = -1) { + if (this.mode === 'list') { + this.updateData(); + } else { + this.gridComponent.deleteItem(index); + } + } + + enterFilterMode() { + this.textSearchMode = true; + setTimeout(() => { + this.searchInputField.nativeElement.focus(); + this.searchInputField.nativeElement.setSelectionRange(0, 0); + }, 10); + } + + exitFilterMode() { + this.textSearchMode = false; + this.textSearch.reset(); + } + + trackByEntity(index: number, entity: BaseData) { + return entity; + } + + isSystem(image?: ImageResourceInfo): boolean { + return !this.isSysAdmin && image?.tenantId?.id === NULL_UUID; + } + + readonly(image?: ImageResourceInfo): boolean { + return this.authUser.authority !== Authority.SYS_ADMIN && this.isSystem(image); + } + + deleteEnabled(image?: ImageResourceInfo): boolean { + return this.authUser.authority === Authority.SYS_ADMIN || !this.isSystem(image); + } + + deleteImage($event: Event, image: ImageResourceInfo, itemIndex = -1) { + if ($event) { + $event.stopPropagation(); + } + const title = this.translate.instant('image.delete-image-title', {imageTitle: image.title}); + const content = this.translate.instant('image.delete-image-text'); + this.dialogService.confirm(title, content, + this.translate.instant('action.no'), + this.translate.instant('action.yes')).subscribe((result) => { + if (result) { + this.imageService.deleteImage(imageResourceType(image), image.resourceKey, false, {ignoreErrors: true}).pipe( + map(() => toImageDeleteResult(image)), + catchError((err) => of(toImageDeleteResult(image, err))) + ).subscribe( + (deleteResult) => { + if (deleteResult.success) { + this.imageDeleted(itemIndex); + } else if (deleteResult.imageIsReferencedError) { + this.dialog.open(ImagesInUseDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + multiple: false, + images: [{...image, ...{references: deleteResult.references}}] + } + }).afterClosed().subscribe((images) => { + if (images) { + this.imageService.deleteImage(imageResourceType(image), image.resourceKey, true).subscribe( + () => { + this.imageDeleted(itemIndex); + } + ); + } + }); + } else { + const errorMessageWithTimeout = parseHttpErrorMessage(deleteResult.error, this.translate); + setTimeout(() => { + this.store.dispatch(new ActionNotificationShow({message: errorMessageWithTimeout.message, type: 'error'})); + }, errorMessageWithTimeout.timeout); + } + }); + } + }); + } + + deleteImages($event: Event) { + if ($event) { + $event.stopPropagation(); + } + const selectedImages = this.dataSource.selection.selected; + if (selectedImages && selectedImages.length) { + const title = this.translate.instant('image.delete-images-title', {count: selectedImages.length}); + const content = this.translate.instant('image.delete-images-text'); + this.dialogService.confirm(title, content, + this.translate.instant('action.no'), + this.translate.instant('action.yes')).subscribe((result) => { + if (result) { + const tasks = selectedImages.map((image) => + this.imageService.deleteImage(imageResourceType(image), image.resourceKey, false, {ignoreErrors: true}).pipe( + map(() => toImageDeleteResult(image)), + catchError((err) => of(toImageDeleteResult(image, err))) + ) + ); + forkJoin(tasks).subscribe( + (deleteResults) => { + const anySuccess = deleteResults.some(res => res.success); + const referenceErrors = deleteResults.filter(res => res.imageIsReferencedError); + const otherError = deleteResults.find(res => !res.success); + if (anySuccess) { + this.updateData(); + } + if (referenceErrors?.length) { + const imagesWithReferences: ImageResourceInfoWithReferences[] = + referenceErrors.map(ref => ({...ref.image, ...{references: ref.references}})); + this.dialog.open(ImagesInUseDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + multiple: true, + images: imagesWithReferences + } + }).afterClosed().subscribe((forceDeleteImages) => { + if (forceDeleteImages && forceDeleteImages.length) { + const forceDeleteTasks = forceDeleteImages.map((image) => + this.imageService.deleteImage(imageResourceType(image), image.resourceKey, true) + ); + forkJoin(forceDeleteTasks).subscribe( + () => { + this.updateData(); + } + ); + } + }); + } else if (otherError) { + const errorMessageWithTimeout = parseHttpErrorMessage(otherError.error, this.translate); + setTimeout(() => { + this.store.dispatch(new ActionNotificationShow({message: errorMessageWithTimeout.message, type: 'error'})); + }, errorMessageWithTimeout.timeout); + } + } + ); + } + }); + } + } + + downloadImage($event, image: ImageResourceInfo) { + if ($event) { + $event.stopPropagation(); + } + this.imageService.downloadImage(imageResourceType(image), image.resourceKey).subscribe(); + } + + exportImage($event, image: ImageResourceInfo) { + if ($event) { + $event.stopPropagation(); + } + this.importExportService.exportImage(imageResourceType(image), image.resourceKey); + } + + importImage(): void { + this.importExportService.importImage().subscribe((image) => { + if (image) { + if (this.selectionMode) { + this.imageSelected.next(image); + } else { + this.updateData(); + } + } + }); + } + + selectImage($event, image: ImageResourceInfo) { + if ($event) { + $event.stopPropagation(); + } + this.imageSelected.next(image); + } + + rowClick($event, image: ImageResourceInfo) { + if (this.selectionMode) { + this.selectImage($event, image); + } else { + if (this.deleteEnabled(image)) { + this.dataSource.selection.toggle(image); + } + } + } + + uploadImage(): void { + this.dialog.open(UploadImageDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: {} + }).afterClosed().subscribe((result) => { + if (result) { + if (this.selectionMode) { + this.imageSelected.next(result); + } else { + this.updateData(); + } + } + }); + } + + editImage($event: Event, image: ImageResourceInfo, itemIndex = -1) { + if ($event) { + $event.stopPropagation(); + } + this.dialog.open(ImageDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + image, + readonly: this.readonly(image) + } + }).afterClosed().subscribe((result) => { + if (result) { + this.imageUpdated(result, itemIndex); + } + }); + } + + embedImage($event: Event, image: ImageResourceInfo, itemIndex = -1) { + if ($event) { + $event.stopPropagation(); + } + this.dialog.open(EmbedImageDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + image, + readonly: this.readonly(image) + } + }).afterClosed().subscribe((result) => { + if (result) { + this.imageUpdated(result, itemIndex); + } + }); + } + + protected updatedRouterParamsAndData(queryParams: object, queryParamsHandling: QueryParamsHandling = 'merge') { + if (this.pageMode) { + this.router.navigate([], { + relativeTo: this.route, + queryParams, + queryParamsHandling + }); + if (queryParamsHandling === '' && isEqual(this.route.snapshot.queryParams, queryParams)) { + this.updateData(); + } + } else { + this.updateData(); + } + } + +} diff --git a/ui-ngx/src/app/shared/components/image/image-references.component.html b/ui-ngx/src/app/shared/components/image/image-references.component.html new file mode 100644 index 0000000000..a9b6943bea --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-references.component.html @@ -0,0 +1,54 @@ + + + + + + +
    + +
  • +
    {{ 'image.system-entities' | translate }}
    + +
  • + +
  • +
    + {{ 'tenant.tenant' | translate }} {{ entry[1].tenantName }} {{ 'image.entities' | translate }} +
    + +
  • +
    +
    +
+
+
+ + + + + + +
{{ referencedEntity.typeName }} + {{ referencedEntity.entity.name }} + {{ referencedEntity.entity.name }} +
+
+ + + diff --git a/ui-ngx/src/app/shared/components/image/image-references.component.scss b/ui-ngx/src/app/shared/components/image/image-references.component.scss new file mode 100644 index 0000000000..bef9cc61ea --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-references.component.scss @@ -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 "../../../../scss/constants"; + +:host { + ul.tb-references { + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 12px; + } + li.tb-entities-container { + padding: 8px 12px 12px 12px; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + border-radius: 8px; + } + a.tb-reference { + color: $tb-primary-color; + font-weight: inherit; + } + .tb-entities-title { + display: flex; + gap: 8px; + color: rgba(0, 0, 0, 0.87); + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: 0.25px; + } + table.tb-entities-list-table { + position: relative; + overflow: hidden; + padding: 8px 10px 8px 4px; + border-radius: 4px; + background: #fff; + align-self: stretch; + z-index: 1; + color: rgba(0, 0, 0, 0.76); + &:before { + display: block; + height: auto; + content: ""; + position: absolute; + inset: 0; + border-radius: 4px; + border: 1px solid $tb-primary-color; + background: transparent; + opacity: 0.4; + pointer-events: none; + } + td.tb-entity-type { + white-space: nowrap; + padding-right: 20px; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: 0.25px; + &:before { + content: "•"; + padding-left: 8px; + padding-right: 8px; + } + } + td.tb-entity-name { + width: 100%; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: 0.2px; + } + } +} diff --git a/ui-ngx/src/app/shared/components/image/image-references.component.ts b/ui-ngx/src/app/shared/components/image/image-references.component.ts new file mode 100644 index 0000000000..e7ae17d50d --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/image-references.component.ts @@ -0,0 +1,171 @@ +/// +/// 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 { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { ImageReferences } from '@shared/models/resource.models'; +import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models'; +import { TranslateService } from '@ngx-translate/core'; +import { getEntityDetailsPageURL } from '@core/utils'; +import { getCurrentAuthUser } from '@core/auth/auth.selectors'; +import { NULL_UUID } from '@shared/models/id/has-uuid'; +import { Authority } from '@shared/models/authority.enum'; +import { Observable } from 'rxjs'; +import { EntityService } from '@core/http/entity.service'; +import { BaseData, HasId } from '@shared/models/base-data'; +import { HasTenantId } from '@shared/models/entity.models'; +import { map } from 'rxjs/operators'; +import { TbPopoverComponent } from '@shared/components/popover.component'; + +interface ReferencedEntityInfo { + entity: BaseData & HasTenantId; + typeName: string; + detailsUrl: string; +} + +interface TenantReferencedEntities { + tenantName?: string; + tenantDetailsUrl?: string; + entities: ReferencedEntityInfo[]; +} + +type ReferencedEntities = {[tenantId: string]: TenantReferencedEntities}; +type ReferencedEntitiesEntry = [string, TenantReferencedEntities]; + +@Component({ + selector: 'tb-image-references', + templateUrl: './image-references.component.html', + styleUrls: ['./image-references.component.scss'] +}) +export class ImageReferencesComponent implements OnInit { + + @Input() + references: ImageReferences; + + popoverComponent: TbPopoverComponent; + + contentReady = false; + + authUser = getCurrentAuthUser(this.store); + + simpleList = true; + + referencedEntitiesList: ReferencedEntityInfo[]; + + referencedEntitiesEntries: ReferencedEntitiesEntry[]; + + constructor(protected store: Store, + private entityService: EntityService, + private cd: ChangeDetectorRef, + private translate: TranslateService) { + } + + ngOnInit(): void { + if (this.authUser.authority === Authority.SYS_ADMIN && this.hasNonSystemEntities(this.references)) { + this.simpleList = false; + this.toReferencedEntitiesEntries(this.references).subscribe( + (entries) => { + this.referencedEntitiesEntries = entries; + this.contentReady = true; + this.cd.detectChanges(); + if (this.popoverComponent) { + Promise.resolve().then(() => { + this.popoverComponent.updatePosition(); + }); + } + } + ); + } else { + this.referencedEntitiesList = this.toReferencedEntitiesList(this.references); + this.contentReady = true; + } + } + + isSystem(tenantId: string): boolean { + return tenantId === NULL_UUID; + } + + private hasNonSystemEntities(references: ImageReferences): boolean { + for (const entityTypeStr of Object.keys(references)) { + const entities = this.references[entityTypeStr]; + if (entities.some(e => e.tenantId && e.tenantId.id && e.tenantId.id !== NULL_UUID)) { + return true; + } + } + return false; + } + + private toReferencedEntitiesList(references: ImageReferences): ReferencedEntityInfo[] { + const result: ReferencedEntityInfo[] = []; + for (const entityTypeStr of Object.keys(references)) { + const entityType = entityTypeStr as EntityType; + const entityTypeName = this.translate.instant(entityTypeTranslations.get(entityType).type); + const entities = references[entityTypeStr]; + for (const entity of entities) { + const detailsUrl = getEntityDetailsPageURL(entity.id.id, entityType); + result.push({ + entity, + typeName: entityTypeName, + detailsUrl + }); + } + } + return result; + } + + private toReferencedEntitiesEntries(references: ImageReferences): Observable { + let referencedEntities: ReferencedEntities = {}; + const referencedEntitiesList = this.toReferencedEntitiesList(references); + for (const referencedEntityInfo of referencedEntitiesList) { + const tenantId = referencedEntityInfo.entity.tenantId?.id || NULL_UUID; + let tenantEntitiesInfo = referencedEntities[tenantId]; + if (!tenantEntitiesInfo) { + tenantEntitiesInfo = { + entities: [] + }; + referencedEntities[tenantId] = tenantEntitiesInfo; + } + tenantEntitiesInfo.entities.push(referencedEntityInfo); + } + referencedEntities = Object.keys(referencedEntities).sort((tenantId1, tenantId2) => { + if (tenantId1 === NULL_UUID) { + return -1; + } else if (tenantId2 === NULL_UUID) { + return 1; + } + return 0; + }).reduce( + (obj, key) => { + obj[key] = referencedEntities[key]; + return obj; + }, + {} + ); + const tenantIds = Object.keys(referencedEntities).filter(id => id !== NULL_UUID); + return this.entityService.getEntities(EntityType.TENANT, tenantIds).pipe( + map((tenants) => { + for (const tenant of tenants) { + const tenantEntitiesInfo = referencedEntities[tenant.id.id]; + tenantEntitiesInfo.tenantName = tenant.name; + tenantEntitiesInfo.tenantDetailsUrl = getEntityDetailsPageURL(tenant.id.id, EntityType.TENANT); + } + return Object.entries(referencedEntities); + }) + ); + } + +} diff --git a/ui-ngx/src/app/shared/components/image/images-datasource.ts b/ui-ngx/src/app/shared/components/image/images-datasource.ts new file mode 100644 index 0000000000..fd92cae367 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/images-datasource.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 { CollectionViewer, DataSource, SelectionModel } from '@angular/cdk/collections'; +import { ImageResourceInfo } from '@shared/models/resource.models'; +import { BehaviorSubject, Observable, of, ReplaySubject, Subject } from 'rxjs'; +import { emptyPageData, PageData } from '@shared/models/page/page-data'; +import { ImageService } from '@core/http/image.service'; +import { EntityBooleanFunction } from '@home/models/entity/entities-table-config.models'; +import { PageLink } from '@shared/models/page/page-link'; +import { catchError, map, take, tap } from 'rxjs/operators'; + +export class ImagesDatasource implements DataSource { + private entitiesSubject: Subject; + private readonly pageDataSubject: Subject>; + + public pageData$: Observable>; + + public selection = new SelectionModel(true, []); + + public dataLoading = true; + + constructor(private imageService: ImageService, + private images: ImageResourceInfo[], + private selectionEnabledFunction: EntityBooleanFunction) { + if (this.images && this.images.length) { + this.entitiesSubject = new BehaviorSubject(this.images); + } else { + this.entitiesSubject = new BehaviorSubject([]); + this.pageDataSubject = new BehaviorSubject>(emptyPageData()); + this.pageData$ = this.pageDataSubject.asObservable(); + } + } + + connect(collectionViewer: CollectionViewer): + Observable> { + return this.entitiesSubject.asObservable(); + } + + disconnect(collectionViewer: CollectionViewer): void { + this.entitiesSubject.complete(); + if (this.pageDataSubject) { + this.pageDataSubject.complete(); + } + } + + reset() { + this.entitiesSubject.next([]); + if (this.pageDataSubject) { + this.pageDataSubject.next(emptyPageData()); + } + } + + loadEntities(pageLink: PageLink, includeSystemImages = false): Observable> { + this.dataLoading = true; + const result = new ReplaySubject>(); + this.fetchEntities(pageLink, includeSystemImages).pipe( + tap(() => { + this.selection.clear(); + }), + catchError(() => of(emptyPageData())), + ).subscribe( + (pageData) => { + this.entitiesSubject.next(pageData.data); + this.pageDataSubject.next(pageData); + result.next(pageData); + this.dataLoading = false; + } + ); + return result; + } + + fetchEntities(pageLink: PageLink, includeSystemImages = false): Observable> { + return this.imageService.getImages(pageLink, includeSystemImages); + } + + isAllSelected(): Observable { + const numSelected = this.selection.selected.length; + return this.entitiesSubject.pipe( + map((entities) => numSelected === entities.length) + ); + } + + isEmpty(): Observable { + return this.entitiesSubject.pipe( + map((entities) => !entities.length) + ); + } + + total(): Observable { + return this.pageDataSubject.pipe( + map((pageData) => pageData.totalElements) + ); + } + + masterToggle() { + this.entitiesSubject.pipe( + tap((entities) => { + const numSelected = this.selection.selected.length; + if (numSelected === this.selectableEntitiesCount(entities)) { + this.selection.clear(); + } else { + entities.forEach(row => { + if (this.selectionEnabledFunction(row)) { + this.selection.select(row); + } + }); + } + }), + take(1) + ).subscribe(); + } + + private selectableEntitiesCount(entities: Array): number { + return entities.filter((entity) => this.selectionEnabledFunction(entity)).length; + } +} diff --git a/ui-ngx/src/app/shared/components/image/images-in-use-dialog.component.html b/ui-ngx/src/app/shared/components/image/images-in-use-dialog.component.html new file mode 100644 index 0000000000..6bbc62ade2 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/images-in-use-dialog.component.html @@ -0,0 +1,82 @@ + +

{{title}}

+
+
+ +
+ + + + + + + + + + + + + + + {{ image.title }} + + + + + + {{ 'image.name' | translate }} + + + {{ translate.get('image.selected-images', {count: dataSource.selection.selected.length}) | async }} + + + + {{ image.title }} + + + + + + + + + + +
+
+
+
+
+ + +
+ + +
+
diff --git a/ui-ngx/src/app/shared/components/image/images-in-use-dialog.component.scss b/ui-ngx/src/app/shared/components/image/images-in-use-dialog.component.scss new file mode 100644 index 0000000000..682f3a1d0c --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/images-in-use-dialog.component.scss @@ -0,0 +1,40 @@ +/** + * 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-images-in-use-content { + display: flex; + flex-direction: column; + gap: 24px; + &.multiple { + gap: 16px; + } + .table-container { + overflow: auto; + .mat-mdc-cell.mat-column-preview { + width: 50px; + height: 50px; + padding: 2px 12px; + display: block; + } + } + .tb-image-preview { + width: 50px; + height: 50px; + object-fit: contain; + border-radius: 4px; + } + } +} diff --git a/ui-ngx/src/app/shared/components/image/images-in-use-dialog.component.ts b/ui-ngx/src/app/shared/components/image/images-in-use-dialog.component.ts new file mode 100644 index 0000000000..20b551c872 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/images-in-use-dialog.component.ts @@ -0,0 +1,114 @@ +/// +/// 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, Inject, OnInit, Renderer2, ViewContainerRef } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { Router } from '@angular/router'; +import { ImageReferences, ImageResourceInfo, ImageResourceInfoWithReferences } from '@shared/models/resource.models'; +import { ImagesDatasource } from '@shared/components/image/images-datasource'; +import { MatButton } from '@angular/material/button'; +import { TbPopoverService } from '@shared/components/popover.service'; +import { ImageReferencesComponent } from '@shared/components/image/image-references.component'; +import { TranslateService } from '@ngx-translate/core'; + +export interface ImagesInUseDialogData { + multiple: boolean; + images: ImageResourceInfoWithReferences[]; +} + +@Component({ + selector: 'tb-images-in-use-dialog', + templateUrl: './images-in-use-dialog.component.html', + styleUrls: ['./images-in-use-dialog.component.scss'] +}) +export class ImagesInUseDialogComponent extends + DialogComponent implements OnInit { + + title: string; + message: string; + + references: ImageReferences; + + dataSource: ImagesDatasource; + + constructor(protected store: Store, + protected router: Router, + @Inject(MAT_DIALOG_DATA) public data: ImagesInUseDialogData, + public dialogRef: MatDialogRef, + public translate: TranslateService, + private renderer: Renderer2, + private viewContainerRef: ViewContainerRef, + private popoverService: TbPopoverService) { + super(store, router, dialogRef); + } + + ngOnInit(): void { + if (this.data.multiple) { + this.title = this.translate.instant('image.images-are-in-use'); + this.message = this.translate.instant('image.images-are-in-use-text'); + this.dataSource = new ImagesDatasource(null, this.data.images, entity => true); + } else { + this.title = this.translate.instant('image.image-is-in-use'); + this.message = this.translate.instant('image.image-is-in-use-text', {title: this.data.images[0].title}); + this.references = this.data.images[0].references; + } + } + + cancel() { + this.dialogRef.close(null); + } + + delete() { + if (this.data.multiple) { + this.dialogRef.close(this.dataSource.selection.selected); + } else { + this.dialogRef.close(this.data.images); + } + } + + toggleShowReferences($event: Event, image: ImageResourceInfoWithReferences, referencesButton: MatButton) { + if ($event) { + $event.stopPropagation(); + } + const trigger = referencesButton._elementRef.nativeElement; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const referencesPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, ImageReferencesComponent, 'top', true, null, + { + references: image.references + }, {}, {}, {}, + false, + visible => { + const addClasses = + visible ? 'mdc-button--unelevated mat-mdc-unelevated-button' : 'mdc-button--outlined mat-mdc-outlined-button'; + const removeClasses = + visible ? 'mdc-button--outlined mat-mdc-outlined-button' : 'mdc-button--unelevated mat-mdc-unelevated-button'; + addClasses.split(' ').forEach(clazz => { + this.renderer.addClass(trigger, clazz); + }); + removeClasses.split(' ').forEach(clazz => { + this.renderer.removeClass(trigger, clazz); + }); + }); + referencesPopover.tbComponentRef.instance.popoverComponent = referencesPopover; + } + } +} diff --git a/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.html b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.html new file mode 100644 index 0000000000..4a60b29ba9 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.html @@ -0,0 +1,111 @@ + +
+ +
+
+
+ {{ 'image-input.images' | translate }} [{{ $index }}] +
+
+ drag_indicator +
+
+ +
+
+ +
+
+
+
{{ 'image-input.no-images' | translate }}
+
+
+
+ +
+
+
+ + +
+
+
+ + +
+
+
+ + +
{{ 'image.no-image-selected' | translate }}
+
diff --git a/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.scss b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.scss new file mode 100644 index 0000000000..f6e05ca2d9 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.scss @@ -0,0 +1,225 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@import "../../../../scss/constants"; + +$imagesContainerHeight: 106px !default; +$selectContainerHeight: 96px !default; +$previewSize: 64px !default; + +.image-card { + margin-bottom: 8px; + &.image-dnd-placeholder { + height: 82px; + width: 146px; + border: 2px dashed rgba(0, 0, 0, 0.2); + background: rgba(0, 0, 0, 0.1); + border-radius: 4px; + } + &.image-dragging { + display: none !important; + } + .image-title { + font-size: 11px; + font-weight: 400; + line-height: 14px; + color: rgba(0, 0, 0, 0.6); + padding-bottom: 4px; + } + + .image-content-container { + background: #FFFFFF; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 4px; + height: $previewSize; + } + + .tb-image-preview { + width: auto; + max-width: $previewSize - 2px; + height: auto; + max-height: $previewSize - 2px; + } + + .tb-image-preview-container { + position: relative; + width: $previewSize; + height: $previewSize; + margin-top: -1px; + margin-bottom: -1px; + border: 1px solid rgba(0, 0, 0, 0.54); + + .tb-image-preview { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + + .tb-image-action-container { + position: relative; + height: $previewSize - 2px; + display: flex; + align-items: center; + justify-content: center; + min-width: 40px; + } +} + +:host { + .tb-container { + margin-top: 0; + padding: 0 0 16px; + display: flex; + flex-direction: column; + gap: 8px; + label.tb-title { + display: block; + padding-bottom: 0; + } + } + + .images-container { + padding: 12px 12px 4px; + background: rgba(0, 0, 0, 0.03); + border-radius: 4px; + flex-wrap: wrap; + margin-bottom: 8px; + &.no-images { + height: $imagesContainerHeight; + padding-bottom: 12px; + align-items: center; + justify-content: center; + } + } + + .no-images-prompt { + font-size: 18px; + color: rgba(0, 0, 0, 0.54); + } + + .tb-image-select-container { + width: 100%; + height: $selectContainerHeight; + border-radius: 4px; + border: 1px solid rgba(0, 0, 0, 0.12); + display: flex; + align-items: center; + + .tb-image-container { + width: $selectContainerHeight - 1px; + height: $selectContainerHeight - 2px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 4px; + border-right: 1px solid rgba(0, 0, 0, 0.12); + background: #fff; + overflow: hidden; + + .tb-image-preview { + width: auto; + max-width: $selectContainerHeight - 2px; + height: auto; + max-height: $selectContainerHeight - 2px; + } + + .tb-no-image { + text-align: center; + color: rgba(0, 0, 0, 0.38); + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: 0.4px; + } + } + + .tb-image-info-container { + display: flex; + flex: 1; + align-self: stretch; + padding: 0 8px; + justify-content: flex-end; + align-items: center; + gap: 4px; + + .tb-external-image-container { + display: flex; + flex: 1; + align-self: stretch; + padding: 16px 8px 0 16px; + flex-direction: column; + align-items: flex-start; + gap: 4px; + .tb-external-link-label { + color: rgba(0, 0, 0, 0.54); + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + letter-spacing: 0.4px; + } + .tb-external-link-input-container { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 4px; + align-self: stretch; + .tb-inline-field { + width: 100%; + } + .tb-image-decline-btn { + color: rgba(0,0,0,0.38); + } + } + } + + } + + .tb-image-select-buttons-container { + display: flex; + flex: 1; + align-self: stretch; + padding: 8px; + gap: 8px; + justify-content: center; + align-items: flex-start; + .tb-image-select-button { + width: 100%; + height: 100%; + align-self: stretch; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 4px; + padding: 8px; + line-height: normal; + font-size: 12px; + @media #{$mat-gt-xs} { + padding: 16px; + } + .mat-icon { + width: 24px; + height: 24px; + font-size: 24px; + margin: 0; + } + } + } + } +} diff --git a/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.ts b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.ts new file mode 100644 index 0000000000..260a7667f8 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.ts @@ -0,0 +1,181 @@ +/// +/// 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 { ChangeDetectorRef, Component, forwardRef, Input, OnDestroy, Renderer2, ViewContainerRef } from '@angular/core'; +import { PageComponent } from '@shared/components/page.component'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, } from '@angular/forms'; +import { moveItemInArray } from '@angular/cdk/drag-drop'; +import { DndDropEvent } from 'ngx-drag-drop'; +import { isUndefined } from '@core/utils'; +import { coerceBoolean } from '@shared/decorators/coercion'; +import { ImageLinkType } from '@shared/components/image/gallery-image-input.component'; +import { TbPopoverService } from '@shared/components/popover.service'; +import { MatButton } from '@angular/material/button'; +import { ImageGalleryComponent } from '@shared/components/image/image-gallery.component'; +import { prependTbImagePrefixToUrls, removeTbImagePrefixFromUrls } from '@shared/models/resource.models'; + +@Component({ + selector: 'tb-multiple-gallery-image-input', + templateUrl: './multiple-gallery-image-input.component.html', + styleUrls: ['./multiple-gallery-image-input.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MultipleGalleryImageInputComponent), + multi: true + } + ] +}) +export class MultipleGalleryImageInputComponent extends PageComponent implements OnDestroy, ControlValueAccessor { + + @Input() + label: string; + + @Input() + @coerceBoolean() + required = false; + + @Input() + disabled: boolean; + + imageUrls: string[]; + + ImageLinkType = ImageLinkType; + + linkType: ImageLinkType = ImageLinkType.none; + + externalLinkControl = new FormControl(null); + + dragIndex: number; + + private propagateChange = null; + + constructor(protected store: Store, + private cd: ChangeDetectorRef, + private renderer: Renderer2, + private viewContainerRef: ViewContainerRef, + private popoverService: TbPopoverService) { + super(store); + } + + ngOnDestroy() { + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + } + + writeValue(value: string[]): void { + this.reset(); + this.imageUrls = removeTbImagePrefixFromUrls(value); + } + + private updateModel() { + this.cd.markForCheck(); + this.propagateChange(prependTbImagePrefixToUrls(this.imageUrls)); + } + + private reset() { + this.linkType = ImageLinkType.none; + this.externalLinkControl.setValue(null, {emitEvent: false}); + } + + clearImage(index: number) { + this.imageUrls.splice(index, 1); + this.updateModel(); + } + + setLink($event: Event) { + if ($event) { + $event.stopPropagation(); + } + this.linkType = ImageLinkType.external; + } + + declineLink($event: Event) { + if ($event) { + $event.stopPropagation(); + } + this.reset(); + } + + applyLink($event: Event) { + if ($event) { + $event.stopPropagation(); + } + this.imageUrls.push(this.externalLinkControl.value); + this.reset(); + this.updateModel(); + } + + toggleGallery($event: Event, browseGalleryButton: MatButton) { + if ($event) { + $event.stopPropagation(); + } + const trigger = browseGalleryButton._elementRef.nativeElement; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const ctx: any = { + pageMode: false, + popoverMode: true, + mode: 'grid', + selectionMode: true + }; + const imageGalleryPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, ImageGalleryComponent, 'top', true, null, + ctx, + {}, + {}, {}, true); + imageGalleryPopover.tbComponentRef.instance.imageSelected.subscribe((image) => { + imageGalleryPopover.hide(); + this.imageUrls.push(image.link); + this.updateModel(); + }); + } + } + + imageDragStart(index: number) { + setTimeout(() => { + this.dragIndex = index; + this.cd.markForCheck(); + }); + } + + imageDragEnd() { + this.dragIndex = -1; + this.cd.markForCheck(); + } + + imageDrop(event: DndDropEvent) { + let index = event.index; + if (isUndefined(index)) { + index = this.imageUrls.length; + } + moveItemInArray(this.imageUrls, this.dragIndex, index); + this.dragIndex = -1; + this.updateModel(); + } +} diff --git a/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.html b/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.html new file mode 100644 index 0000000000..5255234ba8 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.html @@ -0,0 +1,65 @@ + +
+ +

{{ ( uploadImage ? 'image.upload-image' : 'image.update-image' ) | translate }}

+ + +
+ + +
+
+
+ + + + image.name + + + {{ 'image.name-required' | translate }} + + +
+
+
+ + +
+
diff --git a/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts b/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts new file mode 100644 index 0000000000..ae022615a1 --- /dev/null +++ b/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts @@ -0,0 +1,115 @@ +/// +/// 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, Inject, OnInit, SkipSelf } from '@angular/core'; +import { ErrorStateMatcher } from '@angular/material/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { + FormGroupDirective, + NgForm, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, + Validators +} from '@angular/forms'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { Router } from '@angular/router'; +import { ImageService } from '@core/http/image.service'; +import { ImageResourceInfo, imageResourceType } from '@shared/models/resource.models'; +import { getCurrentAuthState } from '@core/auth/auth.selectors'; + +export interface UploadImageDialogData { + image?: ImageResourceInfo; +} + +@Component({ + selector: 'tb-upload-image-dialog', + templateUrl: './upload-image-dialog.component.html', + providers: [{provide: ErrorStateMatcher, useExisting: UploadImageDialogComponent}], + styleUrls: [] +}) +export class UploadImageDialogComponent extends + DialogComponent implements OnInit, ErrorStateMatcher { + + uploadImageFormGroup: UntypedFormGroup; + + uploadImage = true; + + submitted = false; + + maxResourceSize = getCurrentAuthState(this.store).maxResourceSize; + + constructor(protected store: Store, + protected router: Router, + private imageService: ImageService, + @Inject(MAT_DIALOG_DATA) public data: UploadImageDialogData, + @SkipSelf() private errorStateMatcher: ErrorStateMatcher, + public dialogRef: MatDialogRef, + public fb: UntypedFormBuilder) { + super(store, router, dialogRef); + } + + ngOnInit(): void { + this.uploadImage = !this.data?.image; + this.uploadImageFormGroup = this.fb.group({ + file: [this.data?.image?.link, [Validators.required]] + }); + if (this.uploadImage) { + this.uploadImageFormGroup.addControl('title', this.fb.control(null, [Validators.required])); + } + } + + imageFileNameChanged(fileName: string) { + if (this.uploadImage) { + const titleControl = this.uploadImageFormGroup.get('title'); + if (!titleControl.value || !titleControl.touched) { + titleControl.setValue(fileName); + } + } + } + + isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean { + const originalErrorState = this.errorStateMatcher.isErrorState(control, form); + const customErrorState = !!(control && control.invalid && this.submitted); + return originalErrorState || customErrorState; + } + + cancel(): void { + this.dialogRef.close(null); + } + + upload(): void { + this.submitted = true; + const file: File = this.uploadImageFormGroup.get('file').value; + if (this.uploadImage) { + const title: string = this.uploadImageFormGroup.get('title').value; + this.imageService.uploadImage(file, title).subscribe( + (res) => { + this.dialogRef.close(res); + } + ); + } else { + const image = this.data.image; + this.imageService.updateImage(imageResourceType(image), image.resourceKey, file).subscribe( + (res) => { + this.dialogRef.close(res); + } + ); + } + } +} diff --git a/ui-ngx/src/app/shared/components/js-func.component.html b/ui-ngx/src/app/shared/components/js-func.component.html index 41e834668e..e072759213 100644 --- a/ui-ngx/src/app/shared/components/js-func.component.html +++ b/ui-ngx/src/app/shared/components/js-func.component.html @@ -1,6 +1,6 @@
+ (selectedTabChange)="onTimewindowTypeChange()" [(selectedIndex)]="timewindow.selectedTab">
@@ -215,6 +216,7 @@ [(hideFlag)]="timewindow.hideAggInterval" (hideFlagChange)="onHideAggIntervalChanged()" [min]="minHistoryAggInterval()" [max]="maxHistoryAggInterval()" + useCalendarIntervals predefinedName="aggregation.group-interval"> diff --git a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.scss b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.scss index 70f43f410c..25d11f510f 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.scss +++ b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts index f4a2e8b916..0c0dd4294c 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts +++ b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import { AggregationType, DAY, HistoryWindowType, + QuickTimeInterval, quickTimeIntervalPeriod, RealtimeWindowType, Timewindow, @@ -186,6 +187,38 @@ export class TimewindowPanelComponent extends PageComponent implements OnInit { this.timewindowForm.get('aggregation.limit').updateValueAndValidity({emitEvent: false}); } + onTimewindowTypeChange() { + this.timewindowForm.markAsDirty(); + const timewindowFormValue = this.timewindowForm.getRawValue(); + if (this.timewindow.selectedTab === TimewindowType.REALTIME) { + if (timewindowFormValue.history.historyType !== HistoryWindowType.FIXED) { + this.timewindowForm.get('realtime').patchValue({ + realtimeType: Object.keys(RealtimeWindowType).includes(HistoryWindowType[timewindowFormValue.history.historyType]) ? + RealtimeWindowType[HistoryWindowType[timewindowFormValue.history.historyType]] : + timewindowFormValue.realtime.realtimeType, + timewindowMs: timewindowFormValue.history.timewindowMs, + quickInterval: timewindowFormValue.history.quickInterval.startsWith('CURRENT') ? + timewindowFormValue.history.quickInterval : timewindowFormValue.realtime.quickInterval + }); + setTimeout(() => this.timewindowForm.get('realtime.interval').patchValue(timewindowFormValue.history.interval)); + } + } else { + this.timewindowForm.get('history').patchValue({ + historyType: HistoryWindowType[RealtimeWindowType[timewindowFormValue.realtime.realtimeType]], + timewindowMs: timewindowFormValue.realtime.timewindowMs, + quickInterval: timewindowFormValue.realtime.quickInterval + }); + setTimeout(() => this.timewindowForm.get('history.interval').patchValue(timewindowFormValue.realtime.interval)); + } + this.timewindowForm.patchValue({ + aggregation: { + type: timewindowFormValue.aggregation.type, + limit: timewindowFormValue.aggregation.limit + }, + timezone: timewindowFormValue.timezone + }); + } + update() { const timewindowFormValue = this.timewindowForm.getRawValue(); this.timewindow.realtime = { diff --git a/ui-ngx/src/app/shared/components/time/timewindow.component.html b/ui-ngx/src/app/shared/components/time/timewindow.component.html index a53ea656fc..622f5654d9 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow.component.html +++ b/ui-ngx/src/app/shared/components/time/timewindow.component.html @@ -1,6 +1,6 @@ }-~*nx2?$h0TM zWPW9-SJy4nHOtK0m~EInRlSLk<7{48W^DLN`qHy8Z+ zh2ws*41(5uUqC0twVRono12=Zw22!T4S^{P1RK@Ju;$RoIFM;JP(S${VDsc9G1_D3oKlHT2=p-RC1Ioh?3k(ZY((4P>v}k|No=wK|l#4XGR(4LqyBWT>a~p zFb9WKO$ZzE+Z>=7aoX>AA7-Tn=n(q*`kps1)!$7&3!&`<#q0;gHOE8>6P zx85TdJ^`6SpM%dci&ub-yFTsEkt3}rPSF4Xf_aUAhS4bsOkiTzfLCTFpmO^!&~pfq zEt~q=X!nhEl$^#P+y5(2Ut1+`_3BkZ=)_|N>3AE;*CT8<&fhG3j7PZ3qm)aHBkMbE zCwLm^=z_5%FI~E%pB3hXER7QM1Ub2$fq{~``d9NLyQ{jo-N@|_+4G$`b>9mJIg#=} zblS1!a3`*JqQk~r4mJzX%S=i^_*7S=q{vA;KiO@-ZFMxC33T%z>#0ZarbWJR(sIvyf#%d@Jk#k8% zNYvESK%$051TO%(hL2_=UXO=|2T2%6M}QROf23jKU&-btH9@+qW^+Bdk1%0_juU z<>p3Wz67l{fWG*6dWJpQwp@JH(`>g*WLszrdP@)wuDG}qB_=W+fD*Z)vJ#SgUAlw2 zw?9P1ua*$`>eVao6F5WN-ds-(4OOG3{xm#?dl6nKAt7<#zyW$v$|xN;!k}j?Kg4CB z_ajg`9$Vg~zy)imJWsvLe}8tnIT#&%9VxZHfh%I%j-pZ=U?*K@&5}!TLIT5!7G`#h z*!$q^AQTuHzL8~sDiYF)bVp;1@lzggT{%YdEY1LZ^!58tLV7WwO~T&6>VUAY&~42b z1!T^iez{S?4bxIKl=ibOw~jk zr=!sg;OE=Td7C`ZkpO-MoASWZY8DMKuzm4<(C9h|bzv4z9Q_#)Pgg#io%2Azf3`3J z+ya5%Aj4tC#tB;o)7Q~veRK0wI1pgu$fB0PbQl;Hw#PN1+bSiBX)Fz!F-$7?VVD8T z8{rGx2?(CE1rvZ=>%M+{E**bMBsD$V!o>_n^M%`YlYb|1)&B< zP=@pcf};Par;)anOR>93+c)FrA`%s@{bhI#f>LE>S4=WwW%nwb5*01!+hb3}Zkejs zy_=;f#!Y(b1j=ydjyl#3GAHx`GLnx`*`w}VgD6(5)`&h9k?v)9I2;8)tXcv+Y1TFc zb*-6+NdYu4hgeh{@7?1wZ=1I5n3|Yy#RL!yW2l;5bCM#mHB<}T`POk5v&>LOGso59 zW8|Q0Lbi*-5K&)076|&qQ>S7v78iA%zl}YJWd5VEQ9p$_`wgbzc&e}XZM~8ZAMuFL zaTmKRy?gP3qNxl8JtjblodlnIQ6G%tiXhC)z({6J1|?>T8y)J0AalY*WlQvh|8r^r zb*SJD`-16|n!<~>UOWdjJtR1;f7CRBdTj~-xTlyBtZT8d!osg>22D*&P=cC% zKZWEHKVAaF>Z!my*IB0`#lzLZa$h||X z2fw;y&|}l1Wy}A+KHmQ!%CJr;k`RgFpd^JFPK!Nrwi+L?XQfgryg9%UEB4uz*h(>OJ0tl@JM;eg;m$h;Evb2 ze_b!5B`iE#rJEteJYz4^s5S*(3Dre(bX*)pQcEswe=K6FW1lK8H8(b<{D(L(8qt!H zG&OUb*_R8srm|l}#R9)GZO}90h)Y}ko%xOlHV)?+j^J;l^|DfI^es(bAB3;|zdM}& z$DR4_^sDOoB*Wn-puSO7UJmCNcEH@B(($@ly}>MMuU^02e?manI%{BH;6KV5Up|6{ z-~9-FLKUs8dB7Uc3?o^q=ilj_0)wJlWpH@&&)}enRvO?YCQ5*vE;CQOl29)~P7aVt zSBcQMxa`~1JtCzNszz~23W_E)#OQv|O#k}!ZF*12Z=&YSwZNKUVK=&YlTg*qITmr4 z5TXGWzG7d+V>^H}AuSeYousC&VFl;A3Ii~t8ceH>larqckO~_FeFWPaQ(PNs>tpbV zLDdyDh>@I~wKb~7Z3iIlfHo7tK3fnpFgHLD?aDEsP#Q<|fXoff$941N|F@b)Oky!X zNlQ9%*%YDwfy&z7hL#QbI4dnB-H5XRv3QHX+y05_r_jdXv1d0Yj|iR`Dkgs#s+SRK!*~NfDamru>Djjsz zANEHmaxexie*QlMjm1UtYjUzS*Tr8Q3}M&C=*k%%5sT91!Yh0pcCCB`Ny$X6eMHXS zn1hTG^(@eQLNNQ&dv}nh4yvJH0(>655qN|E_-?>gJ-icdy`^P9 z@Fh$Co`t#zJe5Z5V10fgeQ>=BA*wAub(boRB_`0Rs!_)IGN-H!PsJqX^M!ByS zh;Id`iQx<8M7enMFsFeZ9j-PKyK;1QDLwHZoMsI{y8*3@FbnbYtV9@=@H;+=H^KCK z`S0;l#8r}Ye}`Ov2P+Kw6+9P!r1Y^s7(jviR8vE+W3axU>=trae2c0M1`zOp0qQu1 zb`~+d;KK)y;J#K=B-9FYTKI8EPbqtSBLB3JMYz2fToeasc-Vw1$9S!XYaSXqT(DJFfB*{Q0AZy(7FQqqY%Iv2VA(1W@7RO(U@^1Qf z{+~G#((!W51wxKJW)?-N6O6;uZ$=d*|`qImn?a8k-rz>b|eyO4FWRj&epM+H4P zh=6?!a=%#nHQ$S;z~Iuq+nhFyc#Pog7GV*5mVv>jDv%z`t7XF~Bx~*bJ278Mu?kU6 zt4Njw1@yU7^ho|;KUZfkLgTONo;3P|X&)qZ2fYW7M8O&h#~MK(0s+_T!ayT@y^&QzJR}9 zdtnf855a=Dz0(20P_6tsmq0O8*Ev&Z>RqAiBCb;O0iOe2XzHx%%c{iZEpk$t8ODB) zCQ(fyqs=n>^MGZ7A>E4CxjgK?t5yGXQ{uWJ-`=sB{)JOJ&TV+zZWZ-+f0OjaP;m&z z7ZNY_t~Tgjp!(sH;Ky6UKrpRY%F4ie3R}^&e<4Wq(w-6tz)N*?bv5^R(NcoI_aYd5 z9n4FF-B$Ahso&@3PBzBN{QH5z0s?M=HPL&=D+x&wJ2x$`uI0keQS@*?p@O92=_Atv z4Bm?yFpI=8>p*dC3m$_=4Zh1;7z&&_Bc`%fHe}b zI3knw}LfmjxQ-2}lJ76jh6@o-_e(A(P!gG&?* zz+zBp;0XhvGXEC6l?c7#zX~y4{Ql*OA)FWy%Gtla0hj`h1Vz@vg@uJgA6I8oWB3j& zIf5U0LTI!)s;a!bz)zYO9bJOF&*(BcJG(etfE4;j^mp6{TPKB`9UUDx>0iHkg~h-N z`k<@p+QA*5tDiV{@VYuto0dZVN1=$Hl9KY0WtjW($AYl60}_Nu>j;uAiYK8e5sY42+yvCIs1~`xpK7QVc|e>WPyHOcY+!&G zjc(ia2cUz-=DCu^PYU;?CS@vK?&dw-qy$C&|kw*V;F}GAz|m3DA7Wopn}x^K@Qjv1zMAU;=ty-k!xOc zeh9@YE+12CtR$5CNc@Gp7mL2c!jw#4iW;VM(8=VP(beI{*-a>rr@jEEjv5%#(tgyk~6e9u(q3?Zo1BbWGDKX#CfDg#IU-Ziuu1 zCNYXru=r;%#So{YqIwDW0-8gR*T*ryg;M6Mxt<;;hQIj!R7ak_2B^*LP-g=Zbh8j(5Wx|7qkIny3arLP8}zJLyJ#JK27L~P zwBN@74yY|kHI%bhiXR8>DwpF1y$TD?!osdl8L*+oMoY7U|A`myZ%fp+ zkPCoIj*TsEne@1}R#sT}BW8Vsr77kSwPNrX>+jFD8@-O%5_VHao~0ApD;~2D2nHVS zrVzkj%Ec-CW8yR_KDdgYaFY$=JbmWOBMo(Hc{f#2@F?oRk_3#3$`0MfzHH7jXACd{ zLnD0HTO8Ywo+!!S}*Po6lT{rNXYD1gY3hu4AJ zg7tx=6+Q^UAYvS%zcmsCa^sE@Ith)H{0Fc|GSTUxGzX(1smJkA^|W=~GshDpg9CLz zX+qSt{c_wpfBxX98rs8{DQI-lC`VtbA%7sPg(UOfcg$+*yYHQ|Qm?#Lr+s96m!EtU zyN>**vG(tXJgdI^KLd3&e|3wOp9|g9)1+NKGqO6CAH>E@!t0Q$k zmhKqCwU9A?k77T$bpvyU6Z_uple~QBkD1AIZo|>r(dqogH74c55*4-2Dx0$BRQ;w@ zYA)WZNT9f$%sRVP`KMCM9krB=OT(DIE=|$msG71ziEd@x>R5C2?vFy|V<|4yd2a4O zXRFcl0%{M^i9|RC@(zVCSFg!Mvnvw!tM6BcRQ6Wb{egMc8?oHCtRlaG*$t2lB6W_c+{UH~| z`2fbmi_LQa>DzHY*nOQaIRY&hd!u$l*&59!_@1endF-BL)^>J=@2=U| z<$!7c7Bqg-zhR@aP=V>GxA!PW98aD|fI02+wr(J`4;HL^;-G+^?*x z)3L})l@%3SG?OJd#BKqu0oe=!n53?530jugQlERX*~{(VgO~M!p~q{|C_YmG4NG!* zdR^}w)Hk}tE?33D4>847LY{=)7y&L}?onjHRgl8UQ zQ38t1<7D8|GD6~+;+MCPaQbyb-Lap&rN556cI)7D8~ps&dsLiqVIcjj!g&Yv%8_kv3y%`DEq~7-g;O-wxfeoqEWrykN4iU z9TSJ#!Zcg#MO z^!gm!(hZb)+3h|Wrywnaq7Z@G=kyCWn!y+S;CD=3Fp&Y1%of9P1Rp17=Y^5)kG#-j zAhy-P3LeEkh?^iRPmGM-K#7N92(qe!2tbOX$&68~&%xL~bf~;G4NQGZxCm4Z7g0TS z8LH*Sj~}Bl^A)FkaPd>o<1qwnZUe1GBOhOo1=ay zVR*%;hVDWKtD84tN=n@EBO(Q)2QUx=Pyt{d)C)QTKy<`}acCnpkkX^w+D zd-uT0kgGtQxrT!>et4Jv6A=-oIV&(IrJ8KE`%n=qpN1d2jTXNR4=v1VH@KH>_q|eM z?^)y{f5`ibINjRcn`yD7477*HBE0g=bCqw*p5kk6p^Y6Eiiup<5D`c)p7Xw4|D!3* zeNtAcp~`I3Qg9;i$4Y&-rt63)%l;0JxDTocGz70wKVgginquQq4EW#y9isrkVtG-5 z6kQ-{enOxDx}T`1F6&`#ig{vLm5{h>4VTSD#gAGT4?`5nK@7LW5eyj1cie-p4-zE6 zFfj^WI~T^MrU2Y>gWAE8YQu3Eh8mEfk$(r3gO!a9J3!2J`6DKLDaBEf(M0* z{xIqGhm9Tt?G3DNY~Yrb7P#vhnVYj7z^@1CpbAX{sg*gHxl50^{XW`8)Y+I8kKu}m zehAeTps7(m=FDs8#-1Qx0wI!?u125%L2e9l_ZepKdEntP@r`|dg(M{thW{-0mRvlZUk}dFYt*{fn%uSLwhJgvL)#co0^$X1VHN!Gg|$a zmoI;Y%00rYlqJqiutq4X1_m-{$GYPr_m}U|#WWp7J|^q6{WEA66lZ=wLk4??aFgq( z&*Sf<>7#Hg-{3O!MB%{jJzX%Y{=gO)8dxMipaUOg}J}W zH>gP1pWJKLJotTe!WbuR<>%Y?RpyMZ&(##O#6N60cNX-b`S(17^Ce;x%L3x(jnzr` zIyOFTc}aDKG(09kPR(QHgIZB zvJ=(y_4N%6qTsh;N5dWsn;N44Sg?b%kKz&HA5E9Z-$y8X%WJ<`g1&*#taJ$tWZfY6 zpJrtAtn9~mAl!U+(3qmb*4doeVj-OE+6ijW*IFq#d3j?I5w0j_j9yVNY6ALOcFn5& z2NS7=VeUAkTJfHsAW8^RF>f8>)x(Vc?ORURXuWu$v|Ntxz{y7wA0H1SAuKr?6d+XY zAamOktU@0rdleM{%&~Eq6h!A(eSDBTdn+nigPj>5u)_ud2Q6gBG25fzK|y&K1&E0W zoIQ;Wo%9dI))Be}qfHqZmaHELdjP5nM`&=(x*645P*T<4V@@AxmjlSu?<(aVP;~6#=l3WLgEJgyt40 z(#vaC`TZ{#J0U+J!$ay?U#o5f4@oFluV258UIM^BHIJ#Xv*adw7cyBU>%H!?>gi93 zGIUOlJ@XtwFknuYzvHkrSi~ww1NFydvwawv=L~u&iYjnZqQGN5d|1^;loJ}&?vE@^ zWnNJA;a$KiS5Q`-M@fL*9eas+>;mLm@7})MMMf4PMTd$7H!sysbH@gRIk^EDL%Nk# zk$YW_FVH#vEhxmfTq+h6y8b&~nx;HB?V!YEn<3(O%x;n_qWpJfwxrdFzULBqKP211Ej+c5pg19eV2~WRxB}~;YdpvfWd$K z$OYPhVIO2T_V)I*HD+MW;g@pY90`oU=$f7N!sZ_Y>ZaCK2UL@d_dk4CM&d_;mlH3q z8Oue@30WncFfyNtq@*#(52z<@*(;Z$`nrQ7B+#Q^;agc* zVU9=(BOHirbug6z%10yQcq&-hSNHN&T&J`&vs;uc-Wu7W8*5$OGD9Dj0!AYIcY5x_ zvKxp)mruRO}4@l6#PIi!Hix*AwYc*FA25|GGs7%hO# zi(1&H6hj7J=LbkVy1KfE8z2S@3EL0HvOt>p-l8MK3lfwMIAOphJjbP#6*RNpPkllW zfl4>LO~>U=Umh9$e$V!Y#9+;7d~{Sp=aHz(A|SIJOlgwANU%8{tzCY4x^2O*%{BpcDt`O+BRicj7=IAL7?yfuS<2wW&KC?UjkK05Q`+{h_ zewM1-??U~CrS80_7Uh029Py^~y0ySV#@uG;o$wJ~x#< zurubf_(@4lt^iwYX>1naxs9uN01Ss=gBy@Jo|crxYIDX<{*Mcetu*`Srkhf$O0GGT zmMX>g@1dt>v`MyBc3!z>V&c}-O0t@|vujw}Z2jSL1t+-X5mU0@H|fc|X=c7JEw8*+ zN+=-Q8@JH+Y+6Rc4CVJf6q|#S|9%n>c3mPIRmG7F+g|v~tSxAI>(;FW)BbVC z%}(+DR0T2jh52t&I+!F;fmc8l!clMxRT0hxZXCv1#9`Y8vEcM2{Ex!APuN!!UF@ZyExg|%_HZS zzP;I90k{PE7BkbaZtS;8Vlvs3et+XUh6M;n&OnP$=38MXfcfQ1%X;HoyLa>3jgZe> z5EQ%zEXJQkbp0i1xGrDX0LKxx8UZ4SE_AbP=7PUZvjbaXh^pvTuewaCdX&V(oXCvZfMFC zxUplJ?W_`JJA;UdI40)~ig|<^mkqaql7E(kF>fPA6NnEVi;9X9P9`hEKjBJp&H#s* zveWA*K`J|3+)E!WR7${Vzk`jGy|M8rBk((p)7YFBxC(C^fbTFyz7q)0(63^zQ;OyR zDltH3k4~2(H5V5Mo*w>G2dzG|%>}+pfX-tZBJv%-Zy$nJ;yZw4%*jlAd}{LYQ`xEk zQn#X1BFptbK7b(TGn^n$5CxSe6TErd)1csx6#9RUHo0|RjW zMxlf%8FYj@!}TYGg@uPIec+7&s19KrpvNCf!B<;e-cYDJ90GSL@5maPA*nKMd z&la~SvWMc4cK`UH3W5s$KZ38}^XE&Nnkx`bgH4`qKk-t53F0EgSlDVqfDAO^OC>QG z{?X9jPmn(_7Fo zj!{#O4GpOpZPdb2m+l~L?G%7ca8j{jh*=-<8$(e}7(97N#M|`4-R$qIg49*Z~_Dj8O0y@vMnn2c%}yOPIiLsfAVJ_2C6p7N+H^$WBJ$?&Vzn6F{3P$YSBbkfA!zbc*V3I3@O;{v&o)n z-!jFee@#y1!MyfL!cZ0K1EptuO^q#%!Z@^Y&WuaRAuXZeu!m* z*E*Zd0qROT0z7gYS$M4;Mj0UdfJadZuF6p3Ivx!S z)WD_KNp?IRDT{FLz^_!nv>5;Z_9E(lPdPEQ>6{qDYA7gh-u`x~JP`N_M2cqRK9DG! z#Jde_Qk=2a8DsJEam%^Br#!|f6r9KGfRm%mu4`yOzjP1P9S#=*ISRHqDt+7T3va=!LKYt>7|^@g!Dt)M_^e zqBgDy(IJ#glOb3dVfV&rJ1SH_CQXn~o;r0=MJ3n^Ey&KjM>$d0kuFQp9jrrUL$1Vb zgVhAQRxnh8f`nZMO0B=oPhW=P$Dz48aNZ%Pg&{Z9`P+Bki!Y!1%nQe#A$XQxIzdex zfn|#giD;<>Y~uX+oT3)Y!TzUdfnWGNYp}eq&xo^Yu;dWJZc$}pae$T1s+lWGcMy^N zkrx6u#o@!e;J70g0n$=U*jAI~=>?ESW}KCx9~GkrVglDjA`HrdUcAT#)JY(dh~@y; zYi*L1t0DCXeXaIwDLw*QCGnkK)hw0jhXEAU{|+i@Fh5h`H|FanBwT07tY8}fS^U6& zxHx))FBd9@BXiLn1L+{9cU*>Fu}9Dlnzf{~Ahq=L^nhA}s+>sTc6lz7CYm31K0!Re zj1qgso0z~9m5xM!tv+|7AR)4C=q~xhw}y%97>o5w+I+|->m1wQ;z7wA;o}v z1k^R`M<6YQg@W1D=%)bKu{5z^0bx=$Gd~X^DWWb;4`e>q`mUA%?jkU>FhlzTkhhkk z`XI7C=A1xMyl!I@g>Z?m0MJo(5T6q3z#OC+&oUDX_>q{fKda4R^b?T~;PCH_SZ#_= zflUVB9kfaGrtl&_3Me%JMfb?+P1m<(-j^S_u-u$0Gh|M@? z@TOk~DZKiY78jFJQV@z^9;TXLfe@;rql4B4mxHzh9hcC_1~dxos^O`aEkHbFXlRJr zXNFp`_Ubf%{F&hZl`!Xu$Xbb~H-MIU&aF$&| zEZmq+W%(7{M0|aHk*v^(<>urVK8ePzBgWOAw+G2b=7Q6JJNO!(7+mmz0{$1ws8kja zM^Jg75Yxs`+wQ%J<4+(noHVJ#eeLWViFlQ}MfYO(&SgWcaAjstGw{a`RxrT*c4Q0s zHiQ6s#;l(Jl;K_!wiJOcc9Wva*iS~L1A`~nq9YGOm4RoA;QW7sp`n{bZVum{4;PEt zVMd%qbktvk$(BVNXSs0!K14`EI<5q0neg5~SYomDKB*HMYW3{MDcuDm7aFXNpB+^7I&9;j@xzL_h0YFuQLl5hk7 zwi%Wm&Nc)Y!CML(OIRvl#r~^Q3oh8o2Fn>J_%X8+hoVA8SDdARamADW1{4-yl~J#Z zqmPm)yUb>|bP#{B@7y0wNu%)8LeTA&R*_z?)|OXR@(8au;^X60(AZ-&;kK)xfmTuB zIeoepg$%fir^rFCCWpB>(+PPNOT*0t;UZE}`&rB*HkS6Jf9r?4W;hM1WPN!Ip$Ewt z9}(dU9_Y-9`L*?#vhE=;5Ho{;7=4hFy;6LG20&lf(jlzDSMHj%&3m{?p~ymf;h0)Y zsWmCQ_t!FEBmVl?xo~MPn{XHle2$ZAI~SxQbHSglZ9#&86t*kovM0ib(Yu8_A&afd z^5L0AV7n_ zOXN%@N|dvxx+=T7H@*g(K@7tx#L*YECRfF=gYmgB*o*2UJ%D2^si>*3c3qHLv3XJO z;_z7r+A#!WI$7lPwW|xf(i)s2vMAX`3QMld;UMdaD&&>029GH7MpV9lq;bk87tWy| z{f&AIdFlil8o}qq9m+FrFKrHwisA^C4(E%3c_41tY{ohVvTFXjv#jETkh)r;tK)GI{aB!FtXeQi4ZS0H+rGt$TZ@#$O!xp z*`c+AwH$C$6du*GM|__>yTyzX&6d(6LNw%^(hu$0erUWNur^|EjSG2RZZ2GnXk$^R zz}!Lr=bhTUOg8kSRQnHA@n#5ct>>@NGVpo!49yZn_5ccF6aY95hQ;cLh?Dy7kr5nf z_Ey}1@cQ^&i!F+yU20N`icWCM<*;Qw0e1yu2cE1T>d(QFL6bcSPSth~st~RD`2M0) zKy`qcAp7mx#Wa|RAzz@V0reKN92l+`T9ymhk00gMy@aYBEz966S}M@BFuk946oSQ< zkyltjOwQZ4)1Xm;A5eP?-jfKADi1D_Q&XpgQ78?mQlhnRUKlSxT0{e6q^h@Rn|W1E zP8hE|XZ;OwJ0YQ>zEl}dR_lyliSU&G+g1=+Py<|zZv^QQW;YQL5$-mX7$icEiAJEm zzdxM5e2lgDgE}ia6O*36rI}|U1lAT3f*R>Xl_7RVTb>ooTwexGX$lY5Shm~+vj)^e zTxHF~xNB40gC@!E*)z6tnRl4FymwoWtqIjTwh-9u{2Kb2d1a*l#@84 zpT%g7WAb@lrEz$rVfa3lY`Ozr|Dt&&t+({3ewB@whhhPRw$JW1p;{v2?+@;Ts;b~VNgzhTjyVig1!wP49rIX5+DIj zOc3WG*#m(=>fV2pGny#Io{0f$UlCoH^v5Da9 zaA!wgb^sIsGbZZ`#{n!tr?G;JjXZD83ty4z7)y6{3bC_KVj;mZ200%gy0f#WI_{gp zH@+hE)W!ZQw=BO2m?Dhg+tZKuT%0aML#Ln4O#7dQ`K zFwC3ag>x-`y)2H9zz>}TrKZ?`IO>9rFVu1`Dy!--+lik%0FNO$3XsasDiD)D#dP*; z0T5b`ldN!|z_^U)Y5;8i^WdWMEzBNuO5Eg1zVI}sM@NG+MbfB^CS^oW5J)0G4ea`q z&R>W_P$dFpMUpZ>E3pa{&h!BO!w%ReC}e9~5JEbdd;gqYygG zKjLIycv9K_eP7&=ukJ0CTOCEHZ3cO-HZWx>Wc|Lu0a*v)8Tu*Wa$Ou+M}<>kW8p6Z zyIm$%(|V)`M8R8AdMRTa(A{xCeuL>gEp2IS?bAqjDQx_#ijJ(z6{Mw^Q%*BUoz9 zS2h5rN7_S`udZElA9WW;kX)FXdr@)W{?yZV z2mdxvS1mq$u5eG5N-q}EgZAT>cPT0;pj>~XRs0Cj^WVtRP||^=diLy90i{_P2y;<@ zX$xGC+XeQsDx&hBV8hmw7m<<0$N`}8K(U0vp^AR{Up#lQcUC{r+HoI8JEDsj^|KaH z3c$psvC0Bte~>EY4b-;um>K9~%02?M^(eL_4NYc3!Ve5;N5!9WWT8C=LV!LmhWfBb z1kQH?CIDn*WJY{cOSu3HFgetLAKkMbyJ&xO=E2dLn2Izqa%mOX*R`~$0B8#OLQVtEYGCzt*nCbmf&>a1Fwv13a0AeU z`Nt9`UEiJf+0xM=h*><=A`44RX{kPX>-oQhV8)d-G;jzA++aP7Q?D5zHKV0{2v3gV z7ZjFvH-wjX7N|M^8!D@+GCam<&G<1z+5q^g5C)IA zmQW1>cD6^tfIVSU0}beWXpyiCEcErc^uO#{9=pgguG1U+_&MY+@SX;d5g`;w=&{HM zR%>ZlnUhdtc=)j^is*qeZE8?XJtTxp&___ocxj@FT!wbo~73N5$h)X9Qy;G>%d-K+5>IxT?Q?#hJ3~ zr|A$IVOohzj9ibRo87k@E{pO~Qb6v*&zoGwnn1C83(9OnDYh5{c~;gm5XMlSuHb@D z^TBzRIP4Cv7CI?VcvZX5^J*_dgP4gQ0`@Th#s)^aXuV;vibzPHUb11|(9h#&@RR<- zz&!^;u-yDWDnsQ52Hft`cw19A)uQ@F@JI6oZ-X(rWUOP;PrXddCMylQcE7KDyETFI zC7%_f?Qnbq(CQ8F|eLC01Gg3=-g3pIO*iDl6OB*uaY-rN9sw zAHXo|9dKNp)oRb@ZP-OXA&~-rEW(+xsFWR*K9qR)aSYVZ5}?9|VLSTk_nq2`iq_z` z0mB5%3spXL{^RGk3*g$rtr9)@)shF9)od(B&)+6LF$76wd?@x}&q`TIDk-}0>u#Jnz^dYhY@Q5SLuuq!MR2Zo3Dcr4amg9tg& zl~GXwNgrf``38hK4i1nOTBnHJg=wvz-N`WWe-;VhqkI1h)X1epAyMi3b6d<74^w z`lfb#s;is8Z=qZfi{TU!TE*_V%Un|Z>(+i|@?8kwOw4D_^rL~a(v8pRwoA5tE<^@|;J=;hwm>T60W);A=l+fM&{Mnd|Lj#FRF-4j)Hb(2k1z!gY z%$IXbVNeA-GsxUg&PY|(q;v+7_d(|lQ-S~~%o4xh$s>ZpI+BKlhMqni&jbGkVh%YL zDzTR2A>t+-d-3ln2v4Ff{d&6gdM|NK!6*OSiiBSK=-&S=|B;PUe4<^+kx9H{f!S@E zZkuOZ<4^9g;me*ER6i^8gyQyk#(n!1NSrX&e7{cL`U2@}M)}6`IW6EqkIrL$`Dqu# zQ8j~K3lATvDiC8mtf&lMbA9i}feJw`EW~_M1xBjo_K(K=V|cvGTR1szGTfH)F8RlZ z)5!ieeT@I^W;{L9T_!`PT%bS~qCk12Dvx3M1U3t)c?fMNtSCeb9CEHN?))Yl)4Nit zy8P#BwweTOjCA$7>s(b9)%348CTTjXo!#_-0(s~0lf0Wh8K}CfQpH^zwC9Rr|7X6- zigOR zd49ZJ1@U@jx8=wjh^M>d(WZ#||KUGXOC}|E4;Hz1gV(t0^g-{(bw(6oc6a|UZ14j2 zOs}2*2Gg3MA#5z4aZ|J6^w{CIC3!}XC0i{T> zD~Z@w3^ohxCQNTye(tq#6w(Q%W-PiVsfY$2AnRGSvpih9644K=F47&;E_CKOH{;sv zwpMVw9>I5gZ2~9mX+d^YecW-0GobVr6xlV_;`W;`=4??CCQ;i_YgS z1NB?-tu-{-@pcEhOIlm`re_x#o0|h2Zf)ICO!72}1#T|+IDHn#**y}^kwOPQnmsWz zznY4i_Uw_75z)oz^m%d-xh;3QwlrsAtNFy9KhHC&yX3Oo=`@#4#mDeit9ZV3&RG6e z=Pz5EcMVa3YBz2$H~9Rs#f9T24amEZshelGHKv7EepQUalp`YWmFzAQK>Y3P2JUM- z0M&TtuXMFMrn%yz!5^BM6dkQ_)5+R;27Sv1`-#c%@y0mg=fw{mNHxDL{<3|`{TRF~ zdL&u7x)F^}IOzsePl1!uV{+)b@7qrxEk1Jo)A-|ifGu0E=jYx#;1PexP}*{TYI}d&Q;&l3mA|{E zx{3j@qtiL;pNP7gc1rrQzi)#Y_xbZaK2K}EE`ou1?4(Bz3rAUOg~#F#eJA-<cUngJJhzzG#5uS7gbjh4;ZqtExA#9l9k1x@EU?B6^)rr~ z=FH=)5WlR)0IQGtH1++G{yHCh;Byn}&c@2><+}6^`w1lA+4Q5Ij4z@pUL=lJB(eW3 zzAM0sKG`I>(*Fdv(<~h)x#G?+5(MNP$uGT3BV*LxM5(EcX)lj)EGv%Yz>uY_Efk5! zoL3V`p*|yd-fSEbZgho6NWnotvU0Lmg%y_rFBTKZR5yirgXAl;ijAK8>FMbk3%FqwF6q+?$fx}?iepAC`4yuz`aAK*ztRUoMvHy+@KTHbQw{= zFCI8_n3P@jgZQok-jAv~OP> zrhS;)E=)F6e);m|P5!`C35TbLHePLs=nNJQ!0+qfLl-feUJ=8DgKmRE*H-8`!I?lw zZ_-jNdG)F{d0+R3yG~98>Z}Zph4S4qQKsVn`uPxxj-4=EzC6XAIJZS_-1ZhIdMPXV zy(o*Z99{aCImJM6>>O)FirK$CJ!e7RzyN`3P}`Tr7c<_(`qvw4t;sU@8TGci&MFcW zlET8;0+r-qC`knGPR3?rTvAkq*SU9cat?WF#j_5F5hl-{+rH|V2917CAA3admxaT9 zaXN}@;-_@?^HVH5^tZlnl&P}n-q7`TeDX3T_(xY2MU1wp#!No?S?j}1moPS5Pw0~NV8Uo6R%YjbZ-62Lq5u-p4tD=W5@C!CX z@@(VR)Pak@`2aAKG3N;h-4N_j*3tsC^ci+2_IO-eM953#U-;DYw6w=FslFa5i+!rj z8p&_q>`AtDX$JtWh7;dP?VAVoExQS!U< zc=@Ee=K>OE1)~m~R$3ob2FJ-PR&YU?duBMiF?N;NI{Ei(S zSA0WVZ2B7{Xs-DEdW#|u{RDYzTxvwXjG|7<;sKXus>^KO<;t6DWp4~Sv*te8hq$}@ zG!3^1)iLVUe(M+kAiMJ?WFMnzqlH=v=W~85;RSv2&!1;b>#R685obJ8Qs&Igz~qkh zF@ZsFpXtB0X;mvudzPJj!Rpt}ZL+6y_l^Zag%g!vFNYMH5*yn$+Wt;$N+i$fid5_M zzzy#`cA1M=&*L7E>@)A}{gLJRshvA9o;q(~E*!^bzKwbGOY5~xiL;8T>d=VZ5u5p4 zAMKZ?lqCJBvJ6&o@AIyotkc350pa1+OO5f@PIU17y+bW@yC=0x-9*uQs(XXiDb}H8 zh)wf6HNU>2ivWw4f^3X9 zg@bvwL^q?@uJH5Lt38*t#YaqZ6juJK(^$CJ%V%Xj^|QUMC0Vyy2e@JgduB{>P)JC| zje??QC7H&ye*?}uk%>4btbcdhTKiIx6@8!SWf19GnJ<4urzB`d@HF=|`z*gvGfpoW)C)vr7<83jxw9Lp~ z@iaiyA66_`2NqX!c9+XkMMTnX zEPdm69ui`&mw1gmBLhbYCKwrE%4_8#n02Y^=ns~-goH?(Oo-eo>hKQKO?YHCzW4Ch z@t7QyhdpBBLcQ)=1vRy)k$^I^swRe(lauRH*%X*)a63*v-zvHpB*|!~xb0tQ#7WF& zx`=F)d4Bn+YnzlR@V=36W(J4q;*|0gE2V_;VwVD^If($N3)YQR@A}f-yn%HN%=v zs@_U2n?Z%&m}pO;?~!^Ab)PGd>L>vKQ`S| zavH?VM09MR%pLzUhmvAwFXB^$fllA`Ne5)?Ek!(|Q1c zW5;L^r@*dDNJ(KXtZD8}Tv=W|AafbCUJU`QC_ zGmn+@dl4AuN3)+FhG`U_RCfm1ijoUj=P-^`wLZ95=HMU1RRn2|Qhgsm{@sLWj@{?cJv_l9(H+zbY%+ z{No4q`kh(Bk=3O=BaY3@874qiGIW+S1*i>vPH`{KPcX7owzh&h!XFTj2VSGuliyI#xxinQNISvw%kTt-(rD;x)1pyswnIl~Eg(mRVW; zEaEv8ed6?+D|;Fiwpy%1-SYL@&BlMI!z0uj^3N){ZrFU^xRb3VR z>CsFc#2N;8d=Xw)pt z(mYSAX*Heu_3g8-efBwfpS`c^fBr7l=c8KdUGMumzvnmH1IB$A%ITiABhwCdw^f)9 z`bJQb(0XiQj=3`MonHEJSN=IFkEc|?)d9Jfb;@qHdNZg(Zu`&p2ZfkGT+vSd*ovL1 zHCb0eCKSU@Y^aKgOdD&Ye30RfK0Ul*`FF0(#16Vzi_w?L=_Te$KEsU{nO}$DWa*922?DG-m zD;;^Jm1prtfDDDmtP$bPyxkqA<8Sg3vPIW)UXa{Aq zr{JI+z32rP3H>E>K+&7o}RIfw?DJg(0*mu}K$CAYOQFsa$;eBioY?xoS|52tB_g@(RONr{Y) zhhR=7te?%zUjt6`e9tM6XIg4%Tqk`a0r}_RqtPE822-E~c{!Q*WE^q+(oq zspeRGb#y7Fc6?fyzmVr|G0Pr}C}R*SnVz0`dMVW((4gL~ScO&dVfQazP&F+J+5i45 zc>#`Tswyfc_bW_BY>si3ar0$Tm?>VId7jMVvtKYb<>r>GslCaW*o%z3qR64&MzIF- zYKDb`q&wD#UH-PzVP%z`{BD)`Yhp?Q$iiEnJ(FTp4y+ML3TSWN&uq?|>(5nD@mj=g ztSK*Nbkn9MPgKXtuBRbjG{;#MwYP^A9o54uL6GET@jT(kk?kz287?J_fG-8)zsX3#>by7Dk+J>PiD}P!EY!1mO+*;*Y8LzR0DrBtIh4e zBTGq`SzgRg9N$@+a>mn_W~4dWxJ`j#Z#401^4F?!i+gwnRo?gR+oNM+)FjlVHY4>z zodvffWDeb(IdykHnO?ff<#*>hQ2L?ncl2lqSsb&TA-1jxh{D;-9y6RUO)%xw&9*ML z4B*%)@ggt~1vG41dFP7ud83IU78@s5Szc8YfBRi;G#ka;hou37aj_Pa_Vx~#UK;e8 zJMg7xw5M98KH9wct}h{mjiW(aiQa~rRf0nEaJ*XdcTW!{JVX5hy}f1@7Dr#t>3zPx z>O42rAxQ-=_yK`?PhY?8@Z7yd`=q~bfau$Z#|2ZNFugP!NK~S5%3!q0G(USkB}LE0 zrPE_q1vPsp!nUcaHmkK3H{7kT3{Xqe>h8*wH#+|nPQGWfv!m7R?HyUf52Ra_ zruXxTMu^$(-)WUuEHG9caM)|lsf%cecXggg6m8NgSn_2GeTHc#qP%#2^@@3g%Ap%Q zwLRa&*bZl#HWvoPWy44K_wVZ&=bx|U-s{#a&J$k^ZQyq)jwU_YtPpatP=9Sb?3^Ye zAHip~tnP*?Bkn@(-2q#uzl0u^4?p8f!7%*I8`r$My{n__>#lMhmfkB-RxB;Y;kB>r z=$q$-;VuBjrTf>n&hCpb#Y~@?^ibl#gU@Rd^{K9FyEr5;Fo=vx$}uQUSL}SKp$<%N zXpV(`hDjfbYgI;ecIOA<$|p9ackf!6bXJzUwO28S&avYj+KFm>`vH+$!g8wNRN`~sg3l169(Z+i)bxIQxYL8fP&ST~s+s395+wh5X}+(w|E2JW zh%-0!Y;ZDNhSkrquINLv`Y%(V;)49LM{!&L`~CiUX(BSsCvN+j>Kje=)ml_E8k2+8 zuOIvBy)sJ%m~LY; zWbebNDi?G#DaE%dt_BS%n$9A=(;RJOwSzfbvGsPHJ0u3zt2wj}=ha=+K61a&uJ)ql z>}X~_7t=lNzYli34|F*%6MyE(Yy}+e5Hv5HehbimA`_kqU6b1{YSZGzM==x-Y=&+Z&-7$%w4)94^Yce zhZ9<#T1S@43ghsS>klvZl^4#7Svu|3ouAB#43sFDAJZOEXTEy9zWV3nqom1BIGG3M zn{HIvp>;&SsY{<*`o(&q_~p(eF^Y7z<3qJAG+lNr7mt71D9&izAz9*%e_+}45(&V% z;mv7kY_~w+hYw zCxeXtYy$BA_t)NaMs4#fjp9r!yomY7{fQ0I(7hTN3Dmb#ep1;N1Py6*V|?;SXHIVJ z9;=V~sml(YC%_fJ(ClA+;?dcIN~)?W4t>qqFCfymd&^_woU^J2@l(fi(Z^8YR8d!7 zb8wHZp+3s$$H~th03-NCCsYHeB7fw3X&9xIk+}nr!bv|oGz2VMs@*$EL=v=>K!RnX z-*SBG9z29^VDJEU0v!$YF`vbG4XXWkhfg~9QZQ^^_g{J1|AhtdpMFbRryLLbR=K!# zZh1^E-Q?Jf_pO~w1G+63NaVznl+`95Ri6ivY&+4?0+bAhnCNI+^l%a(ly{ZxSrqbK zh!#VPx1piu_HfaNRHE41OVFFkDc2`H3l&-8IjEb>r=<$21CRW%LjR-YdoU&?1%qEu zkqbLX!@Pt*3oxz}E@C)UxE*s`By@kC*m+KR;DY|=6H~f;8CUwx6Qh^D7S4xnSNU|k zY2ZtH#iR})=X>?oAKB>tr+=Kf@CsZ|2#(l0I?A!_Z0XzS@ujV;4O41N&!-dHgs-Tn zLBpVLWJJ5K6;WH*^v5VB`&}Q@vIa&*Od$#nIK#vKaLpLj#a!py3212n?tozHz1 z#A!fL?8bEffQ#7*e&B^vfBgccX9Q?0Fc5MDWqGW)M>KxR84po=!#D{z+8E~T04Kru zGKa8rm=TvHoXg;B9PsFoBydqde~gs}`*3c84K@iiQd`>t$F616e1gxX9qDt7?u z&|;w4_?N?CYSHR2P#Az1hVVUY(#;2xl4rXqEAcGmCm z+vy=ifEOBKpW}sL?g=K(pr2UoNE9Fzp!DIJfaHO4FHj(n^Qa?UpK;6vKLSh?zz(>! z(N4*raB^ba^$VyIvOn;4^na{ZByCmL4;LHFIK{y_w?u7;qaPuTLc*xg#!~tQ437{)Ptw6-a ztz$1RV02Np)QR54Cn_QIqqd{ zUY=suNk6)%gakNItH52ZHD3U6_l@#wFKX9_G<7^Ms1~6_eEz%|yK3k$;!0Lpn(W1k z>6w|MwUHYNZUayD59$~ba^T-LZWJ(Y6~I~(7A8~`@Sw>?NIJJ|*#dkBtF$tR(^zNd zUeZg0Sjff6c?+mVdg++xXlQcxBSz6nW2^-Bx~7&^Cn!%*oRk5?hK882pJ^q~Vgu@e zUK&2PU-05^s)A#3R6LY6@ZErr=N9kf)%gH0=n3GuQU(B-!Uzk4P#2fN(IF*zLs)5y zj^gjoc>;M8VFjEbX=StwAk&taoeihBI8GC+D|{e4vZQWS14F}>pFh#kkAgE@R6Nk% zfNjl>H2a7VZu0=(!|j?&e+^1(kg!B4S@$gq_ocJow6rqFA9xvHZ?LEE`C?*liMTsx zH6VsY%kF}M9QMq!D3BfCKMKGIigRxILQD?;XG6%TD^ds*s)h|9Rwohyke#sot-Epl zBN9M73SpqWwSKn}s~;ecU(paNJOMmE-V#?5z4cu;L!|zNp(K8&W8(EN(UDV32HQ?m zNCt==CNVy?M*rmjB)1Drg+4wt=z8D;q#^;*OrD=d2dkcj4YjU8G}aC*C9JGYkf1Qs zhiylY_H1p1PMp93Ye8^CdmMM<4&ya>Po!MD5My+5H(8qX9b z(%aPYU=D!nh>~uQHc(N|Ei7!mpG;${{64V=MJi*+h=A4sS5c1b!y_X=hOIPq4nrt7F&x@+{R#H}Jsp2xB^+%D;BsMj*(Ba0c*aDBTIE z&ysGCfiu8-0n8fYhPRy0mgkM*Qd9Lm`jZoJtI=ap&3!-pvjXs2OpxcsJ5JyDx=lg` z#|9A8CUC`x+bR*~wuPlYP-mlq2yMY`@avL4KK;w}; zswBefYa%W4CDhA9`cR6&FDeoMeo0Dyy*38aKT-53$xY1q?<^=MpN?Zu-5 zCljJuh_%Y}F|o0Xknwk%c@G_R&(h24>Z!-xJ`5K!gFIL%`eta-05o3RIDnv{B-tzz@JRlYADz z!_60`UTsmK%ZgTRBKYfnz^M1{ugj$cwWX;ktN0_BuMiYZdjB4*6hZ+Lk(&IICZa}N zO^t|+-|hgq4)L&2Z;%hkG-9QtrNS2N;L4?!Xbb9Zq*$b4ZKE|KAp>GZMh5>G*&w>& zJ}YXHMC5x3RW#4;+(`pgK)w8YE)#Hb5NA0rB~|MPT>RxDOqYR9Bxzjs{*tR~KL_4L}*9 zIfUcZ6DcX89W{yks17{w0st4VaR8eI&f9yu{!KtNat~sQ0?~>v2V*Wkk&XYx*$l=J zI!#T;xzJ??wiPTM*eN=~&?bEr8Zu=3q~r=VUUfo!J<|3xLv+}9H&H})ZmX;QuAqkrC*bXSYKz1iByYmP9{L^Ni%C!|_DVY9n4-*$IbvHyxKPS#Y9?@t0XtWC`BIx_~kb_w~&pLB>bGvcn126hQA2WPv*a(}zuU+>)kXsv<&pc*r8~aHr0~U=|k* z)dzsZA?7^R-MwSy&f=aa0LQ_GXw9*7h44O5%fK}t3kXV%#aUMq)1V{i=ZrF9f zK=D21fOw+ctE!L!Ea5?$xbC1LA+}*jCMt1?LS7817{Yb52gvOnc!FTD14zWMMF&GN zgk?xmP2$xMSuiv}EmTgcqH2uKO1v{ZD+D%xTJD642A42|unA#tWdB$#MEF1y!PPeC zN&#!O+T$aRvj8G1Ft_lXDVS&B%^1vMc*m>Oa^nebo2CZgG& zR6!jWK|+ELLXh4w|5U^#LCemt@YZxl+k)T?1Bq=giP4+g3tpb-0p5oK100aauTORXL!&1p+&hHFzRR1@PT54e;Szp)(#E;T z_x>LTo&Tq`_J5(8Cn{em604sEYa|;zJ5g7!JInBshcUGJ_ig%KT|cg}Qx!_|JGMwu z5k5jRuiT>8u3u!0{GdbY$v)A#%y(-0u|F;V#~!;yxk>otn=1Q>zV(t}J5RU>T&1Iy z_K>=6-~8LPjK4yL?N9e&TSKi_VIPxWEjt0g6`&dG*(ZF1z}o(&_|g9iTZ*p<5YpWK zD>k1W{(U9(656tU>duAPz_ZIk0qf{dg-(X`>-rZJqN>1r0ZN{lgiVZ`fHKGM)XNK6 z#Xqo4O*$_fq`MS$GHrSqKM1_@)QHM+`{>kuA6d4YVDVFJd;i9-lo~6H0G@ld^ zsX!CG1|A|v9^yC636N8}Q5>SEUmXPmU&N}n42DC5y0A}H;z3?sbBH_Wr#i*Ag!XRB zA<3~6I`Bn)|vKJ)KzZ(${t&pcYad!7$3oo zfhQt%z6MXqSg;rNQd?sqxpF&nzhIf5v-klAAczIU#Sg2E&^W`8{Y7P;%VIavUzF5d z;MVc0!W0zGL&2Q*M9h?%=zc&Q;)k(a%Ux{SDF`qRP@MNZiwXxT7*Y)QDBGC?29ab; zr_>E_^70Zks8B>elrDT9?_haDwb1j(v&1XzzB*cByr)mMefi>6Gmz1;wpL_UKsG8b z%qZMVZH znN6-=M*$y;Fi$6eQvwA=XQ8txcszI+2phF%8Q#1JVQ~C^2N+bWeziFGwn9ngrLXUs zNx%Ju1QBw&1k-=G-IH$P}0=?AjFoT@k`3PF?W`hzLwfNPMrL zQHVq(_v6P7Ts2BG)I0>`0o5<~(~#yO3<;2g)bZ^qXa=8=I6H!a?Le*S?KJ@36qN^R zK9>%h#Ay6C?nVQFb;kr_s?`yc^?%mxQE4m7>cxx*v)SP&F~j1yQ!EGG<} zK6$c- z()8aPZa8DW5{3CP(B&u<>yVw*)TDwRi=r4kFtD!x=ow^ZXng`Va$t=(F1@^JVW9`G z1Nt+l%dh~{3mq6*H3C!p-fdAuWrsc}bOS>3@|K9>8Vv#{%mCoH>y_OU9zD_(EDjL} zV;l|Ej{Hm~0aUQh{!`Q4C7Y4-!?Tm{p^Im5zV$4sAIdwhC&J3b|0AXSH#i8q>E{oc*Go9I_AqDTfU7lm->%a@HhIZuX4+vtP89^TL@ z%;Bc7XT)OL$DlC3n>S+D233D2O1j1w^b1?I-s+AYXL8c}sFb-nm{m0X<<@lIx4G$w z`U=hLunNKjX~bIZG&b;TD5uo{Cye2x8~Kp3rBp}duw{P z*XZ!i1=rQd)t6U3+?!bZHdP*UUS!5~==#lTQdFmIPkrw$nh5kLHP;EP+S@5Bo7O5G zuGn#J&mvj=?q<1`$2GqL#=o$6vAa}{@(fRzRPLB@Fgzf7?-xjUAoxQ`wdN;)tVT%c zu?bE??7fAQ`%l9aZ#BYLlxRS-SatgOI} zKI|8y^^m)=zI!)G^m#vm2Ixkh00B3FI1#fOLKAhLK3&DxgasoGiIT^p|jg zaT@(KI7`9w541$Q@6X1@%;I+%@Ct=Sf*B~XaD73sg1p+z7cmRr2}ZoRh^;s$+1ym@ zj-r4BA>0JAgxG}WhNBa~y}~bid=XIY#~TwGK>Q=m&JxoEDxAI@ z80KOd;?v4OenZd>dUQY$f4(G3Jp2l9Y; z2|hY1C_)iZn<7tr*PM5QQV8IW41&GYBa$1g6kRivYw4)p@b2t^T4K+kcJ<+dsOxGN zo&U?1@enTh$1;{syFv|!TL#I6tXJ#R?#>_{P;J>_(waGh8;f%EPm3I*lm@g!O+Sc{ zS+o#uv6j}kmuLd6SyWUcKxyDA%D@B-0%?f-Xv#$=sFhp;M2a z%g<(CV!3rAHbPrTz+N)`qu+SNopT<>r%ZixaDt269Z5Z1GeA4m*wVJ>)3IADdY~fc zihXiGmhlC}CFZ!|)OP2oY3J6)2f*&gJz8@Jd|BxH^{nN$uUqHzIO$&0=6%bTd-ap= zQ^V)$HwK@pQya^DBP$IYu@rHU)Dnw`%QU5&H5Y7ZX{(W0OOL7k>BP#Pb9;6{?@6mk zLrxgIC;M^BD?(2?_q0`7&Mv%p@1E+dQ>b3Tz`4t#BQ(T^diw3!4vF^AkfK%J?y*~% zC3;>Z?>T3%LU7nZYyi+UoDUCIkEQI=*Vjkof}u&EJ%op5C#cKM%AW< z=+q!j-6a7vHc+~w-EFO`fK10355+k&PqD~c0fNIo;iFCp=(*UBDC-7!kq#4n%xxYk zdpY393I+!TFNC5MRP}D&M5oih(vq)Wx~VDP2TCOz<7lv>(~{mY3Yb`hdyuMz#y!YT z;8=LIdgBhZCr&mV#>$o!O(yLmGBPcEVkofz{fvqmz15*PbWoJk)NHM->8Unikev0A zDgA?v1-KP5Y)F=|9}1|5xf(QbATtG~G>*5}8FwDU44C{tb>IdflxqJh?(WNw5R9g= zs-YnW2`%UbpyN$R6uUS12^~+2G~lF%zCYRBv@fWn`!?sZi@;^8sfDBG*|Gjg-`}nn zn?W*z=+W}>4k_dfdrMe4p^${GtobR`Y#K8k7X@8Undl@c2(V6$$v8~^BrOlpB;_Ix%*hFWvu4k<5-nBIrt%!9#v1(rrIa1he z_H#rV$pv#bS2@oewJ}TmA(kT4L&=o?Uga9_f<*5@MUqJSQdiOYWjd`xJMYKpLs5so zlQ%|&nszySY1P>BlcGHYKAGg=sm`AAao z^1R27r|BhzL_{dgpMqjCBjd$GTUYM(jkh3Mfr;BShX-Sg~9{{SsjvJ^jilZBN<2ela?d4rB1&LV%4qaV&5eDkf;K-Hf959%9l_UO?g z!t*XhZue#Rwp$3?5DdX|7e99j0#B_v^?KG z7LeX?ED+YVgd1;PU+I@GkVW#PL-!1^h}hWh0|z-FbYHEB#R0*E-q}d)ttriyS9 zE?-rb%~`HV33ZyKzV#z7c`4w-_I*Abd(xJFEjIO>u-bCu*~Zmu4?0#qC5g1?51Bmt zse=p8-Q$W`c1To6|Mn7nkh$?$RHBaQyQI4M&nJGDhrU@O+#iC*iWa6zzNMcak))Q3 z*6NOMz6VczzYxi-(#W%vVQpVy-LG8|R$Dya@Fc{1BIM)S)4F;-*4 zrj7fTN4~edZPvF8c7aYhdu0kBi$D1QS#TjE=U?=f!>;!*wtrfSeE zIJszQz9OI40@Q$Aq!LC(BG8NQld*<&3PL`lZq7q(_Ul(8v`|zTi3SC7OEi>2>FVJm zh4ut=W<;uGpoKxTZ5t-Ck4B3tc;h~NfU^BfM0x}u#7s{wFEb3z0(a{m#=d!TKb%W> zMwyBPK?2AQpnTNMFanh!8RYyx^G9^oZ{D=)t6+E*W#DdVI$7QvpUVa0LsN0_Z@fGF zvf?9`x%PPhYKI#_c4lH>u>>eWUWlRg#-$xQcA#p6Ei5ZBazS_a5>(M-WsPx<8M0HS ztF`aW#DCtM-QBt{np+N!mA$zqPnLBhtM9WD)}HBdwGcO$is0*t8#YZ!Yk9X}#+`dr zxKv70R$1{%Q*)`&)vIz29*6ZcwP+E(t;X7VtJ-QhO{VPK`7SgBDD+Q=G?ytYO;bFM z?EMHm{N!{sL4&f!Dp852pu0)0cE~8oy{0?icRA2idLeWSxP-vEp`UcIyr| z%5&I86bOzDJgY7|L8!b$#;t3RROniNnC2KdL*O^o1(<-_PxL|E+&1P8%xuLN8t9h= zggli0Z`Q0Zp+u_o`s_g&Sy{i;%~*CYdBF_D{4#As4Jac;x4R$8uu&jd3wX+C#5pK0 z;idwO;O2|=yxe9r2}#Kzdo~0@2-OwqD+D&fnjK+~Ku`<}TsVLJVh+ZW5Su#X+(itq z$rEvy4sLy1j0pq;B`}J5Su-GPT;GcX4rnms-56Gc8(w|@EpE(z`j*u3VhAdw*Y8ww zXg?YrmVKLNdy&9|N8!Iil_}BDD!_$ZGxG~yJPt{(p@JI{k-mkAh?VKvZzW9Y{O>{y zY9+jugowgzYlkH)OorXN5q)%Xtvw38Sp9BcX`!ctDH!-ZtJ+XU7CLom5s5KGB#`Rx z@LbB~#Bdt<6RIJUBJNL~z!SLH#)$pQDG@L_IqBhr(qI>^ZgC3JZh&Jj=D>k{8N*vX znZVru_AJ86?XL$1Nu+Zk9I+K|Wq`MU`gpWanhOU!Nis)14RiQ;^lOGl0e9l!zeR&frvi3=)v-MxG0F6JSlo_^5C&!lUwD~l$AAeETC872X(kJHqA&Ckq)7n zMa-yQ+ws%P7E+A>v52DuAy=tb^NIe6;q-PO zWFeuqa~oI|wE6+`Q60=k$PfC~LzwO%RFU`7554zJPoE}s6^q!rq$CK8C>c{j6bAk1 z{j@iM;vwH^hWM`cfioh|YQ!7?3B3BL^~CTFr72!xAHR{;s1@8R@EV>{QLqdQQOp)0 zl44A8&(1 zaE|7JU*FgmGoTndcS4TnDOcMQ;J8AoR}EhHncomBIv<#Xo{$5c9I_6ud@)TsBOqXn z7Q3~&MW0<7;zuA2fuF)y{G-cCZg_Ynp&hs8YGBH)y&2suR0a-F+ep#KO#oGMU7m6W z$^~_cwXJya|6#veko&gDoVp;bhnyT$e}el)$85k7)2*Z(64@)O4Z|hsu@)kAWoJz( zZ@k@nkDqaVEKwKKBU~XBr4UZ57Q1%0#JDfZE~4nU)2hW1IYKl-zouF8_^fAbS=|i!w{WQ^RNN~u%vk&Bd`|s!&T{j??5eHbuBZLDG@LhGQ`A2u z5|>!T{39zc@!92IH3e$pmde$9oufPLMKrvIyCtdY7mv=?C4Kp(;%*th=Ir z&!03C1Cico=1b(Bo9JVryABMi^S74WTzq^*c&Nxg1-?~<2y(;XE`^zTol=ILdFW!U z2KW0GhE@DIZ_#sfqP1xs&cpS~@3}-T3}{>3xdY+PSEugAhJ>`Dk!56+XRPBrG7@p~W`Goq<)J{ow4`dkNZO-zP@VWSO^*{K7rUL~f z^o06!w-O`2Ey}UyWaQ*R`EM%p^@09Rv|=FT?BI|)I*m#Ur*C=M^{%hjI%tsg*^n)H z1O&)HDMb|Iojpis#o>41Faxao)PU%0=3bi-sM1>hN%#?G!|j;3IPf1^koJ|85hqvu zggQiUZyknFqR4ZD?O%rtKu=iVguveCHKPmWM|B|8N5BN_lTc?SXg#PEXMjR)l>)+X|$KvQkqQsAEe z1(xiV>S_hCKASCr)@n3-ZGX!VQhrl_UZfJFKf37$WJG&uN z>H-zf5Pbcbz)0c5+_Ps7U_AG$jnpwPAOnVlpU2X}JP>!#9H1VUHxUZ#U(YY$C`QN{ zwB&l~;qejeT&QW9TG(KkODJFg@C%~>+~A7_W^uHR5ECu{*`+Xpe7&$Jv=>uPhmM_#ny2Z!v=fC#jb$!<`E^$XK+Eav>qE7Rj%hpq zAOAqV(d&MU?j?}JR3v1_gw!aS#+ZnFxjuz#go=c_b4ft~{d58&gV3Q^!*&we8*N^k zpE0SauF!>)C<9g!8SNPeaw1bjX9J1pE(xRzSf|IY{Uf}OQqCrRn)5P}5>z(W`1;vq zSYIuGQ4SIK^pKDc!Y~3>Q1~=dB(%A4Dgr+U;XI2#jy5#afojG#qhsIx^XE%%J~z5F zjjBE?@rj2J(8mh(rAvpU78J<1h&2k}Z(o0ZHpbHc--L_W`_n;rpAK7ug(U(Dbce+M z-jQEko2uU?1ReFyCW7Wd)hllgRZP=e+24?%sX#>Q#&`<*DGn z$v`=Ur3uL*OoaitDMF~hh!~A=wZUgt4CgOjuE#S$x&%}5kpPewpz5CRY!9ac=J?w54)pkvb2wFa0-Iy?AT|BN71 zDC|lIVq0NVoOw&x*mwvjJrxP(6lU@f$g41K!wW#+Mm=&`FsHsEPyOVrz+?fGN-mZP zFjMB{_7qbJ)JE=B`_EJaxYVYCkaeGKZSy?w9|`-B*9`w%7u1CqFGwjXr$J{6B9yhY zw~@b+Bcfr44)QPC&Oajhsd{d7sDR++g;WsET7=B=@`4}TG|Xo(;)akn4r81r|13Ae zZ#0l`vi00PiQ3)zly&vW@-onfkb1zxkeY;I3u=SVLB@-bUDFvR@8tvOjrnKz$vf9^ zq>*3vp<@8}kDNG1YoB|jxOSt%jUn^7c_$UIDa2wR znt*4xeR4mPtdY|rau1sf_V=H^koofEp4{N1imz%JiiIy21S~ssot^^H~(iEj`e&|??SYPIP6l>10g`ALg_R^n5EHHn=Cilw$7^r zd~Z#Na@4Qijo!1L3>68z93&%Pr5ps6JSHkif(nA6AQ{1J>MWdLP)*?Ik*C^=5P+Bh zuEEu7*Xl6&5sRq#UmJ8|gM%`Jo*0@2479p^%F%eZ5Q)G^fmY+jzs>=(5EB^f>TAmn zdPObs_NF6zeCn4k!+S$PIId^bTG$ z@W+9M7#vRmBYH@G4Ic${5l(X=uK-YniU1YROIJsT>*u02zJ@hNz#Cq_CZ==%k=0e= zwjw7(R2IOY&$V3(0$<7Cu>KoOO5cbGBnmDR3WUlWe##*>HZ(xl;xgrk#-j?3qjXdt zRh|lS?Gm&8g~3;nm7TC~4n~Bq$phlU??7HcdRo(H0H2|an7#9$ldSLop-|nWAweES zPm6L~9r7MBk1hby&m#j>TP})!bPP;ZIY+j!r$z+%q4K?E%H~3wa z@3lNefX2=MqMS@~4)+&17!C=vv*SNQYKMj1ofbwf}tp{@d~lz4hbaMEdX-II}g$#A2K{cT`|TgMGUS+x&3X#4>* z0!aJwXV0SI6jkFYb|K!PC&cJkiZ(a)1r47&)XI^uZQXkJ_U$)0sp)C5ShKYeQw-mu z`h(L&BJ#!b72w@|?AUuyZuE`kxwMV@WL28Xk0c3I?^(CU{o000f*Dy^z?mRhcqPT^ z@%%Xrlr`Pjaa=%v6#zyjv53k(C<^$=Wa6M&Shz>)4w;6V*tcd`82mYo+&t7m^7VfCKR&thb z`~ubx<64UeHyb;<^W5JULzxMk=H`}T^;6MolA6jwPfzqKaIm2-WMSa~TSPw@G8j5=RLeaJUsfb%Ek%{kh#l(Y zYKbyX{QUj4lM#DZO9X{ler`vyoHR0%CbuHvNV3imIWmR)-1&Ou@paUu&P2#!0l6*~G_bI;W^ zRiSADEC9|R#h1q-D_YewkK-O7QWF@kY9j~|;5b8|t;+5+4ZysE2stn+uA`zVY{(hU* zm`tzrH=3X{y7~fywad77z`zvU`5TERo+{T8PY?=LW%?$ZBbGV=mLMAgZ~;K0bp1j) z5G0s{8oL5sEU>ZSV!Md>+FnxRTw&7sScl+$CyGvJwl9eQN%^*zzYh($IrPdYLh%!_ z80Fz{$Lzu`{zn(R{yV72_bdLq3aBlqNlAI2PBD7+_4G8HrED5>H$aG0L;Bunlc0#y zl$Vp!S8VTN0y#mreYbQUz>jY^_Gu%!4>ph1AI2Z|DGxXa?CiED|J^?h*Kn4k^azvD z(YW6(nCWBr@%&!fl3Yf-*rY5#x!O?IEm6L8tDF}9V)Dr-?d1Ny{{VUIQ?>W;>W~;cIk~K)Skt5=WQT`N=i=*cT+%dogz`Smeye4Y$~Ji!jN7@6 zNvz$AAS(a&ulT?H5x@FPbhGbF)ZyGI2f5{5?Ok}=`1N4vT+N{WxL+ugeIj>xyZs!1 z$ttofMd!|YH{l!ZD@OgRZ0?iU1l}6XD@W-`U+|S7-8 zhdpeiq0SeUC0MK+4yte%#J zq{8MjKFqp!ODMV^Xaju=*eO~FW(F2|Iyzy2fwEMmT*u9BnC?RsDp7_Gq1iigDBn_% zhK!Bl6v7d_rY3K7e)$nZ=N}aQwP$MEwr$j;a#>lsaVexcLs}ALQ2)Q7Ul@H_7YY!N zXhBsXRozM@Q7btStS)#GC1)HjIoV+?(45TC$X3<`mhj4YL`yeyK~ zoRE;*NI&J(t=jX|sjwAM5JgHpygllpJup;6hD1#Y!W?YFU&uA_ zX&@(=5E*$Sj+?koYu7KQdgbPxS5lgI`gAf`TWIgT(37Y0ezvxhf4}ZmO5kf&FrWY# z7EW_G<+L&12`Dw}@(#$Ri4KpL zG(hsO(c@gMJFS=JkY!oqvKQKpY=?gwy8;@)x0VeaMQGlC&rn*fSHRf=8 zOp>Rksm(sL!*@y`4bRHV;^#jRodkI#Jqy^`Q9I6$9(F^P4FU+&#>b_l?2P@4WFaJe zsr&skc+}eNuRC*Q1#4oM6^xg4PI8x?otV0F=kLdVBPWG)AbxAUdNm*Q7Gy6t#n5zZ zKBxRbgYB~atHxqLfp~(z<~~yZ4YKHW;G09^9gUp-20oXsT!zWZA5t>(nxOo6)6lRG&$Xf=N*Ku>@ef8uY=y3C-I7r;rE6Uu zzVul^_D9S~20h8f#(Ex39yWTsJ~6Po%YmjB{~2EMiEsd$3s~K-HmNs0EH3`*V;Ir5 zZS;~YIAMe%(6ZZpNli*t_PBcqz|Q6kLig!@Pjpdw%WDt0Z$}9JH(93CWxB@<7C0 z=!cLG%NZ}K?Gv4E2Xe%&;q4b*ggh}CCg|v3t0?4AJ*ynvz;p`ec)ow#Tjd}t)T_G#{~9kW zuJj_!q+O#^6@R<$Ft-7HZ-k@7ZZ<~_k(4~8_Yx<$lIb^SD3b69IxZQ_1ozLSjO*OKlJ#1|{`%*Ki*|2WAZJz{^B2W|qSu+6nVHpVWxejc zs2D*v zeZ1#}jdJW~Jm>m*T0Vocus4|PlYSNQidVbvcV*@Jb+>*2K&66oZu$fDE{rnH+dZgV zU0t$L^064VzyQD&c{yXjdpjkcSNySZIn<{dzEn5K9;Bm_*tFW{iggj4blD&AIpkO0 zQ1?We$#_@`aB20bSbrHt-zP0v+Vc!&#QSTKQY2UFO59)PS>Lg;!uWje!py;?*tvQW zItk8aiIeASpq%ji0dspt*yim_8rOb5{a4M`Ga(Mjv ztmI1OEn^BxOz{6KR+KuP56 zTuavL)uqM<;a8+t@V4yT`Y=gc-+Dk8Ut+=Nsryzph#=c`k_#_?MM1!m{UD+adr^AYd6%8 zG=Q_*^yL0^XCD=hLJbNGoP%zn4h!2?Mq-LqLspkm_$(*nLvvaM(q5muwtwYwZNlB) zww&S^mR`h+TTK=2H3RCL@(1a*F`wXMKV|~=wBUaa0&LV1J&iBL`x6&kJkNOUDZs2TG>v9ZQ1J~ zJXXP&1y$HzD~_&vk6X=#5OUs!E^GsYs;R!-qON!bd=jz{YJFwD9Jqm~rj)}*>6_O9 zc&ZfHc04)v$bGac=O#4F1oh*YG&HmTF>rgV8|NyoDCgGUC-B9sKVDLso0B3$e=#!E3p}`?;CB|nk$lv z&XKs|+(YCe)zUj8AfXG6v&me${jS58Fgx#lPkID7ViAjFH~X2@vZ}I|$DKpW79*6k zDgH(`Z}MuU=c{r@fLjtNxv6hpAXOvFXyt3QnUG_9>J8MfRHV(@nfHpju#$Qw{d^M| zRtG*bLE6TvpkSp!)znM=l8hjqbKvQ(-@ZkN*j%rG{_CZcm8rMx(CK?;l>sp}B&8hh zuMG5YtD71dPXv41$}HWwoA^jW^$fUg{4NoPLmk$yV>;1Kb4>M3LIN6y80Sb+MRJ;~ zg)yAkH!TY&~f5CNu3;QVWN9Q zTvs2iZg63B6UZ`!)J$HI`s#S+TLL@}DHI5g!})f+!}I77-m%)W8+{EeY0jZGH%4an ztv=_&r+2iS2wQGbk&v<3o!Fm*X|E4p{ks_%6B80T^6e#MWfPLCq9YQD6yari$c;xY zoxGS4w|RA&t)1n0D!5&HLWZE9w++X}%8GVeZ0zdZ{D?xT=T+7FUI~gg^u7n&>B*DW z(KHmwaHcu6-y7X#(iBnCs6D@HG3DQ)u7b%m?rJjK~J3OQ|Z(nZ7GM)c8)4xjs5T=OW;HAOtHS2h=WHn)PJjJqe*A&e=h*x<{1d`U|`3_>Nx+Ju6!{O}NCE)&GVG*e`INZO= z+JB1l1+vKSv4(iRMA?{j4&XVV+3N#6DFaaMqxB|qZ7~PX`*6D)uot?W%+Adf^%d~s zINFXDVO0Ff-NysB4nboX@&{do40Q=t+@Zn^*HJgU)nA`iT$~-DvE#G%v_kF_bl6)r zZIrpGJ2*Tft1f+^i`^~LxGhL5D%;yT!Nd5{rEMg(H@c1QNDD|c%4VeH z72htjR_}72Pf3jsmsTcsgC!Sm#UGUb6$v|ZjPe|^d-Jrzi{)>db?8Y_SLEbGsLMeE zgXxIK#D%U;_v!pYXVw%ci(aieB?PhrV)z(+zCkppE9>rsi8luj^`Fo#z9RG#l|pwV zczKJh{fMLl7oLzjBuN+wkY{Pq@1}EG280I%g$B13N^Tz7$;|wEOB<$V_2QVd?vzO6 z*}U$}`s+@qmuzj-fP`cg8(ecD#>IILKD)X;wi|Bj`xNncrho0ujM2-~RG`mI`s$H8 zWM*Z>6s2qM3>7G2m~PowXxu-}n&<4Irx%ztytgq)d;UOox3Jwr>v8L{H)E%5?HzNh ztgX>j0ixdXdzjd4!>5QL-i-7NSY##f;B*c~1MYdzs01a=@z0nzxj03C>$Xw)9WEIa zuPOm4{17dry|gBthCF|;Az@LX>Fk9IIjDx;zaJSpZ4H3(>a##dJzkcS3=rEQt^Cpc z<2N7o{o)5$^Uk^GiFLe6`$zb;ZC{}>bH3kr z$Qb8Cs=T0B!js_DncAD`rwSX_*_CZrcjcH^1q>!4=zb6PD^Mw`_U)4BuhGBSoS9&~ z;i$UbD(Tq!2G{`~fK$Yh+836sjOv<95jAn*(p*rQ zLkIMcp-Y-&(P4D9NG#88j67#i+A{@zn|%jdW`37$t>=6jm&8FwuVyDj>%MDw;9N`F z>&&cGc`b1A^>Pi66|ET<7^$4f{nCB=9v7FY%W9Jo)?~8wJQOn8^Y2JLsD>M0szpXs z)ur4-9!5E7&5u_GQVJaAgE~Has`aJw5AmO#>=q{kz1@XO)b1+lM+Idi|C;K#klLdM z=5R}Ky}t^-y=L}wR;pq(-^$I}<^~S8Ue$p7_3QRLZ`p7O)8V#kv+SH4yW6)9x*_Jq zPc0rfQvOG|mOBZd`Um;zlk?~CcL;Lsd?uCLmYI-#7V46GdS7~%o3p~n-I7q}j}W!L zL}mP=>d@4RBj$$2-9#JO`9LNH_nC9^@=j~vtE!MT_>p3)W)y3^0kvs+*jf>H#pk-? zTwIqarhaE9*8+`yz-gX(<6kX@F0zc*LjhlgN3X!-acF3siy$*sip6-2g|v)o!R=L@ ztM0Z~QT1L);lr7(8i{mmqY2)KHH9a223vOLzCYEbm9``^r!wPTshMqgv zotRg#y7m4eeVa5M%k^TbzWcdIROr}0st4YXWzFMD6>PL zyL`A_T2!(hgTEe*OCq;_)nu8fA!HRGOI#}~$gyl=?GVPQLs^2ER?G|=*I;u|QEmt& z^~MEQoowHlw~9=$wY612;k%o!%gSc3;GQoVF7(L-<4n{0cwKYg6K#5qNkiD{*N|(0 zr?)cn|EcVk`sJk-7q$RykC(Qi?GnWHL;o?y+{s4!Jr|9Jp%X2iXVGgcI67% zR>j+xs@rYbwrtbBai|skH0TR>H@VKi&FH|%dm8HMmUC4@GXvkVO-+hSYxEpK;($T> zTynuIL_jlt@PD-T7En>QZ@Z|zzAC7Mq9P#Rh=72AAR+xa5=uAHBGM%}l4F1f2&i;R zcX!MnBA|pw3?n%-l0$dwd;Ip^>-%>6_de^av(7o|92W~+I86NFdG7nVuLvcdKttJs zE0EYLZ8_(Hp!91#S;U6pL7MGNj$$Eg{bjHj~OmG=8T=^B#Vczy*D(`b+>dq!( zE%YkUw+~?`UU4LDxx7wSYVDkCJw4WCaNn?TuvW`&>R@+E%JI4jG_KHYfUhge)ia|Y zm3om%QWaF0Qp!tL|B5MvzqG$U3or? zp&Zuw7N^Y2(EEJ6oSaS*8Qe;?u@7p8#3l40Y!GN0o&9%?d_uqG;A}S5H(;n#YBwMG z$p}*}VBY?FKZbPxr`#yiCG5pqEZY`v z&qQ(T|ly{GT;FX%X$?Q z;MqAj_Jm>uZ24cuc48qr1ZXI&t@Ha=IV211S@!;5I4eCq3~VP(G@3JY9MwGk;Nui< zOQkdN-aSmFQcRsm&*jrGFWF_^zN=%r4mw8y;44kTp2NUJZOu+8nsnmQi)Io4&b)EG+ah45n~O&pBN2ZcbKhOK+Vk^Ts~5MVBvz-8kmZCMXH_5p#pu4L zS~~-ER`<2d`#!R^rFGiuTwu${fLiz9BX7O$K%Br%B_Npjy5%LGiaxitTF+N7CMI%E z8FCzZA4gxjijlLfD~S8-Ibm_ZZDu#sSO@K3n9zH+5TlvL7!(avOQU zEHia=jqx3y$)D(|IS7#f0O{DqiGK+|{d;gqF_F+v=80DpVIsx$Np|*fgiRUx9kF-b z?D@n)g2ry2|KscXqJfk*b?pD6f8AY`sFOxUoRxV(E~6IiWkcen3Igf>zeEF08b%!< zI*sT8d^tJxgui_&CPmdQKLn$~uOC11Crfu1NtRF1nYH>|_XQuEW2cgD!kFYEiu=$X z+*_(%Hi^Oyx6|HiuE6}`H4n)fw%H027OP&90?Gbm@Zr0MYHYl`sGX8@3+1GbhTCkC zK0g+8X@4Z;+86eQhePZI1SmiYYe%R6qgEZa#b5>#z+!sK*?=Gcw$^)-<`-oEDzCXr z8a$P^qyfNSQmPB-*eXz{9srgd5E@E*rp@M;jD|w4?j0&hIZETM<@MRHOKnl)eqS8W zmZZzjH@^OLb^&xyK|u;kQa(VvQzC<0Bgl~M1CE#dGMnTf+&#WX6G$17N zLnO6}V1og+cbQpPzw%;EBPPM<3iia2k^J9Jl3-V1S@1A2T7rI7)OBeU-*mPkuCl1C z1nhaM&tIM%Zmli)v~0GZfPB#05(*$Qx4s8Vg3lvC?s@%7BlsKwURPl`wzI(lQ@_us z7mgVI1#ndx3JAOy)a3hqDE=z)El~C`LfnF`AZ~1CWBb9wV}dUPN@qB=x}N&3BqI6E z%S4!-MqH$g(|=@uahlp()c2)^lxpw63SgXC&_;nFxbT-RkZb_<5io#;>4jaafcqL7 zwyFvO5noa}Z7E+wfIw=}$fXP#)Uro5HVj+lOkUX7&_c*2gucLsaVs_@3%WI!B1766 zfbMa^_E3L#xVuYLp^4waTK?qLz>Y(E@uEOQ1@_tDzSNQUwl)3&I68ZNE`lpodVG4C ziDqrz8;LZvflaU$rZAA^myWl#whF$&rw&Pg;gP>*X93nM7BT~^zALdSjQY#ivn6R6 z56{XPXZFAr4e~jhJ`i~RA&kO>;pYbv48M!4vvj>doikh<9ENqzUQ$0XGjrW&jeyke zp?CvURvA$FS{1_?10p1-f8^wJpz?%$5{B3yG=gEg&Ev=4CbBOeAvGFW6_SQ|eg=JH zRF-Mc79BkUI|3=1z`PVRBdOONYHNi}OX(u-0{V`ndm}?v{3tCg5BBRTw9J{Ag+PLo z`r5Xq zoNgSB8;W*G9v)uaEtvOla*AtdVH2^5Bz2oI&^4766fPZZU7A_{qz*d3nm4k3AA!ma z(=mJd5csaDT4X(RcYj(5%yGae$>TND80}yW6~92s*O{M3PlIe{hyh>7==x^ugyvYD=ioMB)4=Y_ieki+D2L;U!0xHNP0j87oPoBt=C0m@vD}ohg zb8t~!o+6V1X zuZhu7P<^MJ&{7Atjk!5%h)*1L5S$aW)kfix0V zRgB_Fsz0pxhYZq!SJu{!N)%4QZjfM#!|S-R|A%5p4|_9kpxoI%v@i**YC7UDVA?ZO zeW%AK=^if-E8N$Ylc1w`%n6g{+h>z9H8U5bK()cd;%P=70zRvNB!dL27($ud+kg@! z;j#Ub7IO>E>Bbqg=^#sMD_Fy9=@Z&V9B-GA#9W!90!n4v^3-4g9xVxOJkx3aRyvOp4teEZ-Agt;#U zPARx^a+2_gx~cccjer+J<`)eT2KM5f(=O22>WkHK1{q?VBK+l?k#9ei06kzr>IR#h zp#81dm&wT=iVPlrJ1>7pQCXTziO+Cs2;&J-Y#JG)iO$HhuffsbF|3HE=C|35w>K1p zL_z4EWDE^WyC*q(sUav0zJOquo^EAls!>Qwx?JVH*4tYOZ<{n$VWqHeIM3|H%iJw&>Vs9^>jj(nbn6a?UxvGBbs! zp}O-zt^-6c3j)5$!QMvpf!fW$-ASQ-k$&Izz#nYo5%?+m{%|N4l?0hb);3m^5O=fb z51-=2fT>Y9EH{98Z+`E9MG2_965uk#B=Pz;D=cXn`ZQWvk_h0Lope)*lc#m64(v`k zIyVB6^it=N&Ui^&E{gFLiG|R60h(`aQ0W4Xq4uZf48aGoAz24{cMsJ3GLn2uZqa)e#GZSYKQ4yu$2|M;Xj0 z>b4JYgUD|H)&&Q@JAEh)&Nd5>V3n&~U{Gx>Xcz)xo%P{b*xDr|^jCNGd8KqoMd{@U zhvtHY-HkZg#f82CT~bzLYRkLDUwrSe8?&Xb?jLOq_KK-}nD5(XkUvGi1cHk3!AkpJ z#yi%-131PLC(w+-P=>91*#U&CJz6lXaSS;45U>wg-||8`0LUl=~ZFaDqLi~N7uuRBh9K8Ie7 zHt_3(z?7RieWXU$8e*+4{<$^T^1l3S@GZz0dwq7&*t508rdFZ_hBEsz32a{7o!NQkgA zv4WtDN4(`wpS&mxHc^v>BK+Gou)lyT_Ju=?Cosxf!a-OcQs)iDEFOxd=?;BR+R-3^ zLIh#1;LiYhwZIgRPl2oeCTwwnYu9`s?G1F?IKZ^D-TGkj0sA7rb=y0*p}hTrB1FG3 zaW=ad$jQqEGveTYfSu*B*FiyC2kA#~{Dy&&L4nR>j;r$w9YEbB1ynInTJPjhZ{^ZBF ztb93%d<%+A9G4E*@H;s>MTB1jl^!_)xZH=B-!QwD_9Z}WF{G)6tv&p+xj^}0<_uD3`Mkj=Uxr_|eCCBQ(b>WZmv$JtA zF%n+e@7tzelX1Lzl~m>f%`6CueHjuWlvKz@pdo!CQIlWCXrKWY%LZd1D4lH>;z)`e zuuYW#wW5>9i2!Luhm5>5&_Zx|sr((+v1vQIF?x6aX?0+MG>ZhDHdrJUI{Y((fJ^4_ z8R(b-Q~vgQ1-!=f^|G1HL=Zy28w8^ ztQW|W3NKUtRED;`ZK|fK#;C^SLyLx%s_J`5AAqf4bOs_G81Pjmo`GlVJ@G$?ai8~1 z$ubl}ZEx?2h>H5`r2^B<>-4sG`hO-5L)`9~AMDHwfEd7G85qzTafN#6g~zg~44o2p z2V@-vD=FT_kgDK4($D@>!Hn*B61Fo((YW+SeEi<;KM;L4O**HBGmGS|GEKSAJH2SgB@Ab5EzYs#}ZIAUVx2qlv3;IcBY>oI=bO9iGMpwaR3 zlc;fpSzdShFe?|A22Z*5D1=A$;4||SDMMHP+CD{XhK-~O2$0OL19)Ic3xNM~bNwV1 z6alOK4h)-Vc@1vE$nVP+q&xm3eIyWLjzryDrlx>eDCM*s4Fm7WLiNTJmyy6Q(b$+jy;_L!~$d^-1Mwt1)vV~ADc;H+(;(dzpHxNbh z-kT;T8IHoZqgSQlu+#(B`Yx0X(V`4eq$Ck#~vZ+0RN%Z8JwlP-lag zmF3DuUS9vkF|g4-T8QcCwnlrxtwcxRB&voHj((#ESu;0pe#1bz0u;~Z6u5FtTU3@c z-Jvl7v1ve5R3+pv8>iYEKRi(#eT=|7z0vwjU0a(;*kl|8tl-YbVYvO@w;!0-9_{gb zhBZn+t+X#tUf*vZ5u+frZ#E}<5^N~gp1XT&?^VQ#S-3$P?*b7OOL;NChgzxRRj>x3h$UOb1ySEVq&Y6@{lDAho*InkdWK$hiQv42{ z?7l&fGk_mEY>8(OXU?oPioPj0T+(kdr%8&r?ez6FLK>tvmJbFajJ>UN%RN!6C$>U= z(~oc<3J8#Re(u!$4R(1a{ZTs*-utWtp9IUOg7qr^LCs)=D~@Mh-+#jNKPH1a~9KpJ!75<|COorXbubW_k}ZPA#Au#0beotS8> z^=;Y+f`ml*w$)soXz-H?zRH&epZ^5SxX<1qzF;gNPb$`$9#-W2=kV#uZP3aJDrYII zZ2Bv6g6wd3E-}kW0vC~u^C2LQd-powTpsaOx5cPx6fjPR!-Y_M78H-81+>Z9{ z{+bDI^!%lM?}mMRerRPZC-VM)&*m&U#$z*DV8u#pqeWsRhWx}S(DWuIE)n_r!bV4865R30jG zoJg}^=QS$1mEyT&!7gEn@pM`(fUTNCBU55$()VCbgURQ2LsO9C^Zfw!OeIedUg52s z@11a&b#r=pdZu<+x_jn3)EmMEyWE=BzjcnT#2VL1)InQ_%(XO!+Tl1Y$5L1|GL#3C zN*t!S?xbn4hcKh(zPErVb#G+vtbgbg=!3^)&Jqf9_D`Oj_Ip!-_8xf!NE+ys=AWAN zl)+8VA|bl#bgu#IZJR?F>X#3;3eHq%33jLGJ|2w~l-io@sob&az~}8$qYdh+Mw&8u zW+Qow1l)#9K@|&rjo#*8G-wh%o(MeW94^y?99&vIYV*>a zd|}$JE$re)Uw}2#nW!cgy1%kBlhon9QSR$|oLINk2Py^@7SGGHw8Z{W&mZyl0`A2@ z2kj}^N%TQSWn!Wc@@>ZP<1BBeloS-sQc@l|c2KdaBAjZEIo*dC);MWxlCw%%ab!=B0!A02vWF)-lF(c-EOyo-TJMXxp&|HmgHQQ6B3en_yBoXNJsE@j{Tsi}Tiw0_Q;-5~U4D=C)KG~- zUuw8Jn1)%tfD&$SHI`Y^_+Yp)s?gwYHMcNb?0qz1%Om~^?KKooUWr!MfCKSO6 z6q&D=0ERAWosx_a(`pg&uEU%oM~^?asN%eauvj0D1S7Js`5Bb{+O$@}LmN17%(o0~ z87|`XUt_F!QK-;A7tnz@Xx0ElaE6pZua*S-0-}AY* zar&mOB|Y`>{u(cj!S-QWPo|-#CGsukO7-5%)zx7DZ>K-AzP7csy6!QyGh@#jP2G=~ z7bDh@f-Hjrb3kc@mU`-G;X53fuF_o*|^4J$SqR1^khXa?8UV7C~T` z|5{HUn=URcVe{+ToZ;3JXJ=HD(e~cnS;WA}(+Uni2lAud*@?QPZ(V-0Pv%t!juJey zlT*`uX=ivH9NOmRq?Ys?U7gDf76t1lSz%EV_WJsbHHcPrYjFeCHfN_2n@23Lv#mcR za5=*&1+5#0mqBa&4c};R@YpydIU?B|1lI1}yWd-SGU~w-q!|(@z^2wfU(duOd5>^p zOoP06F>sn&??EB(9aZARyV9NI<`)YMum)DSOEr6m4XB}Nv$kn7g+H60Oi+}p?B+QN zJ1OUBFch^oTt1jP&q9o>5uiJDBC`+)u*$*v~_ADSR z=!l-jJ-!_t8KHZ0p-MY9f--ZL#w=Mo*VxBw`aadj(f1Z+L)RLkggc&V8Np$R-aG3p)L!HFqXssT`{?1AcdDs*hdXYtO^nZR z(G%S%WJz-Urjpuywo}r=%#f*_4Mm^0WA_bOTD+d%h~B+>hvh5jY{7X(`8*Y|&W?`f zkp^`x-|?M=+FJW>^SzNix;0)-94kfSzGi20pnk!Jr65OoZD6D{iWto(}z{JfRTZ zZCwtoB^sF+Tg>fi*G6+luxn6Ikhr+G7AHJ=J=QzbpMWBkq$|L(H!wIzRgL-`$sGs2 zpB4(?E350AJO%qE+JlQyF&-{vR zc1j&|N*)B0>@3y#Lx7|uloXMEq6zjLu|#7Jt5`Ei)#0VYtixlK_WkP5svkr3RPMdh z57sWfCns-F%)hO#ce+*M8uYu5I|b6fIILQ7OD!NN_m)03g)%q_?)IY{ivtz8tg$9- zeQ-2Dl2M_y^t99lL-mtYdv6!x_C;^;@CeaU0Lu`h)-19k%#1Y7d!LRIy!SdLRK#6} z_3p;}lgds!o&idEKVm&CL>64QaNQSN#+{s8+P_r+w>x^>7=mN;4dDYu)k_wj1cJ>AYWJga3i` z_DGO$mi5S0&mJhVL-7%lX0koq-Dw{M^ZWX~(IdQ7d$OUr`NOd0%DFe7)Ssv4MkO_W z-Mn)pcx|R*u{YaU3mx~yb*|2CP`hm~3BAjQC`f8}oOLK|IMqLsSc)G&o4M*h2xLIR z9G(uj>f2Pu?THW&Cxu(*2<9y|c8{nUpy-Ouhb-i(l+cgUkRvK3U*T<^S8KDM=CUtr&T#keCk z>u>@)=O&Ku&CJws+mxazsB>9)qGgx6<631owud6P`%mQqH8|7X!pLZf)tSF=FO=T$ z=_IWgKnmdg6BAx$I;CSgf+9*l3jvq0^;#DD+w;SA? zh?J1e0yvI?N9b~Uk4klIEli^BkvYPCN3zH`Bz|xW z2&hG|*Gq2UUXnZZRaz^6qtz#zHE{UzdS-p8*;V3y)tHr<_4!pzA8DI1F#_{M2zncI z2FW#THldPG!kJ?VHwJA|(tguS(qezD2)nh%GGmR`8n?Qg&(D7*5Qq!arO zjd^J1zl2%MYHjMlt+jBuOG21;3u2@nI^gpa+P}4v9eS#_Y2A&%AIMP%@UJpFZvEE& z+@<{pmIDV~q7i2A9iy;vYy!LcXoEl8X_7nJsl3?jp`J$PWk%FH^a6R?K-Kp4&YE#( z;chLoQyV><*l1ygrEpp{IEKHYeL9sAZygZ8j%2o!7wcu(u&;Z^Sm;VH0+Fl`RR}H- z^*Mi2QFUf(WOl}jnD#UiK!ob-xV-}5KxKry(K ztVUJ8((KhXaMGb}qhXKev)>iC|7!oU`AZF>Sh(KWN`w$5qyXUEmL@INyJKU9wA@C! zOJWWZJ6}zimYBArmPg^t+c>2ZIJG384z?#^hik*Q6-GSfhhf9Q7C%k|`Z+uTOtmy{ z8g4l{9mkETo%&Oi(W3Api`MY$B%jq4$bo{ShEVXY^RDvJm6grN&DB3TbcEYt&$7v% zOUGwwdhRmKpu>2YMWOK%9Mt?D)7zk&hJ4v`QpWYCndvv?a!coz_Zp!@0>6j7cXU0_ zm37^^UG#=lUkTjPZc0cjre10jq>oceWvWoj&C$99r5`vlbc)}xn*AsP{S(wtq1596 z?Cb_$i12!g0K0>nVG~ zC@Oci@g7*`?Xsqa$KT0Lqy?yu3@pF+TF}>U(LWO>TyuyfjeWK?kCrf4|zrhc7RXt8nx%Tv>a9a`Yl;l|D(t3XY_Z67Y}(-Qathr zMcLh2pmYN_yHZ9plh(a-bs5>scoCb;`f8=!>E+GMn4@NWg{WIb#ZRhpgKRVlM`+lU zat1Fl_kO)Y!$n8!MLh7kB$_~-V&5nmJmSwK3AYFGZSG;-U-T3tQsh62f6O6NrAYI* zf13Y~ecwkZJ(u6C|D+5AiBT!*FB&Sh3~S1g^;aCu1JQDu_oI`d-;bX^DRwGJ&$~Y( z5POy7&%f}GX0A-P0!S@V&DnCBG)er{TrQGv{v97jySX#wq6_J2`TSXLQQbgKjaTc$ zu@`aQyGAOs2l0p-y;m{++i$g(;?Wk=F7!oi$BwBAhp|Zx|5VzRyDuA~KPOFk^(Q3C z>9;E+rs@AHzdypr&;h?oC~iJi01~b5Mt7L|Asr`L3oCB|UIGL7xqtgPNMS4mVi|ON z;PJ3U0Y_|?6C5=JC}HLSj#$D4`yN63U}xrm!9o@Q_6!VYoOB*N%EHe>NV|iTO1r+^Be7d zojNvJ{}3ix0`&08389k7*ahG+6S-bxeEQ0vnTW zAAkeLaY=~2Ts^z$WqGg8!tI!Lvr8UGpb8absNO8Ah-HW}pR;@MFjM%wDNMMv+RaOq z9jY9s@cQ9=v81fRPZxv*ZuIJhCo90=(VTnp=I=j47=Bq2hv@&3?-}-=Yc$k1!8-8} zM_E45)wNRbc@WGb3TsopKiyrdG`|1pe(cFpBcnpv$U?lsuVqjFO~zOVo-Ok0HGuvD zjI^#_uYr!N*Np%LJ2)1AHKuTi3EZ#>6#ZPKQmgbU^xJB~Ky_)U zi?0}<4*W1SE$zAC_y7d0fDx{|0+iNxO9A1k7#Ogrosgp|*8>M=7R=__mWqPXaHT_G z!()J`I5_rPL=8ikK6DRgu&XdhIf_e4CU-lPl$L}f-8ItFn;RYd3E|o>A+o6i&yt}o zQ#lrJNYl^=3Jko;$Ox9ffPki#1DrM)Kts#V1Gm#%5fM=J>(as?#%1ywGk9+43;+H9|r{f}MTPQlO@)3YPokrY0>tGyWK`&Mz(DPuE%;I0>AdhjJd1zdyLy z4JL@YLb6Obzz82djsukjXu6R97akrCaR!1n?%rUzlM3_X=4Q4mt@i>yTt`3qWa}(^ zK0E*yyTFi;^T?+&PXSI6q}a}F5KZ9W<`#rG_fvkTe&LS$H8`k{D`Yot<)^?u4!570 zo8P>6#+al87~qI#Z~5!k&_5Jc%?h4?6B~a_8Xl$+^74V)YSWY1Vf6HBpB4T#t z3+Kc=(O#n&Bp6%1ud{*h z@;GGj0|~cv0Mjd}u#L^lvSh^$piQq014}tU`i>Q;o;y4SS8hLh537?)8tvNZE%rOS z#BsR#626E+XA5X%zJftqRNVaZG(fZXMo8$H49!>#>jpZ=v5-SwSK)B8HAO2^=E1e1BD$ysocLs;%|^{--Ajwv;)rrUVe0Jssmy7=HXhCQXh*z&qn z3#C;d_%yJyF8=<>cMGmy6j5?%iODq!^TW?}xI{Nyy`_0`o|zVpz25@3`m0x7h_4Y` zQTU@x@Z0oMRJ1*+s`_F01w3rLr`N3%VvI&cAZ-_Xk)6{sk*QrS#4Z*dc+w;+=sX6% zAf7r!Bl8E~mFJNzb3-C*6@+q6=vU2qnuEdUXAWP8HZbtoqhti*Ms) zRv8~178f6!J;TE+>QdA_aQs*nFU1g-hNfm6k7GXdm&doCT3Emp@$1)NIcG9_Qpob? z>MFJyC_9g=s`b1fIPCL#6!;s75%$cu+$aIJo?_EqU@Uodbq!8FSha_J_`qlT>+N8y zFfH=A=U)6>ACjfsiPOUcU6w$d1t+$_Oci6R8%+&eCc`!5<@s=Qt^~^>e2ofG&M5ed z-3<-*=Kd0a%rzMMMe~9Dd50VUfCumN)I$lykC2gEuz0nEjFSAr4`AXkqS)C1f4?nM zkpveT<~4>InTykV6P(8g5ew<+8^IxwOTMei>qC{OP7sebei41h@b{@x@`Zq`!RQyj z-JHYUBt8M$W$$E7A!dL&<@4<6?G0LCr*kPlaxgG zk&v0&|LZyzSI^*Jo0D9nY^v3Oz-Ssy$)a!UdtaY&X71{1*xif-wiy+byBQTv?wq9M zc?z|-F7{o1eMBxo=``&2ettS>tjCXca4xD<6LzH2?UzGZg?N_!DKdC#Cf+2 zjv)r~n)=J&py$!yfoOvA+|2DO=irX9_k-0nEp6c}1%=&kh7xR0N$3nTGu1i=T%@U+UY5kw%+C5U-#0|3=20iY{#hqCdu=pE8yWkvG;r=cfYQ#nOS=Gg>pR>U$Ch2^Y@?02xfqFvkH#p z%M*KO<9cjf;Ad1m3wr;9;}}o~++mvpYd`!7@jH*3n_jv)*!}@s*mKdy#3aE*bQsja zuwyzom7tasYo4#DM=dYYYo9sx52n`7zIk(F<17^w0ZcI}-;yyi69CUhl{@@ZXZ1QP ztW-TaFQ@XKY|Tv~^VS}59x$2d(a}$;H$iE6a1hsr`{PgMMVYqh;9UWkHz^939?ycLbxik)&Hg}5WTyZLc(0+k>_L;M18yjoE z82AhVMqtpJ198@(@eRSw))xK?OdaF!c?z;*Y6b>%0KUN}0!aFwK3!`IR@Td}P>QQS zUzOC|z&)J?hrW&eQShp&VxtP|& zFkch}7O*s3^3S7H(<8E(HTdr2FHj>N_DojrO z)8%fCu9uLI#J9V>4Zl^cw>UR9fc5r=V{FXeeGv(Ufga#B4JU-fL;?zC*!C6hHpMZ{2+ga%-qL8Sn!*bW=0MwCEc z`0SY~X9RpsNT~*_=vL?k3>Q#NZfZH<6>e^%duRmXFM!yJWw~_5uL$*w?2NUYsVV4; z>p^5TJT>*T;Oh_N5alhPv(9pz zw?99e-oQ5NY&BBnml+i`l?A6+0K*~0fAUyWQ@^FXCNUsITSGEe&7c*-x%xgV>|idw z-?T-dnOFL+WA^lNo`VdUtK0&l2H{i1TmB;vsQpfyqFmkFtU1g$c5G<%PppFQ)jv|f zh-;)yl8)uSet)4Cz1&MfG3@^1bbhN(Ry8vb$coE^NQU>ssDtQWY1n>F& z^>-~a#r@BerNG=yE?lzi?m z6^di1AuoqUEJs%XPTZ%J(i>MqWa)zB?*t?J{Gn+rP}nUH1_ljnUz>wcWbbv1>dlLh zv^sVV3*meP$GC>@#VAhK3%b-=ORos0t8-uk<2rQG={x|fuq?YJB725UPR0Dz4j;$P zx9l?s$;olrEEPg?OUc~Lg#J5eW;7f>4F-kplU};3WW6C;F@uGjM|^*7Mif(=%%Ei> zM2}dU`aAQp@gVJ6^&S*PiL$WK?T? zsBvFir$aM)PU<;{6`SSvDy92FkJM23$3Cg++XY4@{>t&pA`^`Z3VsyB1#yUExwq6$ z9(Qh148Q+#bAGxUS=gVbue!eU)ugm}WMw?d*Nj*4k*4}#7w<#(4TggIxfx2B;U8u* zTMIwCzc&;l$E{Jh-WP_uP^7;|7)NMJSDESS9;D2VJr^?fICE!yZ#|09KWe{d(M#Ef zh8NH7-+b=fxl2f|o%tmZW_GNA^=F;=t;tE+&4r)VOEf4kYdb$`-KaAb`P-~J-#FMk z2OHEFljxXo)pB7Rz&qKob9ZHQWlhpvnTjg#Digl^CFK_LYmYZ`6wM;cg@!^?4OR9H zxx&P#NUn>47H?WYeiO>m45F&msOAmzgxA~`i);0SR^%T_WvY*4jnI%TwJeUX{`e25 z>X=afjW0VY6fpuN_0&&@#id~ciYM z%OPx$BihZ^e1)}_L_9p!M-%xB2Yl9@yT@_*e$+aFt+E}vcjw2aGT+EnT1|^NH}S@8 zr4J9Cz{Dbx-x8TVdQGl}+-F}q6PWgvjqWPWWWf-lY-Y6Yvv%lXIH()Rbtw?VPGK|L zK9jrQxq2qB#$TxZo?R*|#4loVe$FbfmA+0;O1JSIN*F=gKgW+w^H91SA6cU6*tbOQ z_Fq;KPcMhlc%E^j0+~r%{~2$ZdB=~M16VKdtzM3rU$S0G_)^pI(h`*jSrqCWCk@t z<8y@F`&Gs&74nWKWHV$qQ^F&8uqlk^Qc|0B0+OBYBcZ9|o?`k|0euy#KA+<5r)xIL z{CyUIjTam!dG`3JCr9fQC38%}^F<@su!m%7vpKsmq*dzjuA6up|hgbkzhY}H_xEnVymmC`=e)yn4GKa)Z%owzN(AR zp1SIbDEVxGSVf^Zv{O@mo&xf%&`U`UD+@pBzTAI1DSB7XDnw%xqx)`tp#u@8ma3gU z?D(r|#BF`_CPMnGlnUZ2R~wqrZtSSP<|)Fr%Q7b;>xbQ61C{G&3tR>l>(ogZ(A`z& zb6Qx|FRSz|#TPGR(#)*+BE7IYJ0Au;B_-23l|-=e55l~3AXec6N>}fRK#ZsVNw}R3 zZaLy}DE3A?Jbu@)6Z_qkw+~j%M`F|=_PhO?CmfZL$LmhcbIe@@-CvF*NEqIy%XP!? z*jR}Sn+HM0ZdVV@_Qpc;|I+^9(MxEPA>+G_oi92xL@|n#TQ_3WUVD%scqWYsGH&`I zSC&dy;Nq;eXAQc2cTaQ6TfxH;8>p zoz5bWS6O@?h`N*@9j^4=(IhLjpZUN_aF}PjEUlw{Qh zcLM+ZgQ)lY?}GmV=G|*Lw^U3%6y{L+!X^C~{VG@%_fsjW)|y_0blH6fOAKb{YpqXa zP)C{M@8>5i+XRy?eN#5pW9jPdXvNdPdXa=Z`tsGoXiE9?l5PQ(w)?u^TU z2WJ>M*Ndd43<|nxXuIk?Ym6}yTW zf=&Sb0Kv7(vMdiH_|QZqT^$~3RSv8M8;EN_w9fj(~Zj0Lw06z@M_xy_WmbW%bEo@MP{`{t!31vBJ%TO!b=Z`vRJA7JGR}j7czQWKlZb#ae|k_xu%<`vu3K$@F-WYigK`V( z_D3g6ehBFBT{#DlKk6I5yCy(}2^|sC=H1UoLf8EE$G77FC<13%fK-o;-{9sJrT<2q R3|r-~hce321<1#*{u4BRvo8Pu literal 0 HcmV?d00001 diff --git a/ui-ngx/src/assets/locale/locale.constant-ca_ES.json b/ui-ngx/src/assets/locale/locale.constant-ca_ES.json index f52ed102f2..db7d6b06ce 100644 --- a/ui-ngx/src/assets/locale/locale.constant-ca_ES.json +++ b/ui-ngx/src/assets/locale/locale.constant-ca_ES.json @@ -3646,8 +3646,7 @@ "assign-rulechains": "Assignar cadenes de regles", "delete-rulechains": "Eliminar cadenes de regles", "unassign-rulechain": "Anul·lar assignació de cadena de regles", - "unassign-rulechains-from-edge-action-title": "Anul·lar assignació {count, plural, =1 {1 cadena de regles} other {# cadenes de regles} } des vores", - "assign-new-rulechain": "Assignar nova cadena de regles" + "unassign-rulechains-from-edge-action-title": "Anul·lar assignació {count, plural, =1 {1 cadena de regles} other {# cadenes de regles} } des vores" }, "rulenode": { "details": "Detalls", @@ -5692,7 +5691,6 @@ "show-empty-space-hidden-action": "Mostrar espai buit en lloc de cel·la oculta", "dont-reserve-space-hidden-action": "No reserveu espai per als botons en cel·la oculta", "display-timestamp": "Mostra columna timestamp", - "display-milliseconds": "Mostrar mil·lisegons", "display-pagination": "Mostrar pàgines", "default-page-size": "Mida de pàgina per defecte", "use-entity-label-tab-name": "Usar etiqueta important al nom de la taula", diff --git a/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json b/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json index c0950bb047..7402aedc5c 100644 --- a/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json +++ b/ui-ngx/src/assets/locale/locale.constant-cs_CZ.json @@ -2411,7 +2411,6 @@ "search": "Vyhledat řetězy pravidel", "selected-rulechains": "Vybráno { count, plural, =1 {1 řetězů pravidel} other {# řetězů pravidel} }", "open-rulechain": "Otevřít řetěz pravidel", - "assign-new-rulechain": "Přiřadit nový řetěz pravidel", "edge-template-root": "Hlavní šablona", "assign-to-edge": "Přiřadit k edge", "edge-rulechain": "Řetěz pravidel edge", diff --git a/ui-ngx/src/assets/locale/locale.constant-de_DE.json b/ui-ngx/src/assets/locale/locale.constant-de_DE.json index 87579470d2..582e3e2902 100644 --- a/ui-ngx/src/assets/locale/locale.constant-de_DE.json +++ b/ui-ngx/src/assets/locale/locale.constant-de_DE.json @@ -19,6 +19,7 @@ "suspend": "Unterbrechen", "save": "Speichern", "saveAs": "Speichern unter", + "move": "Verschieben", "cancel": "Abbrechen", "ok": "OK", "delete": "Löschen", @@ -27,18 +28,20 @@ "no": "Nein", "update": "Aktualisieren", "remove": "Löschen", - "select": "Auswählen", "search": "Suche", "clear-search": "Suchanfrage löschen", "assign": "Zuordnen", "unassign": "Zuordnung aufheben", "share": "Teilen", "make-private": "Privat machen", + "make-public": "Öffentlich machen", "apply": "Anwenden", "apply-changes": "Änderungen übernehmen", "edit-mode": "Bearbeitungsmodus", "enter-edit-mode": "Zum Bearbeitungsmodus wechseln", "decline-changes": "Änderungen nicht übernehmen", + "open": "Öffnen", + "decline": "Verwerfen", "close": "Schließen", "back": "Zurück", "run": "Ausführen", @@ -56,16 +59,27 @@ "import": "Importieren", "export": "Exportieren", "share-via": "Teilen mit {{provider}}", + "select": "Auswählen", "continue": "Fortsetzen", "discard-changes": "Änderungen verwerfen", "download": "Download", + "next": "Nächste", "next-with-label": "Nächste: {{label}}", "read-more": "Mehr dazu", "hide": "Verstecken", "done": "Erledigt", "print": "Drucken", "restore": "Wiederherstellen", - "confirm": "Bestätigen" + "confirm": "Bestätigen", + "more": "Mehr", + "less": "Weniger", + "skip": "Überspringen", + "send": "Senden", + "reset": "Zurücksetzen", + "show-more": "Zeige mehr", + "dont-show-again": "Nicht wieder anzeigen", + "see-documentation": "Siehe Dokumentation", + "clear": "Leeren" }, "aggregation": { "aggregation": "Aggregation", @@ -80,9 +94,11 @@ "none": "kein Wert" }, "admin": { + "settings": "Einstellungen", "general": "Allgemein", "general-settings": "Allgemeine Einstellungen", "home-settings": "Home Einstellungen", + "home": "Home", "outgoing-mail": "E-Mail Versand", "outgoing-mail-settings": "Konfiguration des Postausgangsservers", "system-settings": "Systemeinstellungen", @@ -103,7 +119,7 @@ "timeout-required": "Wartezeit ist erforderlich.", "timeout-invalid": "Das ist keine gültige Wartezeit.", "enable-tls": "TLS aktivieren", - "tls-version" : "TLS-Version", + "tls-version": "TLS-Version", "enable-proxy": "Proxy aktivieren", "proxy-host": "Proxy Host", "proxy-host-required": "Proxy Host ist erforderlich.", @@ -114,8 +130,21 @@ "proxy-password": "Proxy Passwort", "change-password": "Passwort ändern", "send-test-mail": "Test E-Mail senden", + "use-system-mail-settings": "System E-Mail-Server Einstellungen benutzen", + "mail-templates": "E-Mail Vorlagen", + "mail-template-settings": "Einstellungen E-Mail Vorlagen", + "use-system-mail-template-settings": "System E-Mail Vorlagen benutzen", + "mail-template": { + "mail-template": "E-Mail Vorlage", + "test": "E-Mail Nachricht testen", + "activation": "Nachricht Benutzerkontoaktivierung", + "account-activated": "Nachricht Benutzerkonto aktiviert" + }, + "mail-subject": "E-Mail Betreff", + "mail-body": "E-Mail Nachricht", "sms-provider": "SMS Anbieter", "sms-provider-settings": "SMS Anbieter Einstellungen", + "use-system-sms-settings": "System SMS Anbieter benutzen", "sms-provider-type": "SMS Anbieter Typ", "sms-provider-type-required": "SMS Anbieter Typ ist erforderlich.", "sms-provider-type-aws-sns": "Amazon SNS", @@ -138,6 +167,7 @@ "password-expiration-period-days-range": "Die Gültigkeitsdauer des Passworts in Tagen kann nicht negativ sein", "password-reuse-frequency-days": "Häufigkeit der Kennwortwiederverwendung in Tagen", "password-reuse-frequency-days-range": "Die Häufigkeit der Kennwortwiederverwendung in Tagen kann nicht negativ sein", + "allow-whitespace": "Leerzeichen erlauben", "general-policy": "Allgemeine Politik", "max-failed-login-attempts": "Maximale Anzahl fehlgeschlagener Anmeldeversuche, bevor das Konto gesperrt wird", "minimum-max-failed-login-attempts-range": "Die maximale Anzahl fehlgeschlagener Anmeldeversuche kann nicht negativ sein", @@ -146,11 +176,14 @@ "alarm": { "alarm": "Alarm", "alarms": "Alarme", + "all-alarms": "Alle Alarme", "select-alarm": "Alarm auswählen", "no-alarms-matching": "Keine passenden Alarme zu '{{entity}}' wurden gefunden.", "alarm-required": "Alarm ist erforderlich", + "alarm-filter": "Alarmfilter", + "filter": "Filter", "alarm-status": "Alarm Status", - "alarm-status-list": "Alarm Status Liste", + "alarm-status-list": "Alarm Statusliste", "any-status": "Jeder Status", "search-status": { "ANY": "Jeder", @@ -178,6 +211,7 @@ "end-time": "Endzeit", "ack-time": "Bestätigungszeit", "clear-time": "Zeit gelöscht", + "duration": "Dauer", "alarm-severity-list": "Alarm Schwere Liste", "any-severity": "Jede Schwere", "severity-critical": "Kritisch", @@ -187,6 +221,7 @@ "severity-indeterminate": "Unbestimmt", "acknowledge": "Bestätigen", "clear": "Löschen", + "delete": "Löschen", "search": "Alarme suchen", "selected-alarms": "{ count, plural, =1 {1 Alarm} other {# Alarme} } ausgewählt", "no-data": "Keine Daten zum Anzeigen", @@ -197,11 +232,18 @@ "aknowledge-alarms-text": "Sind Sie sicher, dass Sie { count, plural, =1 {1 Alarm} other {# Alarme} } bestätigen möchten?", "aknowledge-alarm-title": "Alarm bestätigen", "aknowledge-alarm-text": "Möchten Sie den Alarm wirklich bestätigen?", + "selected-alarms-are-acknowledged": "Ausgewählte Alarme wurden bereits bestätigt", "clear-alarms-title": "{ count, plural, =1 {1 Alarm} other {# Alarme} } löschen", "clear-alarms-text": "Möchten Sie wirklich { count, plural, =1 {1 Alarm} other {# Alarme} } löschen?", "clear-alarm-title": "Alarm löschen", "clear-alarm-text": "Möchten Sie den Alarm wirklich löschen?", - "alarm-status-filter": "Alarm Status Filter" + "delete-alarms-title": "Lösche { count, plural, =1 {1 Alarm} other {# Alarme} }", + "delete-alarms-text": "Sind Sie sicher { count, plural, =1 {1 Alarm} other {# Alarme} } zu löschen?", + "selected-alarms-are-cleared": "Ausgewählte Alarme wurden bereits gelöscht", + "alarm-status-filter": "Alarm Status Filter", + "alarm-filter-title": "Alarmfilter", + "assigned": "Zugewiesen", + "filter-title": "Filter" }, "alias": { "add": "Alias hinzufügen", @@ -228,14 +270,14 @@ "filter-type-edge-type-description": "Rand vom Typ '{{edgeTypes}}'", "filter-type-relations-query": "Beziehungsabfrage", "filter-type-relations-query-description": "{{entities}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", + "filter-type-edge-search-query": "Edge-Abfrage", + "filter-type-edge-search-query-description": "Edge vom Typ {{edgeTypes}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", "filter-type-asset-search-query": "Objektabfrage", "filter-type-asset-search-query-description": "Objekte vom Typ {{assetTypes}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", "filter-type-device-search-query": "Geräteabfrage", "filter-type-device-search-query-description": "Geräte vom Typ {{deviceTypes}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", "filter-type-entity-view-search-query": "Entitätsansichtsabfrage", "filter-type-entity-view-search-query-description": "Entitätsansichten vom Typ {{entityViewTypes}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", - "filter-type-edge-search-query": "Randabfrage", - "filter-type-edge-search-query-description": "Rand vom Typ {{edgeTypes}} mit {{relationType}} Beziehung {{direction}} {{rootEntity}}", "entity-filter": "Entitätsfilter", "resolve-multiple": "Als mehrere Entitäten auflösen", "filter-type": "Filtertyp", @@ -254,11 +296,16 @@ "any-relation": "Jede Beziehung" }, "asset": { + "all": "Alle", + "all-assets": "Alle Objekte", + "groups": "Gruppen", + "shared": "Geteilt", "asset": "Objekt", "assets": "Objekte", "management": "Objektverwaltung", "view-assets": "Objekte anzeigen", "add": "Objekt hinzufügen", + "asset-type-max-length": "Objekttyp sollte kürzer als 256 Zeichen sein", "assign-to-customer": "Einem Kunden zuordnen", "assign-asset-to-customer": "Objekte dem Kunden zuordnen", "assign-asset-to-customer-text": "Bitte wählen Sie die Objekte aus, die dem Kunden zugeordnet werden sollen", @@ -281,6 +328,8 @@ "asset-types": "Objekttypen", "name": "Name", "name-required": "Name ist erforderlich.", + "name-max-length": "Name sollte weniger als 256 Zeichen sein", + "label-max-length": "Label sollte weniger als 256 Zeichen sein", "description": "Beschreibung", "type": "Typ", "type-required": "Typ ist erforderlich.", @@ -290,6 +339,7 @@ "asset-details": "Objektdetails", "assign-assets": "Objekte zuordnen", "assign-assets-text": "Kunden { count, plural, =1 {1 Objekt} other {# Objekte} } zuordnen", + "assign-asset-to-edge-text":"Bitte wählen Sie die Objekte aus, die dem Edge zugeordnet werden sollen", "delete-assets": "Objekte löschen", "unassign-assets": "Objektzuordnungen aufheben", "unassign-assets-action-title": "Kunden { count, plural, =1 {1 Objektzuordnung} other {# Objektzuordnungen} } aufheben", @@ -316,7 +366,6 @@ "name-starts-with": "Name des Objekts beginnt mit", "label": "Bezeichnung", "assign-asset-to-edge": "Objekte dem Rand zuordnen", - "assign-asset-to-edge-text":"Bitte wählen Sie die Objekte aus, die dem Rand zugeordnet werden sollen", "unassign-asset-from-edge": "Objekte von Rand entfernen", "unassign-asset-from-edge-title": "Sind Sie sicher, dass Sie die Zuordnung für das Objekt '{{assetName}}' aufheben möchten?", "unassign-asset-from-edge-text": "Nach Bestätigung wird die Zuordnung des Objekts aufgehoben und es ist für den Kunden nicht mehr zugänglich.", @@ -327,6 +376,7 @@ "attribute": { "attributes": "Eigenschaften", "latest-telemetry": "Neueste Telemetrie", + "no-latest-telemetry": "Keine Telemetriedaten", "attributes-scope": "Entitätseigenschaftsbereich", "scope-telemetry": "Telemetrie", "scope-latest-telemetry": "Neueste Telemetrie", @@ -334,11 +384,15 @@ "scope-server": "Server Eigenschaften", "scope-shared": "Gemeinsame Eigenschaften", "add": "Eigenschaft hinzufügen", + "add-attribute-prompt": "Bitte Attribut hinzufügen", "key": "Schlüssel", + "key-max-length": "Der Schlüssel sollte weniger als 256 Zeichen haben", "last-update-time": "Datum der letzten Aktualisierung", "key-required": "Eigenschaftsschlüssel ist erforderlich.", "value": "Wert", "value-required": "Eigenschaftswert ist erforderlich.", + "telemetry-key-required": "Telemetrieschlüssel ist erforderlich", + "telemetry-value-required": "Telemetriewert ist erforderlich", "delete-attributes-title": "Sind Sie sicher, dass Sie { count, plural, =1 {1 Eigenschaft} other {# Eigenschaften} } löschen möchten?", "delete-attributes-text": "Seien Sie vorsichtig, nach der Bestätigung werden alle ausgewählten Eigenschaften entfernt.", "delete-attributes": "Eigenschaften löschen", @@ -350,7 +404,12 @@ "add-to-dashboard": "Zum Dashboard hinzufügen", "add-widget-to-dashboard": "Widget zum Dashboard hinzufügen", "selected-attributes": "{ count, plural, =1 {1 Eigenschaft} other {# Eigenschaften} } ausgewählt", - "selected-telemetry": "{ count, plural, =1 {1 Telemetrieeinheit } other {# Telemetrieeinheiten} } ausgewählt" + "selected-telemetry": "{ count, plural, =1 {1 Telemetrieeinheit } other {# Telemetrieeinheiten} } ausgewählt", + "no-attributes-text": "Keine Attribute gefunden", + "no-telemetry-text": "Keine Telemetriedaten gefunden", + "copy-key": "Schlüssel kopieren", + "add-telemetry": "Telemetriedaten hinzufügen", + "copy-value": "Wert kopieren" }, "audit-log": { "audit": "Audit", @@ -371,17 +430,27 @@ "type-credentials-updated": "Anmeldeinformationen wurden aktualisiert", "type-assigned-to-customer": "Kunden Zuordnung", "type-unassigned-from-customer": "Kunden Zuordnung aufgehoben", - "type-assigned-to-edge": "Rand Zuordnung", - "type-unassigned-from-edge": "Rand Zuordnung aufgehoben", + "type-assigned-to-edge": "Zum Edge hinzugefügt", + "type-unassigned-from-edge": "Vom Edge entfernt", "type-activated": "Aktiviert", "type-suspended": "Ausgesetzt", "type-credentials-read": "Anmeldeinformationen gelesen", "type-attributes-read": "Eigenschaften gelesen", + "type-added-to-entity-group": "Zur Gruppe hinzugefügt", + "type-removed-from-entity-group": "Aus der Gruppe entfernt", "type-relation-add-or-update": "Beziehung aktualisiert", "type-relation-delete": "Beziehung gelöscht", "type-relations-delete": "Alle Beziehungen gelöscht", "type-alarm-ack": "Bestätigt", "type-alarm-clear": "Gelöscht", + "type-alarm-assign": "Zugeweisen", + "type-alarm-unassign": "nicht zugewiesen", + "type-added-comment": "Kommentar hinzugefügt", + "type-updated-comment": "Kommentar aktualisiert", + "type-deleted-comment": "Kommentar gelöscht", + "type-rest-api-rule-engine-call": "Regelkette REST API Aufruf", + "type-made-public": "Öffentlich machen", + "type-made-private": "Privat machen", "type-login": "Anmeldung", "type-logout": "Ausloggen", "type-lockout": "Aussperrung", @@ -392,7 +461,15 @@ "action-data": "Aktionsdaten", "failure-details": "Fehlerdetails", "search": "Audit-Protokolle durchsuchen", - "clear-search": "Suche leeren" + "clear-search": "Suche leeren", + "type-assigned-from-tenant": "Vom Tenant zugewiesen", + "type-assigned-to-tenant": "Dem Tenant zugewiesen", + "type-provision-success": "Gerätebereitstellung erfolgreich", + "type-provision-failure": "Gerätebereitstellung fehlgeschlagen", + "type-timeseries-updated": "Telemetriedaten aktualisiert", + "type-timeseries-deleted": "Telemetriedaten gelöscht", + "type-owner-changed": "Besitzer wurde gewechselt", + "type-sms-sent": "SMS gesendet" }, "confirm-on-exit": { "message": "Sie haben nicht gespeicherte Änderungen. Möchten Sie diese Seite wirklich verlassen?", @@ -409,7 +486,10 @@ "address2": "Adresse 2", "phone": "Telefon", "email": "E-Mail", - "no-address": "Keine Adresse" + "no-address": "Keine Adresse", + "state-max-length": "Staat sollte weniger als 256 Zeichen haben", + "phone-max-length": "Telefonnummer sollte weniger als 256 Zeichen haben", + "city-max-length": "Ort sollte weniger als 256 Zeichen haben" }, "common": { "username": "Benutzername", @@ -417,7 +497,12 @@ "enter-username": "Benutzername eingeben", "enter-password": "Passwort eingeben", "enter-search": "Suche eingeben", - "created-time": "Erstellungszeit" + "created-time": "Erstellungszeit", + "loading": "wird geladen...", + "proceed": "Fortfahren", + "open-details-page": "Detailseite öffnen", + "not-found": "Nicht gefunden", + "documentation": "Dokumentation" }, "content-type": { "json": "Json", @@ -425,6 +510,11 @@ "binary": "Binär (Base64)" }, "customer": { + "all": "Alle", + "all-customers": "Alle Kunden", + "groups": "Gruppen", + "shared": "Geteilt", + "hierarchy": "Hierarchie", "customer": "Kunde", "customers": "Kunden", "management": "Kundenverwaltung", @@ -437,7 +527,6 @@ "public-devices": "Öffentliche Geräte", "public-assets": "Öffentliche Objekte", "public-entity-views": "Öffentliche Entitätsansichten", - "public-edges": "Öffentliche Rand", "add": "Kunde hinzufügen", "delete": "Kunde löschen", "manage-customer-users": "Kundenbenutzer verwalten", @@ -446,7 +535,6 @@ "manage-public-devices": "Öffentliche Geräte verwalten", "manage-public-dashboards": "Öffentliche Dashboards verwalten", "manage-customer-assets": "Kundenobjekte verwalten", - "manage-customer-edges": "Randobjekte verwalten", "manage-public-assets": "Öffentliche Objekte verwalten", "manage-public-edges": "Öffentliche Rand verwalten", "add-customer-text": "Neuen Kunden hinzufügen", @@ -463,6 +551,7 @@ "manage-dashboards": "Dashboards verwalten", "title": "Titel", "title-required": "Titel ist erforderlich.", + "title-max-length": "Titel sollte weniger asl 256 Zeichen haben", "description": "Beschreibung", "details": "Details", "events": "Ereignisse", @@ -1463,7 +1552,6 @@ "management": "Regelverwaltung", "debug-mode": "Modus zur Fehlersuche", "assign-rulechains": "Regelketten zuweisen", - "assign-new-rulechain": "Neues Regelkette zuweisen", "delete-rulechains": "Regelketten löschen", "unassign-rulechain": "Nicht zugeordnete Regelkette", "unassign-rulechains": "Nicht zugeordnete Regelketten", @@ -1588,26 +1676,98 @@ "hours": "Stunden", "minutes": "Minuten", "seconds": "Sekunden", - "advanced": "Erweitert" + "advanced": "Erweitert", + "predefined": { + "yesterday": "Gestern", + "day-before-yesterday": "Vorgestern", + "this-day-last-week": "Dieser Tag letzte Woche", + "previous-week": "Letzte Woche (So - Sa)", + "previous-week-iso": "Letzte Woche (Mo - So)", + "previous-month": "Letzter Monat", + "previous-quarter": "Letztes Quartal", + "previous-half-year": "Letztes Halbjahr", + "previous-year": "Letztes Jahr", + "current-hour": "Aktuelle Stunde", + "current-day": "Aktueller Tag", + "current-day-so-far": "Aktueller Tag bisher", + "current-week": "Aktuelle Wiche (So - Sa)", + "current-week-iso": "Aktuelle Woche (Mo - So)", + "current-week-so-far": "Aktuelle Woche bisher (So - Sa)", + "current-week-iso-so-far": "Aktuelle Woche bisher (Mo - So)", + "current-month": "Aktueller Monat", + "current-month-so-far": "Aktueller Monat bisher", + "current-quarter": "Aktuelles Quartal", + "current-quarter-so-far": "Aktuelles Quartal bisher", + "current-half-year": "Aktuelles Halbjahr", + "current-half-year-so-far": "Aktuelles Halbjahr bisher", + "current-year": "Aktuelles Jahr", + "current-year-so-far": "Aktuelles Jahr bisher" + } + }, + "timeunit": { + "milliseconds": "Millisekunden", + "seconds": "Sekunden", + "minutes": "Minuten", + "hours": "Stunden", + "days": "Tage" }, "timewindow": { + "timewindow": "Zeitfenster", + "years": "{ years, plural, =1 { Jahr } other {# Jahre } }", + "years-short": "{{ years }}J", + "months": "{ months, plural, =1 { Monat } other {# Monate } }", + "months-short": "{{ months }}M", + "weeks": "{ weeks, plural, =1 { Woche } other {# Wochen } }", + "weeks-short": "{{ weeks }}W", "days": "{ days, plural, =1 { Tag } other {# Tage } }", + "days-short": "{{ days }}T", "hours": "{ hours, plural, =0 { Stunde } =1 {1 Stunde } other {# Stunden } }", + "hr": "{{ hr }} Std", + "hr-short": "{{ hr }}S", "minutes": "{ minutes, plural, =0 { Minute } =1 {1 Minute } other {# Minuten } }", + "min": "{{ min }} Min", + "min-short": "{{ min }}m", "seconds": "{ seconds, plural, =0 { Sekunde } =1 {1 Sekunde } other {# Sekunden } }", + "sec": "{{ sec }} Sek", + "sec-short": "{{ sec }}s", + "short": { + "days": "{ days, plural, =1 {1 Tag } other {# Tage } }", + "hours": "{ hours, plural, =1 {1 Stunde } other {# Stunden } }", + "minutes": "{{minutes}} Min ", + "seconds": "{{seconds}} Sek " + }, "realtime": "Echtzeit", "history": "Historie", "last-prefix": "letzte", "period": "von {{ startTime }} bis {{ endTime }}", "edit": "Zeitfenster bearbeiten", "date-range": "Datumsbereich", + "for-all-time": "Für immer", "last": "Letzte", - "time-period": "Zeitfenster" + "time-period": "Zeitfenster", + "hide": "Verstecken", + "interval": "Intervall", + "just-now": "Soeben", + "just-now-lower": "soeben", + "ago": "vor", + "style": "Zeitfenster Style", + "icon": "Symbol", + "icon-position": "Position Symbol", + "icon-position-left": "Links", + "icon-position-right": "Rechts", + "font": "Schriftart", + "color": "Farbe", + "displayTypePrefix": "Echtzeit-/Verlaufspräfix anzeigen", + "preview": "Vorschau" }, "user": { - "user": "User", - "users": "Users", - "customer-users": "Kunden Users", + "all": "Alle", + "all-users": "Alle Benutzer", + "groups": "Gruppen", + "user": "Benutzer", + "users": "Benutzer", + "management": "Benutzerverwaltung", + "customer-users": "Kunden-Benutzer", "tenant-admins": "Mandanten-Administratoren", "sys-admin": "System-Administrator", "tenant-admin": "Mandanten-Administrator", @@ -1618,6 +1778,7 @@ "add-user-text": "Neuen Benutzer hinzufügen", "no-users-text": "Keine Benutzer gefunden", "user-details": "Benutzer-Details", + "delete-users": "Benutzer löschen", "delete-user-title": "Möchten Sie den Benutzer '{{userEmail}}' wirklich löschen?", "delete-user-text": "Vorsicht, nach Bestätigung werden der Benutzer und alle zugehörigen Daten gelöscht.", "delete-users-title": "Sind Sie sicher, dass Sie { count, plural, =1 {1 Benutzer} other {# Benutzer} } löschen möchten??", @@ -1649,7 +1810,11 @@ "disable-account": "Benutzerkonto deaktivieren", "enable-account": "Benutzerkonto aktivieren", "enable-account-message": "Benutzerkonto wurde erfolgreich aktiviert!", - "disable-account-message": "Benutzerkonto wurde erfolgreich deaktiviert!" + "disable-account-message": "Benutzerkonto wurde erfolgreich deaktiviert!", + "copyId": "Benutzer-Id kopieren", + "idCopiedMessage": "Benutzer-Id in die Zwischenablage kopiert", + "user-list": "Benutzerliste", + "user-list-required": "Benutzerliste ist erforderlich" }, "value": { "type": "Wertetyp", @@ -1813,6 +1978,27 @@ }, "widgets": { "date-range-navigator": { + "date-range-picker-settings": "Einstellungen Datumsbereichsauswahl", + "hide-date-range-picker": "Datumsbereichsauswahl verstecken", + "picker-one-panel": "Datumsbereichsauswahl in einem Bereich", + "picker-auto-confirm": "Automatische Bestätigung der Datumsbereichsauswahl", + "picker-show-template": "Vorlage für die Anzeige der Datumsbereichsauswahl", + "first-day-of-week": "Erster Tag der Woche", + "interval-settings": "Intervalleinstellungen", + "hide-interval": "Intervall verstecken", + "initial-interval": "Anfangsintervall", + "interval-hour": "Stunde", + "interval-day": "Tag", + "interval-week": "Woche", + "interval-two-weeks": "2 Wochen", + "interval-month": "Monat", + "interval-three-months": "3 Monate", + "interval-six-months": "6 Monate", + "step-settings": "Schritteinstellungen", + "hide-step-size": "Schrittweite verstecken", + "initial-step-size": "Anfangsschrittweite", + "hide-labels": "Beschriftung verstecken", + "use-session-storage": "Sessionspeicher verwenden", "localizationMap": { "Sun": "So.", "Mon": "Mo.", @@ -1897,6 +2083,7 @@ }, "icon": { "icon": "Symbol", + "icons": "Symbole", "select-icon": "Symbol auswählen", "material-icons": "Material-Symbole", "show-all": "Alle Symbole anzeigen" 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 7937b197f3..34109326b7 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -77,7 +77,10 @@ "show-more": "Show more", "dont-show-again": "Do not show again", "see-documentation": "See documentation", - "clear": "Clear" + "clear": "Clear", + "upload": "Upload", + "delete-anyway": "Delete anyway", + "delete-selected": "Delete selected" }, "aggregation": { "aggregation": "Aggregation", @@ -179,7 +182,10 @@ "password-policy": "Password policy", "minimum-password-length": "Minimum password length", "minimum-password-length-required": "Minimum password length is required", - "minimum-password-length-range": "Minimum password length should be in a range from 5 to 50", + "minimum-password-length-range": "Minimum password length should be in a range from 6 to 50", + "maximum-password-length": "Maximum password length", + "maximum-password-length-min": "Maximum password length should be at least 6", + "maximum-password-length-less-min": "Maximum password length should be greater than minimum length", "minimum-uppercase-letters": "Minimum number of uppercase letters", "minimum-uppercase-letters-range": "Minimum number of uppercase letters can't be negative", "minimum-lowercase-letters": "Minimum number of lowercase letters", @@ -193,6 +199,8 @@ "password-reuse-frequency-days": "Password reuse frequency in days", "password-reuse-frequency-days-range": "Password reuse frequency in days can't be negative", "allow-whitespace": "Allow whitespace", + "force-reset-password-if-no-valid": "Force to reset password if not valid", + "force-reset-password-if-no-valid-hint": "Please be careful when enabling this feature: it will require users with not valid password to reset their password via email.", "general-policy": "General policy", "max-failed-login-attempts": "Maximum number of failed login attempts, before account is locked", "minimum-max-failed-login-attempts-range": "Maximum number of failed login attempts can't be negative", @@ -664,7 +672,7 @@ "asset-type": "Asset type", "asset-type-required": "Asset type is required.", "select-asset-type": "Select asset type", - "enter-asset-type": "Enter asset type", + "enter-asset-type": "Enter asset profile", "any-asset": "Any asset", "no-asset-types-matching": "No asset types matching '{{entitySubtype}}' were found.", "asset-type-list-empty": "No asset types selected.", @@ -1178,6 +1186,7 @@ "hide-details": "Hide details", "select-state": "Select target state", "state-controller": "State controller", + "state-controller-default": "static (deprecated)", "search": "Search dashboards", "selected-dashboards": "{ count, plural, =1 {1 dashboard} other {# dashboards} } selected", "home-dashboard": "Home dashboard", @@ -1188,7 +1197,8 @@ "assign-dashboard-to-edge": "Assign Dashboard(s) To Edge", "assign-dashboard-to-edge-text": "Please select the dashboards to assign to the edge", "non-existent-dashboard-state-error": "Dashboard state with id \"{{ stateId }}\" is not found", - "edit-mode": "Edit mode" + "edit-mode": "Edit mode", + "duplicate-state-action": "Duplicate state" }, "datakey": { "settings": "Settings", @@ -2017,6 +2027,7 @@ "sync-process-started-successfully": "Sync process started successfully!", "missing-related-rule-chains-title": "Edge has missing related rule chain(s)", "missing-related-rule-chains-text": "Assigned to edge rule chain(s) use rule nodes that forward message(s) to rule chain(s) that are not assigned to this edge.

List of missing rule chain(s):
{{missingRuleChains}}", + "upgrade-instructions": "Upgrade Instructions", "widget-datasource-error": "This widget supports only EDGE entity datasource" }, "edge-event": { @@ -2198,6 +2209,8 @@ "list-of-edges": "{ count, plural, =1 {One edge} other {List of # edges} }", "edge-name-starts-with": "Edges whose names start with '{{prefix}}'", "type-tb-resource": "Resource", + "type-tb-resources": "Resources", + "list-of-tb-resources": "{ count, plural, =1 {One resource} other {List of # resources} }", "type-ota-package": "OTA package", "type-rpc": "RPC", "type-queue": "Queue", @@ -2686,7 +2699,12 @@ "rpc-command-result": "Response", "rpc-command-edit-params": "Edit parameters", "gateway-configuration": "General Configuration", - "docker-label": "In order to run ThingsBoard IoT gateway in docker with credentials for this device you can use the following commands.", + "docker-label": "Use the following instruction to run IoT Gateway in in Docker compose with credentials for selected device", + "install-docker-compose": "Use the instructions to download, install and setup docker compose", + "download-configuration-file": "Download configuration file", + "download-docker-compose": "Download docker-compose.yml for your gateway", + "launch-gateway": "Launch gateway", + "launch-docker-compose": "Start the gateway using the following command in the terminal from folder with docker-compose.yml file", "create-new-gateway": "Create a new gateway", "create-new-gateway-text": "Are you sure you want create a new gateway with name: '{{gatewayName}}'?", "created-time": "Created time", @@ -3027,6 +3045,59 @@ "browse-file": "Browse file", "browse-files": "Browse files" }, + "image": { + "gallery": "Image gallery", + "search": "Search image", + "selected-images": "{ count, plural, =1 {1 image} other {# images} } selected", + "created-time": "Created time", + "name": "Name", + "name-required": "Name is required.", + "resolution": "Resolution", + "size": "Size", + "system": "System", + "download-image": "Download image", + "export-image": "Export image to JSON", + "import-image": "Import image from JSON", + "upload-image": "Upload image", + "edit-image": "Edit image", + "image-details": "Image details", + "no-images": "No images found", + "delete-image": "Delete image", + "delete-image-title": "Are you sure you want to delete image '{{imageTitle}}'?", + "delete-image-text": "Be careful, after the confirmation image will become unrecoverable.", + "delete-images-title": "Are you sure you want to delete { count, plural, =1 {1 image} other {# images} }?", + "delete-images-text": "Be careful, after the confirmation all selected images will be removed and all related data will become unrecoverable.", + "list-mode": "List view", + "grid-mode": "Grid view", + "image-preview": "Image preview", + "update-image": "Update image", + "export-failed-error": "Unable to export image: {{error}}", + "image-json-file": "Image JSON file", + "invalid-image-json-file-error": "Unable to import image from JSON: Invalid image JSON data structure.", + "image-is-in-use": "Image is used by other entities", + "images-are-in-use": "Images are used by other entities", + "image-is-in-use-text": "The image '{{title}}' was not deleted because it is used by the following entities:", + "images-are-in-use-text": "Not all images have been deleted because they are used by other entities.
You can view referenced entities by clicking the References button in the corresponding image row.
If you still want to delete these images, select them in the table below and click the Delete selected button.", + "delete-image-in-use-text": "If you still want to delete the image, click the Delete anyway button.", + "system-entities": "System entities:", + "entities": "entities:", + "references": "References", + "include-system-images": "Include system images", + "clear-image": "Clear image", + "no-image": "No image", + "no-image-selected": "No image selected", + "browse-from-gallery": "Browse from gallery", + "set-link": "Set link", + "image-link": "Image link", + "link": "Link", + "copy-image-link": "Copy image link", + "embed-image": "Embed image", + "embed-to-html": "Embed to HTML", + "embed-to-html-hint": "This feature will make link available to any unauthorized user.", + "embed-to-html-text": "Using the following code snippet, you may embed an image into the components based on the plain HTML.
Such components include HTML card widgets, cell content functions, etc.", + "embed-to-angular-template": "Embed to Angular HTML template", + "embed-to-angular-template-text": "Using the following code snippet, you may embed an image into the Angular HTML template.
Such components include the Markdown widget, HTML section in the widget editor, custom actions, etc." + }, "image-input": { "drop-images-or": "Drag and drop an images or", "drag-and-drop": "Drag & Drop", @@ -3175,7 +3246,9 @@ "weeks": "(week ago)", "months": "(month ago)", "years": "(year ago)" - } + }, + "label": "Label", + "value": "Value" }, "login": { "login": "Login", @@ -3365,15 +3438,13 @@ "recipient-type": { "affected-tenant-administrators": "Affected tenant administrators", "affected-user": "Affected user", - "affected-user-hint": "Affected user hint", "all-users": "All users", "customer-users": "Customer users", "system-administrators": "System administrators", "tenant-administrators": "Tenant administrators", "user-filters": "User filter", "user-list": "User list", - "users-entity-owner": "Users of the entity owner", - "users-entity-owner-hint": "Users of the entity owner hint" + "users-entity-owner": "Users of the entity owner" }, "recipients": "Recipients", "notification-recipients": "Notifications / Recipients", @@ -3485,69 +3556,70 @@ } }, "ota-update": { - "add": "Add package", - "assign-firmware": "Assigned firmware", - "assign-firmware-required": "Assigned firmware is required", - "assign-software": "Assigned software", - "assign-software-required": "Assigned software is required", - "auto-generate-checksum": "Auto-generate checksum", - "checksum": "Checksum", - "checksum-hint": "If checksum is empty, it will be generated automatically", - "checksum-algorithm": "Checksum algorithm", - "checksum-copied-message": "Package checksum has been copied to clipboard", - "change-firmware": "Change of the firmware may cause update of { count, plural, =1 {1 device} other {# devices} }.", - "change-software": "Change of the software may cause update of { count, plural, =1 {1 device} other {# devices} }.", - "chose-compatible-device-profile": "The uploaded package will be available only for devices with the chosen profile.", - "chose-firmware-distributed-device": "Choose firmware that will be distributed to the devices", - "chose-software-distributed-device": "Choose software that will be distributed to the devices", - "content-type": "Content type", - "copy-checksum": "Copy checksum", - "copy-direct-url": "Copy direct URL", - "copyId": "Copy package Id", - "copied": "Copied!", - "delete": "Delete package", - "delete-ota-update-text": "Be careful, after the confirmation the OTA update will become unrecoverable.", - "delete-ota-update-title": "Are you sure you want to delete the OTA update '{{title}}'?", - "delete-ota-updates-text": "Be careful, after the confirmation all selected OTA updates will be removed.", - "delete-ota-updates-title": "Are you sure you want to delete { count, plural, =1 {1 OTA update} other {# OTA updates} }?", - "description": "Description", - "direct-url": "Direct URL", - "direct-url-copied-message": "Package direct URL has been copied to clipboard", - "direct-url-required": "Direct URL is required", - "download": "Download package", - "drop-file": "Drop a package file or click to select a file to upload.", - "drop-package-file-or": "Drag and drop a package file or", - "file-name": "File name", - "file-size": "File size", - "file-size-bytes": "File size in bytes", - "idCopiedMessage": "Package Id has been copied to clipboard", - "no-firmware-matching": "No compatible Firmware OTA Update packages matching '{{entity}}' were found.", - "no-firmware-text": "No compatible Firmware OTA Update packages provisioned.", - "no-packages-text": "No packages found", - "no-software-matching": "No compatible Software OTA Update packages matching '{{entity}}' were found.", - "no-software-text": "No compatible Software OTA Update packages provisioned.", - "ota-update": "OTA update", - "ota-update-details": "OTA update details", - "ota-updates": "OTA updates", - "package-type": "Package type", - "packages-repository": "Packages repository", - "search": "Search packages", - "selected-package": "{ count, plural, =1 {1 package} other {# packages} } selected", - "title": "Title", - "title-required": "Title is required.", - "title-max-length": "Title should be less than 256", - "types": { - "firmware": "Firmware", - "software": "Software" - }, - "upload-binary-file": "Upload binary file", - "use-external-url": "Use external URL", - "version": "Version", - "version-required": "Version is required.", - "version-tag": "Version tag", - "version-tag-hint": "Custom tag should match the package version reported by your device.", - "version-max-length": "Version should be less than 256", - "warning-after-save-no-edit": "Once the package is uploaded, you will not be able to modify title, version, device profile and package type." + "add": "Add package", + "assign-firmware": "Assigned firmware", + "assign-firmware-required": "Assigned firmware is required", + "assign-software": "Assigned software", + "assign-software-required": "Assigned software is required", + "auto-generate-checksum": "Auto-generate checksum", + "checksum": "Checksum", + "checksum-hint": "If checksum is empty, it will be generated automatically", + "checksum-algorithm": "Checksum algorithm", + "checksum-copied-message": "Package checksum has been copied to clipboard", + "change-firmware": "Change of the firmware may cause update of { count, plural, =1 {1 device} other {# devices} }.", + "change-software": "Change of the software may cause update of { count, plural, =1 {1 device} other {# devices} }.", + "chose-compatible-device-profile": "The uploaded package will be available only for devices with the chosen profile.", + "chose-firmware-distributed-device": "Choose firmware that will be distributed to the devices", + "chose-software-distributed-device": "Choose software that will be distributed to the devices", + "content-type": "Content type", + "copy-checksum": "Copy checksum", + "copy-direct-url": "Copy direct URL", + "copyId": "Copy package Id", + "copied": "Copied!", + "delete": "Delete package", + "delete-ota-update-text": "Be careful, after the confirmation the OTA update will become unrecoverable.", + "delete-ota-update-title": "Are you sure you want to delete the OTA update '{{title}}'?", + "delete-ota-updates-text": "Be careful, after the confirmation all selected OTA updates will be removed.", + "delete-ota-updates-title": "Are you sure you want to delete { count, plural, =1 {1 OTA update} other {# OTA updates} }?", + "description": "Description", + "direct-url": "Direct URL", + "direct-url-copied-message": "Package direct URL has been copied to clipboard", + "direct-url-required": "Direct URL is required", + "download": "Download package", + "drop-file": "Drop a package file or click to select a file to upload.", + "drop-package-file-or": "Drag and drop a package file or", + "file-name": "File name", + "file-size": "File size", + "file-size-bytes": "File size in bytes", + "idCopiedMessage": "Package Id has been copied to clipboard", + "no-firmware-matching": "No compatible Firmware OTA Update packages matching '{{entity}}' were found.", + "no-firmware-text": "No compatible Firmware OTA Update packages provisioned.", + "no-packages-text": "No packages found", + "no-software-matching": "No compatible Software OTA Update packages matching '{{entity}}' were found.", + "no-software-text": "No compatible Software OTA Update packages provisioned.", + "ota-update": "OTA update", + "ota-update-details": "OTA update details", + "ota-updates": "OTA updates", + "package-file": "Package file", + "package-type": "Package type", + "packages-repository": "Packages repository", + "search": "Search packages", + "selected-package": "{ count, plural, =1 {1 package} other {# packages} } selected", + "title": "Title", + "title-required": "Title is required.", + "title-max-length": "Title should be less than 256", + "types": { + "firmware": "Firmware", + "software": "Software" + }, + "upload-binary-file": "Upload binary file", + "use-external-url": "Use external URL", + "version": "Version", + "version-required": "Version is required.", + "version-tag": "Version tag", + "version-tag-hint": "Custom tag should match the package version reported by your device.", + "version-max-length": "Version should be less than 256", + "warning-after-save-no-edit": "Once the package is uploaded, you will not be able to modify title, version, device profile and package type." }, "position": { "top": "Top", @@ -3645,7 +3717,8 @@ "password-requirements": "Password requirements", "password-should-difference": "New password should be different from current", "special-character": "{ count, plural, =1 {1 special character} other {# special characters} }", - "uppercase-letter": "{ count, plural, =1 {1 uppercase letter} other {# uppercase letters} }" + "uppercase-letter": "{ count, plural, =1 {1 uppercase letter} other {# uppercase letters} }", + "at-most": "At most:" } }, "relation": { @@ -3714,6 +3787,8 @@ "no-resource-text": "No resources found", "open-widgets-bundle": "Open widgets bundle", "resource": "Resource", + "resource-file": "Resource file", + "resource-files": "Resource files", "resource-library-details": "Resource details", "resource-type": "Resource type", "resources-library": "Resources library", @@ -3771,7 +3846,6 @@ "search": "Search rule chains", "selected-rulechains": "{ count, plural, =1 {1 rule chain} other {# rule chains} } selected", "open-rulechain": "Open rule chain", - "assign-new-rulechain": "Assign new rulechain", "edge-template-root": "Template root", "assign-to-edge": "Assign to edge", "edge-rulechain": "Edge rule chain", @@ -3865,7 +3939,9 @@ "test": "Test", "help": "Help", "reset-debug-mode": "Reset debug mode in all nodes", - "test-with-this-message": "{{test}} with this message" + "test-with-this-message": "{{test}} with this message", + "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." }, "timezone": { "timezone": "Timezone", @@ -4053,7 +4129,7 @@ "rule-engine": "Rule Engine", "time-to-live": "Time-to-live", "alarms-and-notifications": "Alarms and notifications", - "ota-files-in-bytes": "OTA files in bytes", + "ota-files-in-bytes": "Files", "ws-title": "WS", "unlimited": "(0 - unlimited)", "maximum-devices": "Devices maximum number", @@ -4074,12 +4150,15 @@ "maximum-rule-chains": "Rule chains maximum number", "maximum-rule-chains-required": "Rule chains maximum number is required.", "maximum-rule-chains-range": "Rule chains maximum number can't be negative", - "maximum-resources-sum-data-size": "Resource files sum size", - "maximum-resources-sum-data-size-required": "Resource files sum size is required.", - "maximum-resources-sum-data-size-range": "Resource files sum size can`t be negative", - "maximum-ota-packages-sum-data-size": "OTA package files sum size", - "maximum-ota-package-sum-data-size-required": "OTA package files sum size is required.", - "maximum-ota-package-sum-data-size-range": "OTA package files sum size can`t be negative", + "maximum-resources-sum-data-size": "Maximum total size of resources files (bytes)", + "maximum-resources-sum-data-size-required": "Maximum total size of resources files is required.", + "maximum-resources-sum-data-size-range": "Maximum total size of resources files can't be negative", + "maximum-resource-size": "Maximum resource file size (bytes)", + "maximum-resource-size-required": "Maximum resource file size is required", + "maximum-resource-size-range": "Maximum resource file size can't be negative", + "maximum-ota-packages-sum-data-size": "Maximum total size of OTA package files (bytes)", + "maximum-ota-package-sum-data-size-required": "Maximum total size of OTA package files is required.", + "maximum-ota-package-sum-data-size-range": "Maximum total size of OTA package files can't be negative", "rest-requests-for-tenant": "REST requests for tenant", "transport-tenant-telemetry-msg-rate-limit": "Transport tenant telemetry messages", "transport-tenant-telemetry-data-points-rate-limit": "Transport tenant telemetry data points", @@ -4206,30 +4285,36 @@ "seconds": "Seconds", "advanced": "Advanced", "predefined": { - "yesterday": "Yesterday", - "day-before-yesterday": "Day before yesterday", - "this-day-last-week": "This day last week", - "previous-week": "Previous week (Sun - Sat)", - "previous-week-iso": "Previous week (Mon - Sun)", - "previous-month": "Previous month", - "previous-quarter": "Previous quarter", - "previous-half-year": "Previous half year", - "previous-year": "Previous year", - "current-hour": "Current hour", - "current-day": "Current day", - "current-day-so-far": "Current day so far", - "current-week": "Current week (Sun - Sat)", - "current-week-iso": "Current week (Mon - Sun)", - "current-week-so-far": "Current week so far (Sun - Sat)", - "current-week-iso-so-far": "Current week so far (Mon - Sun)", - "current-month": "Current month", - "current-month-so-far": "Current month so far", - "current-quarter": "Current quarter", - "current-quarter-so-far": "Current quarter so far", - "current-half-year": "Current half year", - "current-half-year-so-far": "Current half year so far", - "current-year": "Current year", - "current-year-so-far": "Current year so far" + "yesterday": "Yesterday", + "day-before-yesterday": "Day before yesterday", + "this-day-last-week": "This day last week", + "previous-week": "Previous week (Sun - Sat)", + "previous-week-iso": "Previous week (Mon - Sun)", + "previous-month": "Previous month", + "previous-quarter": "Previous quarter", + "previous-half-year": "Previous half year", + "previous-year": "Previous year", + "current-hour": "Current hour", + "current-day": "Current day", + "current-day-so-far": "Current day so far", + "current-week": "Current week (Sun - Sat)", + "current-week-iso": "Current week (Mon - Sun)", + "current-week-so-far": "Current week so far (Sun - Sat)", + "current-week-iso-so-far": "Current week so far (Mon - Sun)", + "current-month": "Current month", + "current-month-so-far": "Current month so far", + "current-quarter": "Current quarter", + "current-quarter-so-far": "Current quarter so far", + "current-half-year": "Current half year", + "current-half-year-so-far": "Current half year so far", + "current-year": "Current year", + "current-year-so-far": "Current year so far" + }, + "type": { + "week": "Week (Sun - Sat)", + "week-iso": "Week (Mon - Sun)", + "month": "Month", + "quarter": "Quarter" } }, "timeunit": { @@ -4288,6 +4373,12 @@ "displayTypePrefix": "Display Realtime/History prefix", "preview": "Preview" }, + "tooltip": { + "value": "Value", + "date": "Date", + "background-color": "Background color", + "background-blur": "Background blur" + }, "unit": { "millimeter": "Millimeter", "centimeter": "Centimeter", @@ -4566,6 +4657,7 @@ "gram-per-cubic-centimeter": "Gram per cubic centimeter", "kilogram-per-square-meter": "Kilogram per square metre", "milligram-per-milliliter": "Milligram per milliliter", + "milligram-per-cubic-meter": "Milligram per cubic meter", "pound-per-cubic-foot": "Pound per cubic foot", "ounces-per-cubic-inch": "Ounces per cubic inch", "tons-per-cubic-yard": "Tons per cubic yard", @@ -5155,15 +5247,20 @@ "background": { "background": "Background", "background-settings": "Background settings", - "background-type-image": "Upload image", - "background-type-image-url": "Image URL", - "background-type-color": "Solid color", + "background-type-image": "Image", + "background-type-color": "Color", "image-url": "Image URL", "overlay": "Overlay", "enable-overlay": "Enable overlay", "blur": "Blur", "preview": "Preview" }, + "bar-chart": { + "bar-appearance": "Bar appearance", + "label-on-bar": "Label on bar", + "value-on-bar": "Value on bar", + "bar-chart-card-style": "Bar chart card style" + }, "battery-level": { "layout": "Layout", "layout-vertical-solid": "Vertical. Solid", @@ -5189,9 +5286,6 @@ "date": "Date", "active-bars-color": "Active signal bars color", "inactive-bars-color": "Inactive signal bars color", - "tooltip": "Tooltip", - "background-color": "Background color", - "background-blur": "Background blur", "signal-strength-card-style": "Signal strength card style" }, "chart": { @@ -5434,18 +5528,8 @@ "clockwise-layout": "Clockwise layout", "sort-series": "Sort series by label", "central-total-value": "Central total value", - "legend-position-top": "Top", - "legend-position-bottom": "Bottom", - "legend-position-left": "Left", - "legend-position-right": "Right", - "legend-label": "Label", - "legend-value": "Value", - "tooltip": "Tooltip", - "tooltip-value": "Value", "tooltip-value-type-absolute": "Absolute", "tooltip-value-type-percentage": "Percentage", - "tooltip-background-color": "Background color", - "tooltip-background-blur": "Background blur", "doughnut-card-style": "Doughnut card style" }, "entities-hierarchy": { @@ -5921,6 +6005,14 @@ "no-columns-found": "No columns found", "no-columns-matching": "'{{column}}' not found." }, + "range-chart": { + "chart": "Chart", + "data-zoom": "Data zoom", + "range-colors": "Range colors", + "out-of-range-color": "Out of range color", + "fill-area": "Fill area", + "range-chart-card-style": "Range chart card style" + }, "rpc": { "value-settings": "Value settings", "initial-value": "Initial value", @@ -6348,8 +6440,7 @@ "hidden-cell-button-display-mode": "Hidden cell button actions display mode", "show-empty-space-hidden-action": "Show empty space instead of hidden cell button action", "dont-reserve-space-hidden-action": "Don't reserve space for hidden action buttons", - "display-timestamp": "Display timestamp column", - "display-milliseconds": "Display timestamp milliseconds", + "display-timestamp": "Timestamp", "display-pagination": "Display pagination", "default-page-size": "Default page size", "use-entity-label-tab-name": "Use entity label in tab name", @@ -6710,9 +6801,9 @@ "ka_GE": "ქართული", "ko_KR": "한국어", "lv_LV": "Latviešu", + "nl_BE": "Koninkrijk België", "pt_BR": "Português do Brasil", "ro_RO": "Română", - "ru_RU": "Русский", "sl_SI": "Slovenščina", "tr_TR": "Türkçe", "uk_UA": "Українська", diff --git a/ui-ngx/src/assets/locale/locale.constant-es_ES.json b/ui-ngx/src/assets/locale/locale.constant-es_ES.json index b9a386071a..8727339851 100644 --- a/ui-ngx/src/assets/locale/locale.constant-es_ES.json +++ b/ui-ngx/src/assets/locale/locale.constant-es_ES.json @@ -2655,7 +2655,6 @@ "rpc-command-result": "Resultado", "rpc-command-edit-params": "Editar parametros", "gateway-configuration": "Configuración General", - "docker-label": "Usa los siguientes comandos para ejecutar el gateway en Docker.", "create-new-gateway": "Crear un gateway nuevo", "create-new-gateway-text": "Crear un nuevo gateway con el nombre: '{{gatewayName}}'?", "created-time": "Hora de creación", @@ -3094,6 +3093,35 @@ "backup-code-auth-description": "Por favor, introduce el código de backup.", "backup-code-auth-placeholder": "Código de Backup" }, + "signup": { + "firstname": "Nombre", + "lastname": "Apellido", + "email": "Correo electrónico", + "signup": "Registrarse", + "create-password": "Crear una contraseña", + "repeat-password": "Repite tu contraseña", + "have-account": "¿Ya tienes una cuenta?", + "signin": "Iniciar sesión", + "no-captcha-message": "Debes confirmar que no eres un robot", + "password-length-message": "Tu contraseña debe tener al menos 6 caracteres", + "email-verification": "Verificación de correo electrónico", + "email-verification-message": "Se envió un correo electrónico con detalles de verificación a la dirección de correo electrónico especificada. Por favor, sigue las instrucciones proporcionadas en el correo electrónico para completar tu proceso de registro. Nota: si no has visto el correo electrónico durante un tiempo, por favor revisa tu carpeta de 'spam' o intenta reenviar el correo electrónico haciendo clic en el botón 'Reenviar'.", + "account-activation-title": "Activación de cuenta", + "account-activated": "¡Cuenta activada con éxito!", + "account-activated-text": "¡Felicidades! Tu cuenta ha sido activada.", + "resend": "Reenviar", + "inactive-user-exists-title": "Ya existe un usuario inactivo", + "inactive-user-exists-text": "Ya hay un usuario registrado con dirección de correo electrónico no verificada. Haz clic en el botón 'Reenviar' si deseas reenviar el correo electrónico de verificación.", + "activating-account": "Activando cuenta...", + "activating-account-text": "Tu cuenta se está activando actualmente. Por favor espera...", + "accept-privacy-policy": "Aceptar la Política de Privacidad", + "accept": "Aceptar", + "privacy-policy": "Política de Privacidad", + "accept-privacy-policy-message": "Debes aceptar nuestra Política de Privacidad", + "recaptcha-title": "reCAPTCHA", + "terms-of-use": "Términos de Uso", + "accept-terms-of-use-message": "Debes aceptar nuestros Términos de Uso" + }, "markdown": { "edit": "Editar", "preview": "Previsualizar", @@ -3247,15 +3275,13 @@ "recipient-type": { "affected-tenant-administrators": "Administradores afectados", "affected-user": "Usuario afectado", - "affected-user-hint": "Sugerencia en usuario afectado", "all-users": "Todos los usuarios", "customer-users": "Usuarios del cliente", "system-administrators": "Administradores del sistema", "tenant-administrators": "Administradores de propietarios", "user-filters": "Filtro de usuarios", "user-list": "Lista de usuarios", - "users-entity-owner": "Usuarios que sean propietarios de la entidad", - "users-entity-owner-hint": "Sugerencia en usuarios propietarios de la entidad" + "users-entity-owner": "Usuarios que sean propietarios de la entidad" }, "recipients": "Destinatarios", "notification-recipients": "Notificaciones / Destinatarios", @@ -3653,7 +3679,6 @@ "search": "Buscar cadenas de reglas", "selected-rulechains": "{ count, plural, =1 {1 cadena de reglas} other {# cadenas de reglas} } seleccionadas", "open-rulechain": "Abrir cadena de reglas", - "assign-new-rulechain": "Asignar nueva cadena de reglas", "edge-template-root": "Raíz de plantilla", "assign-to-edge": "Asignar a Edge", "edge-rulechain": "Cadena de reglas de Edge", @@ -6066,7 +6091,6 @@ "show-empty-space-hidden-action": "Mostrar espacio vacío en lugar de celda oculta", "dont-reserve-space-hidden-action": "No reservar espacio para los botones en celda oculta", "display-timestamp": "Mostrar columna timestamp", - "display-milliseconds": "Mostrar milisegundos", "display-pagination": "Mostrar páginas", "default-page-size": "Tamaño de página por defecto", "use-entity-label-tab-name": "Usar etiqueta de entidad en el nombre de la tabla", diff --git a/ui-ngx/src/assets/locale/locale.constant-fr_FR.json b/ui-ngx/src/assets/locale/locale.constant-fr_FR.json index 9fbdfef9f4..7e678d9ed9 100644 --- a/ui-ngx/src/assets/locale/locale.constant-fr_FR.json +++ b/ui-ngx/src/assets/locale/locale.constant-fr_FR.json @@ -1866,7 +1866,6 @@ "set-root-rulechain-title": "Voulez-vous vraiment que la chaîne de règles '{{ruleChainName}} soit racine (root) ?", "system": "Système", "assign-rulechains": "Attribuer aux chaînes de règles", - "assign-new-rulechain": "Attribuer une nouvele chaînes de règles", "delete-rulechains": "Supprimer une chaînes de règles", "unassign-rulechain": "Retirer chaîne de règles", "unassign-rulechains": "Retirer chaînes de règles", diff --git a/ui-ngx/src/assets/locale/locale.constant-nl_BE.json b/ui-ngx/src/assets/locale/locale.constant-nl_BE.json new file mode 100644 index 0000000000..df3820d497 --- /dev/null +++ b/ui-ngx/src/assets/locale/locale.constant-nl_BE.json @@ -0,0 +1,6951 @@ +{ + "access": { + "unauthorized": "Geen toegang", + "unauthorized-access": "Geen toegang", + "unauthorized-access-text": "Gelieve u zich opnieuw in te loggen.", + "access-forbidden": "Toegang verboden", + "access-forbidden-text": "Je hebt geen toegangsrechten tot deze locatie!
Probeer in te loggen met een andere gebruiker als u toch toegang wilt verkrijgen.", + "refresh-token-expired": "Sessie is verlopen", + "refresh-token-failed": "Kan sessie niet vernieuwen", + "permission-denied": "Toestemming geweigerd", + "permission-denied-text": "U hebt geen toestemming om deze bewerking uit te voeren!" + }, + "action": { + "activate": "Activeren", + "suspend": "Opschorten", + "save": "Opslaan", + "saveAs": "Opslaan als", + "cancel": "Annuleren", + "ok": "OK", + "delete": "Verwijderen", + "add": "Toevoegen", + "yes": "Ja", + "no": "Nee", + "update": "Update", + "remove": "Verwijderen", + "search": "Zoeken", + "clear-search": "Zoekopdracht wissen", + "assign": "Toewijzen", + "unassign": "Toewijzing ongedaan maken", + "share": "Delen", + "make-private": "Privé maken", + "make-public": "Openbaar maken", + "apply": "Toepassen", + "apply-changes": "Wijzigingen toepassen", + "edit-mode": "Bewerk modus", + "enter-edit-mode": "Ga naar de bewerkingsmodus", + "decline-changes": "Wijzigingen weigeren", + "open": "Open", + "close": "Sluiten", + "back": "Terug", + "run": "Uitvoeren", + "sign-in": "Aanmelden", + "edit": "Bewerken", + "view": "Bekijken", + "create": "Aanmaken", + "drag": "Slepen", + "refresh": "Vernieuwen", + "undo": "Ongedaan maken", + "copy": "Kopiëren", + "paste": "Plakken", + "copy-reference": "Referentie kopiëren", + "paste-reference": "Referentie plakken", + "import": "Importeren", + "export": "Exporteren", + "share-via": "Delen via {{provider}}", + "move": "Verplaatsen", + "select": "Selecteren", + "continue": "Voortzetten", + "discard-changes": "Wijzigingen negeren", + "download": "Downloaden", + "next": "Volgend", + "next-with-label": "Volgende: {{label}}", + "read-more": "Lees meer", + "hide": "Verbergen", + "done": "Klaar", + "print": "Afdrukken", + "restore": "Herstellen", + "confirm": "Bevestigen", + "more": "Meer", + "less": "Minder", + "skip": "Overslaan", + "send": "Verzenden" + }, + "aggregation": { + "aggregation": "Aggregatie", + "function": "Functie voor gegevensaggregatie", + "limit": "Maximale waarden", + "group-interval": "Groeperingsinterval", + "min": "Min", + "max": "Max", + "avg": "Gemiddeld", + "sum": "Som", + "count": "Tellen", + "none": "Geen" + }, + "admin": { + "settings": "Instellingen", + "general": "Algemeen", + "general-settings": "Algemene instellingen", + "home-settings": "Home-instellingen", + "home": "Thuis", + "outgoing-mail": "E-mailserver", + "outgoing-mail-settings": "Serverinstellingen voor uitgaande e-mail", + "system-settings": "Systeeminstellingen", + "test-mail-sent": "Testmail is succesvol verzonden!", + "base-url": "Basis-URL", + "base-url-required": "Basis-URL is vereist.", + "prohibit-different-url": "Verbieden om de hostnaam te gebruiken in de headers van de clientaanvraag", + "prohibit-different-url-hint": "Deze instelling moet zijn ingeschakeld voor productieomgevingen. Kan beveiligingsproblemen veroorzaken wanneer deze is uitgeschakeld", + "mail-from": "E-mail van", + "mail-from-required": "Mail Van is vereist.", + "smtp-protocol": "SMTP-protocol", + "smtp-host": "SMTP-host", + "smtp-host-required": "SMTP-host is vereist.", + "smtp-port": "SMTP-poort", + "smtp-port-required": "U moet een smtp-poort opgeven.", + "smtp-port-invalid": "Dat ziet er niet uit als een geldige smtp-poort.", + "timeout-msec": "Time-out (msec)", + "timeout-required": "Er is een time-out vereist.", + "timeout-invalid": "Dat ziet er niet uit als een geldige time-out.", + "enable-tls": "TLS inschakelen", + "tls-version": "TLS-versie", + "enable-proxy": "Proxy inschakelen", + "proxy-host": "Proxy-host", + "proxy-host-required": "Proxyhost is vereist.", + "proxy-port": "Proxy-poort", + "proxy-port-required": "Proxypoort is vereist.", + "proxy-port-range": "De proxypoort moet tussen 1 en 65535 liggen.", + "proxy-user": "Proxy-gebruiker", + "proxy-password": "Proxy wachtwoord", + "change-password": "Wachtwoord wijzigen", + "send-test-mail": "Testmail versturen", + "use-system-mail-settings": "Systeeminstellingen voor e-mailserver gebruiken", + "mail-templates": "E-mail sjablonen", + "mail-template-settings": "Instellingen voor e-mailsjablonen", + "use-system-mail-template-settings": "Systeem-e-mailsjablonen gebruiken", + "mail-template": { + "mail-template": "E-mail sjabloon", + "test": "E-mailbericht testen", + "activation": "Bericht over accountactivering", + "account-activated": "Bericht over account geactiveerd", + "account-lockout": "Bericht over accountvergrendeling", + "reset-password": "Bericht over wachtwoord opnieuw instellen", + "password-was-reset": "Bericht Wachtwoord is opnieuw ingesteld", + "user-activated": "Door de gebruiker geactiveerd bericht", + "user-registered": "Geregistreerd bericht van de gebruiker", + "api-usage-state-enabled": "Api-gebruiksstatus ingeschakeld", + "api-usage-state-warning": "Waarschuwing voor API-gebruiksstatus", + "api-usage-state-disabled": "Api-gebruiksstatus uitgeschakeld", + "two-fa-verification": "2FA-verificatiebericht" + }, + "mail-subject": "Onderwerp van de e-mail", + "mail-body": "Hoofdtekst van e-mail", + "sms-provider": "SMS-provider", + "sms-provider-settings": "Instellingen sms-provider", + "use-system-sms-settings": "De instellingen van de systeem-sms-provider gebruiken", + "sms-provider-type": "Type sms-provider", + "sms-provider-type-required": "Het type sms-provider is vereist.", + "sms-provider-type-aws-sns": "Amazone SNS", + "sms-provider-type-twilio": "Twilio", + "sms-provider-type-smpp": "SMPP", + "aws-access-key-id": "AWS-toegangssleutel-ID", + "aws-access-key-id-required": "AWS Access Key ID is vereist", + "aws-secret-access-key": "AWS geheime toegangssleutel", + "aws-secret-access-key-required": "AWS geheime toegangssleutel is vereist", + "aws-region": "AWS-regio", + "aws-region-required": "AWS-regio is vereist", + "number-from": "Telefoonnummer van", + "number-from-required": "Telefoonnummer van is vereist.", + "number-to": "Telefoonnummer naar", + "number-to-required": "Telefoonnummer Naar is vereist.", + "phone-number-hint": "Telefoonnummer in E.164-formaat, bijv. +19995550123", + "phone-number-hint-twilio": "Telefoonnummer in E.164-formaat/SID van telefoonnummer/SID-berichtenservice, bijv. +19995550123/PNXXX/MGXXX", + "phone-number-pattern": "Ongeldig telefoonnummer. Moet in E.164-formaat zijn, bijv. +19995550123.", + "phone-number-pattern-twilio": "Ongeldig telefoonnummer. Moet in E.164-indeling/SID/Berichtenservice SID van het telefoonnummer/telefoonnummer zijn, bijv. +19995550123/PNXXX/MGXXX.", + "sms-message": "SMS-bericht", + "sms-message-required": "SMS-bericht is vereist.", + "sms-message-max-length": "SMS-bericht mag niet langer zijn dan 1600 tekens", + "twilio-account-sid": "TSID voor Twilio-account", + "twilio-account-sid-required": "TSID voor Twilio-account is vereist", + "twilio-account-token": "Twilio-accounttoken", + "twilio-account-token-required": "Twilio-accounttoken is vereist", + "send-test-sms": "Test-sms verzenden", + "test-sms-sent": "Test-sms is succesvol verzonden!", + "security-settings": "Beveiligingsinstellingen", + "password-policy": "Wachtwoord beleid", + "minimum-password-length": "Minimale wachtwoordlengte", + "minimum-password-length-required": "Minimale wachtwoordlengte is vereist", + "minimum-password-length-range": "De minimale wachtwoordlengte moet tussen 5 en 50 liggen", + "minimum-uppercase-letters": "Minimum aantal hoofdletters", + "minimum-uppercase-letters-range": "Minimum aantal hoofdletters mag niet negatief zijn", + "minimum-lowercase-letters": "Minimum aantal kleine letters", + "minimum-lowercase-letters-range": "Minimum aantal kleine letters mag niet negatief zijn", + "minimum-digits": "Minimum aantal cijfers", + "minimum-digits-range": "Minimum aantal cijfers mag niet negatief zijn", + "minimum-special-characters": "Minimum aantal speciale tekens", + "minimum-special-characters-range": "Minimum aantal speciale tekens mag niet negatief zijn", + "password-expiration-period-days": "Vervalperiode van wachtwoord in dagen", + "password-expiration-period-days-range": "De vervalperiode van het wachtwoord in dagen mag niet negatief zijn", + "password-reuse-frequency-days": "Frequentie van hergebruik van wachtwoorden in dagen", + "password-reuse-frequency-days-range": "De frequentie van hergebruik van wachtwoorden in dagen mag niet negatief zijn", + "allow-whitespace": "Witruimte toestaan", + "general-policy": "Algemeen beleid", + "max-failed-login-attempts": "Maximum aantal mislukte inlogpogingen voordat het account wordt vergrendeld", + "minimum-max-failed-login-attempts-range": "Het maximale aantal mislukte aanmeldingspogingen mag niet negatief zijn", + "user-lockout-notification-email": "Als het gebruikersaccount is vergrendeld, stuurt u een melding naar e-mail", + "domain-name": "Domeinnaam", + "domain-name-unique": "Domeinnaam en protocol moeten uniek zijn.", + "domain-name-max-length": "Domeinnaam moet kleiner zijn dan 256 tekens tekens", + "error-verification-url": "Een domeinnaam mag geen symbolen '/' en ':' bevatten. Voorbeeld: thingsboard.io", + "oauth2": { + "access-token-uri": "Toegangstoken URI", + "access-token-uri-required": "De URI van het toegangstoken is vereist.", + "activate-user": "Gebruiker activeren", + "add-domain": "Domein toevoegen", + "delete-domain": "Domein verwijderen", + "add-provider": "Provider toevoegen", + "delete-provider": "Provider verwijderen", + "allow-user-creation": "Aanmaken van gebruikers toestaan", + "always-fullscreen": "Altijd volledig scherm", + "authorization-uri": "Autorisatie-URI", + "authorization-uri-required": "Autorisatie-URI is vereist.", + "client-authentication-method": "Verificatiemethode voor clients", + "client-id": "Client-ID", + "client-id-required": "Client-ID is vereist.", + "client-id-max-length": "Client-ID lengte moet kleiner zijn dan 256 tekens tekens", + "client-secret": "Geheim van de klant", + "client-secret-required": "Clientgeheim is vereist.", + "client-secret-max-length": "Clientgeheim lengte moet kleiner zijn dan 2049 tekens", + "custom-setting": "Aangepaste instellingen", + "customer-name-pattern": "Patroon klantnaam", + "customer-name-pattern-max-length": "Het patroon van de klantnaam moet kleiner zijn dan 256 tekens tekens", + "parent-customer-name-pattern": "Patroon voor bovenliggende klantnaam", + "user-groups-name-pattern": "Naampatroon van gebruikersgroepen", + "default-dashboard-name": "Standaard dashboardnaam", + "default-dashboard-name-max-length": "De standaardnaam van het dashboard moet kleiner zijn dan 256 tekens tekens", + "delete-domain-text": "Let op, na de bevestiging zijn dit domein en alle providergegevens niet meer beschikbaar.", + "delete-domain-title": "Weet u zeker dat u instellingen wilt verwijderen van dit domein '{{domainName}}'?", + "delete-registration-text": "Let op, na de bevestiging zijn de gegevens van deze provider niet meer beschikbaar.", + "delete-registration-title": "Weet u zeker dat u de provider '{{name}}' wilt verwijderen?", + "email-attribute-key": "E-mail attribuut sleutel", + "email-attribute-key-required": "E-mailkenmerksleutel is vereist.", + "email-attribute-key-max-length": "De e-mailkenmerksleutel moet kleiner zijn dan 32 tekens", + "first-name-attribute-key": "Voornaam attribuutsleutel", + "first-name-attribute-key-max-length": "De kenmerksleutel voor de voornaam moet kleiner zijn dan 32 tekens", + "general": "Algemeen", + "jwk-set-uri": "JSON-websleutel-URI", + "last-name-attribute-key": "Sleutel voor het kenmerk achternaam", + "last-name-attribute-key-max-length": "De kenmerksleutel voor de achternaam moet kleiner zijn dan 32 tekens", + "login-button-icon": "Pictogram van de inlogknop", + "login-button-label": "Label van de aanbieder", + "login-button-label-placeholder": "Log in met $(Providerlabel)", + "login-button-label-required": "Label is vereist.", + "login-provider": "Login provider", + "mapper": "Mapper", + "new-domain": "Nieuw domein", + "oauth2": "OAuth2", + "password-max-length": "Wachtwoord moet kleiner zijn dan 256 tekens tekens", + "redirect-uri-template": "Sjabloon voor omleidings-URI", + "copy-redirect-uri": "Omleidings-URI kopiëren", + "registration-id": "Registratie-ID", + "registration-id-required": "Registratie-ID is vereist.", + "registration-id-unique": "Registratie-ID moet uniek zijn voor het systeem.", + "scope": "Draagwijdte", + "scope-required": "Scope is vereist.", + "tenant-name-pattern": "Patroon van tenantnaam", + "tenant-name-pattern-required": "Het patroon van de naam van de tenant is vereist.", + "tenant-name-pattern-max-length": "Patroon van tenantnaam imoet kleiner zijn dan 256 tekens tekens", + "tenant-name-strategy": "Strategie voor naam tenant", + "type": "Type mapper", + "uri-pattern-error": "Ongeldige URI-indeling.", + "url": "URL", + "url-pattern": "Ongeldige URL-indeling.", + "url-required": "URL is vereist.", + "url-max-length": "URL moet kleiner zijn dan 256 tekens tekens", + "user-info-uri": "Gebruikersinfo URI", + "user-info-uri-required": "URI voor gebruikersinformatie is vereist.", + "username-max-length": "Gebruikersnaam moet kleiner zijn dan 256 tekens tekens", + "user-name-attribute-name": "Sleutel voor gebruikersnaamattribuut", + "user-name-attribute-name-required": "De kenmerksleutel van de gebruikersnaam is vereist", + "protocol": "Protocol", + "domain-schema-http": "HTTP (HTTP)", + "domain-schema-https": "HTTPS", + "domain-schema-mixed": "HTTP+HTTPS", + "enable": "OAuth2-instellingen inschakelen", + "domains": "Domeinen", + "mobile-apps": "Mobiele applicaties", + "no-mobile-apps": "Geen applicaties geconfigureerd", + "mobile-package": "Applicatie pakket", + "mobile-package-placeholder": "Vb.: my.example.app", + "mobile-package-hint": "Voor Android: uw eigen unieke applicatie-ID. Voor iOS: ID van productbundel.", + "mobile-package-unique": "Het toepassingspakket moet uniek zijn.", + "mobile-app-secret": "Geheim van de toepassing", + "invalid-mobile-app-secret": "Het geheim van de toepassing mag alleen alfanumerieke tekens bevatten en moet tussen de 16 en 2048 tekens lang zijn.", + "copy-mobile-app-secret": "Toepassingsgeheim kopiëren", + "add-mobile-app": "Applicatie toevoegen", + "delete-mobile-app": "Toepassingsgegevens verwijderen", + "providers": "Providers", + "platform-web": "Web", + "platform-android": "Android", + "platform-ios": "iOS", + "all-platforms": "Alle platformen", + "allowed-platforms": "Toegestane platforms" + }, + "smpp-provider": { + "smpp-version": "SMPP-versie", + "smpp-host": "SMPP-host", + "smpp-host-required": "SMPP-host is vereist", + "smpp-port": "SMPP-poort", + "smpp-port-required": "SMPP-poort is vereist", + "system-id": "Systeem-ID", + "system-id-required": "Systeem-ID is vereist", + "password": "Wachtwoord", + "password-required": "Wachtwoord is vereist", + "type-settings": "Typ instellingen", + "source-settings": "Bron-instellingen", + "destination-settings": "Bestemming instellingen", + "additional-settings": "Aanvullende instellingen", + "system-type": "Type systeem", + "bind-type": "Type binden", + "service-type": "Soort dienst", + "source-address": "Bronadres", + "source-ton": "Bron: TON", + "source-npi": "Bron: NPI", + "destination-ton": "Bestemming TON (type nummer)", + "destination-npi": "Bestemming NPI (Nummerplan Identificatie)", + "address-range": "Adres bereik", + "coding-scheme": "Coderingsschema", + "bind-type-tx": "Zender", + "bind-type-rx": "Ontvanger", + "bind-type-trx": "Transciever", + "ton-unknown": "Onbekend", + "ton-international": "Internationaal", + "ton-national": "Nationaal", + "ton-network-specific": "Netwerk Specifiek", + "ton-subscriber-number": "Abonneenummer", + "ton-alphanumeric": "Alfanumeriek", + "ton-abbreviated": "Afgekort", + "npi-unknown": "0 - Onbekend", + "npi-isdn": "1 - ISDN/telefoonnummerplan (E163/E164)", + "npi-data-numbering-plan": "3 - Nummeringsplan voor gegevens (X.121)", + "npi-telex-numbering-plan": "4 - Telexnummerplan (F.69)", + "npi-land-mobile": "6 - Landmobiel (E.212)", + "npi-national-numbering-plan": "8 - Nationaal nummerplan", + "npi-private-numbering-plan": "9 - Privé nummerplan", + "npi-ermes-numbering-plan": "10 - ERMES-nummerplan (ETSI DE/PS 3 01-3)", + "npi-internet": "13 - Internet (IP)", + "npi-wap-client-id": "18 - WAP-client-ID (te definiëren door WAP-forum)", + "scheme-smsc": "0 - SMSC Default Alphabet (ASCII voor korte en lange code en naar GSM voor gratis)", + "scheme-ia5": "1 - IA5 (ASCII voor korte en lange code, Latijnse 9 voor gratis code (ISO-8859-9))", + "scheme-octet-unspecified-2": "2 - Octet Niet gespecificeerd (8-bits binair)", + "scheme-latin-1": "3 - Latijn 1 (ISO-8859-1)", + "scheme-octet-unspecified-4": "4 - Octet Niet gespecificeerd (8-bits binair)", + "scheme-jis": "5 - JIS (X 0208-1990)", + "scheme-cyrillic": "6 - Cyrillisch (ISO-8859-5)", + "scheme-latin-hebrew": "7 - Latijn/Hebreeuws (ISO-8859-8)", + "scheme-ucs-utf": "8 - UCS2/UTF-16 (ISO/IEC-10646)", + "scheme-pictogram-encoding": "9 - Codering van pictogrammen", + "scheme-music-codes": "10 - Muziek Codes (ISO-2022-JP)", + "scheme-extended-kanji-jis": "13 - Uitgebreide Kanji JIS (X 0212-1990)", + "scheme-korean-graphic-character-set": "14 - Koreaanse grafische tekenset (KS C 5601/KS X 1001)" + }, + "queue-select-name": "Selecteer de naam van de queue", + "queue-name": "Naam", + "queue-name-required": "Queue naam is verplicht!", + "queues": "Queues", + "queue-partitions": "Partities", + "queue-submit-strategy": "Strategie indienen", + "queue-processing-strategy": "Verwerkingsstrategie", + "queue-configuration": "Configuratie van queues", + "repository-settings": "Repository-instellingen", + "repository": "Opslagplaats", + "repository-url": "URL van opslagplaats", + "repository-url-required": "De URL van de opslagplaats is vereist.", + "default-branch": "Standaard filiaalnaam", + "repository-read-only": "Alleen-lezen", + "show-merge-commits": "Samenvoegcommits weergeven", + "authentication-settings": "Authenticatie-instellingen", + "auth-method": "Verificatiemethode", + "auth-method-username-password": "Wachtwoord / toegangstoken", + "auth-method-username-password-hint": "GitHub-gebruikers moeten toegang tokens gebruiken met schrijfmachtigingen voor de opslagplaats.", + "auth-method-private-key": "Privé-sleutel", + "password-access-token": "Wachtwoord / toegangstoken", + "change-password-access-token": "Wachtwoord / toegangstoken wijzigen", + "private-key": "Privé-sleutel", + "drop-private-key-file-or": "Sleep een bestand met een persoonlijke sleutel of", + "passphrase": "Wachtwoordzin", + "enter-passphrase": "Voer wachtwoordzin in", + "change-passphrase": "Wachtwoordzin wijzigen", + "check-access": "Toegang controleren", + "check-repository-access-success": "Toegang tot repository succesvol geverifieerd!", + "delete-repository-settings-title": "Weet je zeker dat je repository-instellingen wilt verwijderen?", + "delete-repository-settings-text": "Opgelet, na de bevestiging worden de instellingen van het archief verwijderd en is de versiebeheerfunctie niet meer beschikbaar.", + "auto-commit-settings": "Instellingen voor automatisch vastleggen", + "auto-commit": "Automatisch vastleggen", + "auto-commit-entities": "Entiteiten automatisch vastleggen", + "no-auto-commit-entities-prompt": "Geen entiteiten geconfigureerd voor automatisch vastleggen", + "delete-auto-commit-settings-title": "Weet je zeker dat je instellingen voor automatisch vastleggen wilt verwijderen?", + "delete-auto-commit-settings-text": "Opgelet, na de bevestiging worden de instellingen voor automatisch vastleggen verwijderd en wordt automatisch vastleggen uitgeschakeld voor alle entiteiten.", + "2fa": { + "2fa": "Twee-factor-authenticatie", + "available-providers": "Beschikbare providers", + "issuer-name": "Naam van de uitgever", + "issuer-name-required": "De naam van de uitgever is vereist.", + "max-verification-failures-before-user-lockout": "Max. aantal verificatiefouten vóór gebruikersvergrendeling", + "max-verification-failures-before-user-lockout-pattern": "Het maximum aantal mislukte verificaties moet een positief geheel getal zijn.", + "number-of-checking-attempts": "Aantal controlepogingen", + "number-of-checking-attempts-pattern": "Het aantal controlepogingen moet een positief geheel getal zijn.", + "number-of-checking-attempts-required": "Het aantal controlepogingen is vereist.", + "number-of-codes": "Aantal codes", + "number-of-codes-pattern": "Het aantal codes moet een positief geheel getal zijn.", + "number-of-codes-required": "Aantal codes is vereist.", + "provider": "Aanbieder", + "retry-verification-code-period": "Verificatiecodeperiode opnieuw proberen (sec)", + "retry-verification-code-period-pattern": "Minimale tijdsduur is 5 sec", + "retry-verification-code-period-required": "De periode van de verificatiecode voor opnieuw proberen is vereist.", + "total-allowed-time-for-verification": "Totale toegestane tijd voor verificatie (sec)", + "total-allowed-time-for-verification-pattern": "Minimaal toegestane tijd is 60 sec", + "total-allowed-time-for-verification-required": "De totale toegestane tijd is vereist.", + "use-system-two-factor-auth-settings": "Tweefactorauthenticatie-instellingen van het systeem gebruiken", + "verification-code-check-rate-limit": "Snelheidslimiet voor verificatiecodecontrole", + "verification-code-lifetime": "Levensduur verificatiecode (sec)", + "verification-code-lifetime-pattern": "De levensduur van de verificatiecode moet een positief geheel getal zijn.", + "verification-code-lifetime-required": "De levensduur van de verificatiecode is vereist.", + "verification-message-template": "Sjabloon voor verificatiebericht", + "verification-limitations": "Beperkingen voor verificatie", + "verification-message-template-pattern": "Verificatiebericht moet patroon bevatten: ${code}", + "verification-message-template-required": "Verificatieberichtsjabloon is vereist.", + "within-time": "Binnen de tijd (sec)", + "within-time-pattern": "Tijd moet een positief geheel getal zijn.", + "within-time-required": "Er is tijd nodig." + }, + "jwt": { + "security-settings": "JWT-beveiligingsinstellingen", + "issuer-name": "Naam van de uitgever", + "issuer-name-required": "De naam van de uitgever is vereist.", + "signings-key": "Sleutel ondertekenen", + "signings-key-hint": "Base64-gecodeerde tekenreeks die ten minste 256 bits aan gegevens vertegenwoordigt.", + "signings-key-required": "Ondertekeningssleutel is vereist.", + "signings-key-min-length": "De ondertekeningssleutel moet ten minste 256 bits aan gegevens bevatten.", + "signings-key-base64": "De ondertekeningssleutel moet de base64-indeling hebben.", + "expiration-time": "Vervaltijd token (sec)", + "expiration-time-required": "De vervaltijd van het token is vereist.", + "expiration-time-pattern": "De vervaltijd van het token is een positief geheel getal.", + "expiration-time-min": "De minimale tijd is 60 seconden (1 minuut).", + "refresh-expiration-time": "Vervaltijd token vernieuwen (sec)", + "refresh-expiration-time-required": "De vervaltijd van het vernieuwingstoken is vereist.", + "refresh-expiration-time-pattern": "De vervaltijd van het token vernieuwen is een positief geheel getal.", + "refresh-expiration-time-min": "De minimale tijd is 900 seconden (15 minuten).", + "refresh-expiration-time-less-token": "De tokentijd voor vernieuwen moet een grotere tokentijd zijn.", + "generate-key": "Sleutel genereren", + "info-header": "Alle gebruikers moeten opnieuw inloggen", + "info-message": "Wijziging van de JWT-ondertekeningssleutel zorgt ervoor dat alle uitgegeven tokens ongeldig zijn. Alle gebruikers moeten opnieuw inloggen. Dit heeft ook gevolgen voor scripts die gebruikmaken van Rest API/Websockets." + }, + "resources": "Weg", + "notifications": "Meldingen", + "notifications-settings": "Instellingen voor meldingen", + "slack-api-token": "Slack API-token", + "slack": "Los", + "slack-settings": "Slack-instellingen" + }, + "alarm": { + "alarm": "Alarm", + "alarms": "Alarmen", + "all-alarms": "Alle alarmen", + "select-alarm": "Selecteer alarm", + "no-alarms-matching": "Er zijn geen alarmen gevonden die overeenkomen met '{{entity}}'.", + "alarm-required": "Alarm is vereist", + "alarm-filter": "Alarm filter", + "filter": "Filter", + "alarm-status": "Alarmstatus", + "alarm-status-list": "Lijst met alarmstatussen", + "any-status": "Elke status", + "search-status": { + "ANY": "Enig", + "ACTIVE": "Actief", + "CLEARED": "Uitgeschakeld", + "ACK": "Erkend", + "UNACK": "Niet erkend" + }, + "display-status": { + "ACTIVE_UNACK": "Actief Niet erkend", + "ACTIVE_ACK": "Actief Erkend", + "CLEARED_UNACK": "Gewist Niet bevestigd", + "CLEARED_ACK": "Gewist Erkend" + }, + "no-alarms-prompt": "Geen alarmen gevonden", + "created-time": "Gecreëerde tijd", + "type": "Type", + "severity": "Strengheid", + "originator": "Opdrachtgever", + "originator-type": "Type opsteller", + "details": "Details", + "originator-label": "Etiket van de afzender", + "assign": "Toewijzen", + "assignments": "Toewijzingen", + "assignee": "Gevolmachtigde", + "assignee-id": "Verantwoordelijke ID", + "assignee-first-name": "Voornaam van de gevolmachtigde", + "assignee-last-name": "Achternaam van de cessionaris", + "assignee-email": "E-mailadres van de verantwoordelijke", + "unassigned": "Toegewezen", + "assignee-not-set": "Alle", + "status": "Status", + "alarm-details": "Details van het alarm", + "start-time": "Begintijd", + "assign-time": "Tijd toewijzen", + "end-time": "Eindtijd", + "ack-time": "Erkende tijd", + "clear-time": "Vrijgemaakte tijd", + "duration": "Duur", + "alarm-severity-list": "Lijst met alarmernst", + "any-severity": "Elke ernst", + "severity-critical": "Kritisch", + "severity-major": "Majoor", + "severity-minor": "Minderjarige", + "severity-warning": "Waarschuwing", + "severity-indeterminate": "Onbepaalde", + "acknowledge": "Erkennen", + "clear": "Duidelijk", + "search": "Alarmen zoeken", + "selected-alarms": "{ count, plural, =1 {1 alarm} andere {# alarms} } geselecteerd", + "no-data": "Geen gegevens om weer te geven", + "polling-interval": "Polling-interval alarmen (sec)", + "polling-interval-required": "Alarmen polling-interval is vereist.", + "min-polling-interval-message": "Minimaal 1 sec polling-interval is toegestaan.", + "aknowledge-alarms-title": "Erken { count, plural, =1 {1 alarm} andere {# alarms} }", + "aknowledge-alarms-text": "Weet je zeker dat je { count, plural, =1 {1 alarm} andere {# alarms} } wilt erkennen?", + "aknowledge-alarm-title": "Alarm bevestigen", + "aknowledge-alarm-text": "Weet u zeker dat u Alarm wilt erkennen?", + "clear-alarms-title": "Wis { count, plural, =1 {1 alarm} andere {# alarms} }", + "clear-alarms-text": "Weet u zeker dat u { count, plural, =1 {1 alarm} andere {# alarms} } wilt wissen?", + "clear-alarm-title": "Alarm wissen", + "clear-alarm-text": "Weet u zeker dat u Alarm wilt wissen?", + "alarm-status-filter": "Alarm Status Filter", + "alarm-filter-title": "Alarm Filter", + "assigned": "Toegewezen", + "filter-title": "Filter", + "max-count-load": "Maximaal aantal te laden alarmen (0 - onbeperkt)", + "max-count-load-required": "Er is een maximaal aantal alarmen vereist om te laden.", + "max-count-load-error-min": "Minimale waarde is 0.", + "fetch-size": "Ophaal grootte", + "fetch-size-required": "Ophaal grootte is vereist.", + "fetch-size-error-min": "Minimale waarde is 10.", + "alarm-type-list": "Lijst met alarmtypen", + "any-type": "Elk type", + "assigned-to-current-user": "Toegewezen aan huidige gebruiker", + "assigned-to-me": "Aan mij toegewezen", + "search-propagated-alarms": "Doorgegeven alarmen zoeken", + "comments": "Alarm opmerkingen", + "show-more": "Meer tonen", + "additional-info": "Aanvullende informatie" + }, + "alarm-activity": { + "add": "Voeg een reactie...", + "alarm-comment": "Alarm commentaar", + "comments": "Opmerkingen", + "delete-alarm-comment": "Wil je deze reactie verwijderen?", + "refresh": "Vernieuwen", + "oldest-first": "Oudste eerst", + "newest-first": "Nieuwste eerst", + "activity": "Activiteit", + "export": "Exporteren naar CSV", + "author": "Auteur", + "created-date": "Datum van aanmaak", + "edited-date": "Bewerkte datum", + "text": "Sms", + "system": "Systeem" + }, + "alias": { + "add": "Alias toevoegen", + "edit": "Alias bewerken", + "name": "Alias naam", + "name-required": "Aliasnaam is vereist", + "duplicate-alias": "Alias met dezelfde naam bestaat al.", + "filter-type-single-entity": "Eén entiteit", + "filter-type-entity-group": "Entiteiten van de groep", + "filter-type-entity-list": "Lijst met entiteiten", + "filter-type-entity-name": "Naam van de entiteit", + "filter-type-entity-type": "Type entiteit", + "filter-type-entity-group-list": "Lijst met entiteitsgroepen", + "filter-type-entity-group-name": "Naam van entiteitsgroep", + "filter-type-entities-by-group-name": "Entiteiten op groepsnaam", + "filter-type-state-entity": "Entiteit vanuit dashboardstatus", + "filter-type-state-entity-description": "Entiteit die is overgenomen uit de statusparameters van het dashboard", + "filter-type-state-entity-owner": "Eigenaar van entiteit vanuit dashboardstatus", + "filter-type-state-entity-owner-description": "Eigenaar van entiteit die is overgenomen uit de parameters van de dashboardstatus", + "filter-type-asset-type": "Type asset", + "filter-type-asset-type-description": "Asset van het type \"{{assetTypes}}\"", + "filter-type-asset-type-and-name-description": "Asset van het type '{{assetTypes}}' en waarvan de naam begint met '{{prefix}}'", + "filter-type-device-type": "Type device", + "filter-type-device-type-description": "Devices van het type \"{{deviceTypes}}\"", + "filter-type-device-type-and-name-description": "Devices van het type '{{deviceTypes}}' en waarvan de naam begint met '{{prefix}}'", + "filter-type-entity-view-type": "Type entiteitsweergave", + "filter-type-entity-view-type-description": "Entiteitsweergaven van het type '{{entityViewTypes}}'", + "filter-type-entity-view-type-and-name-description": "Entiteitsweergaven van het type '{{entityViewTypes}}' en met een naam die begint met '{{prefix}}'", + "filter-type-edge-type": "Type edge", + "filter-type-edge-type-description": "Edge van het type \"{{edgeTypes}}\"", + "filter-type-edge-type-and-name-description": "Edge van het type '{{edgeTypes}}' en met de naam beginnend met '{{prefix}}'", + "filter-type-relations-query": "Query op relaties", + "filter-type-relations-query-description": "{{entities}} die {{relationType}} relatie hebben {{direction}} {{rootEntity}}", + "filter-type-edge-search-query": "Edge-zoekopdracht", + "filter-type-edge-search-query-description": "Edge met types {{edgeTypes}} die {{relationType}} relatie hebben {{direction}} {{rootEntity}}", + "filter-type-scheduler-event": "Scheduler-events", + "filter-type-scheduler-event-type-description": "Scheduler-events met het type '{{eventType}}'", + "filter-type-scheduler-event-originator-description": "Scheduler-gebeurtenissen van een specifieke afzender", + "filter-type-scheduler-event-type-originator-description": "Scheduler-gebeurtenissen van een specifieke afzender met '{{eventType}}'", + "filter-type-asset-search-query": "Zoekquery voor asset", + "filter-type-asset-search-query-description": "Asset met types {{assetTypes}} die {{relationType}} relatie hebben {{direction}} {{rootEntity}}", + "filter-type-device-search-query": "Zoekquery voor device", + "filter-type-device-search-query-description": "Devices met types {{deviceTypes}} die {{relationType}} relatie hebben {{direction}} {{rootEntity}}", + "filter-type-entity-view-search-query": "Zoekquery voor entiteitsweergave", + "filter-type-entity-view-search-query-description": "Entiteitsweergaven met types {{entityViewTypes}} die {{relationType}} relatie hebben {{direction}} {{rootEntity}}", + "filter-type-apiUsageState": "Api-gebruiksstatus", + "entity-filter": "Entiteit filteren", + "resolve-multiple": "Oplossen als meerdere entiteiten", + "filter-type": "Filter type", + "filter-type-required": "Filtertype is vereist.", + "entity-filter-no-entity-matched": "Er zijn geen entiteiten gevonden die overeenkomen met het opgegeven filter.", + "no-entity-filter-specified": "Geen entiteitsfilter opgegeven", + "root-state-entity": "Dashboardstatusentiteit gebruiken als hoofdmap", + "group-state-entity": "Dashboardstatusentiteit gebruiken als entiteitsgroep", + "group-state-entity-owner": "Dashboardstatusentiteit gebruiken als eigenaar van entiteitsgroep", + "last-level-relation": "Alleen relatie op het laatste niveau ophalen", + "root-entity": "Hoofdentiteit", + "state-entity-parameter-name": "Naam van de parameter van de entiteit van de staat", + "default-state-entity": "Entiteit met standaardstatus", + "default-state-entity-group": "Entiteitsgroep standaardstatus", + "default-entity-parameter-name": "Standaard", + "max-relation-level": "Max. relatieniveau", + "unlimited-level": "Onbeperkt niveau", + "state-entity": "Entiteit voor dashboardstatus", + "entities-of-group-state-entity": "Entiteiten uit de entiteitsgroep van de dashboardstatus", + "all-entities": "Alle entiteiten", + "any-relation": "enig", + "originator": "Opdrachtgever", + "originator-state-entity": "Dashboardstatusentiteit gebruiken als afzender", + "scheduler-event-type": "Gebeurtenistype planner" + }, + "asset": { + "all": "Alle", + "all-assets": "Alle assets", + "groups": "Groepen", + "shared": "Gedeeld", + "asset": "Asset", + "assets": "Assets", + "management": "Vermogensbeheer", + "view-assets": "Assets bekijken", + "add": "Asset toevoegen", + "asset-type-max-length": "Het type asset moet kleiner zijn dan 256 tekens tekens", + "assign-to-customer": "Toewijzen aan klant", + "assign-asset-to-customer": "Asset(s) toewijzen aan klant", + "assign-asset-to-customer-text": "Selecteer de asset die u aan de klant wilt toewijzen", + "no-assets-text": "Geen asset gevonden", + "assign-to-customer-text": "Selecteer de klant om de asset toe te wijzen", + "public": "Publiek", + "assignedToCustomer": "Toegewezen aan klant", + "make-public": "Assets openbaar maken", + "make-private": "Assets privé maken", + "unassign-from-customer": "Toewijzing van klant ongedaan maken", + "delete": "Asset verwijderen", + "asset-public": "Asset is openbaar", + "asset-type": "Type asset", + "asset-type-required": "Het type asset is vereist.", + "select-asset-type": "Selecteer asset type", + "enter-asset-type": "Asset type invoeren", + "any-asset": "Elke asset", + "no-asset-types-matching": "Er zijn geen asset types gevonden die overeenkomen met '{{entitySubtype}}'.", + "asset-type-list-empty": "Er zijn geen asset types geselecteerd.", + "asset-types": "Soorten asset", + "name": "Naam", + "name-required": "Naam is verplicht.", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens tekens", + "label-max-length": "Etiket moet kleiner zijn dan 256 tekens tekens", + "description": "Omschrijving: __________", + "type": "Type", + "type-required": "Type is vereist.", + "details": "Detail", + "events": "Events", + "add-asset-text": "Nieuw asset toevoegen", + "asset-details": "Details van het bedrijfsmiddel", + "assign-assets": "Middelen toewijzen", + "assign-assets-text": "Wijs { count, plural, =1 {1 asset} andere {# assets} } toe aan de klant", + "assign-asset-to-edge-title": "Asset(s) toewijzen aan Edge", + "assign-asset-to-edge-text": "Selecteer de assets die u aan de edge wilt toewijzen", + "delete-assets": "Assets verwijderen", + "unassign-assets": "Toewijzing van assets ongedaan maken", + "unassign-assets-action-title": "Toewijzing { count, plural, =1 {1 asset} andere {# assets} } van klant ongedaan maken", + "assign-new-asset": "Nieuw asset toewijzen", + "delete-asset-title": "Weet je zeker dat je de asset '{{assetName}}' wilt verwijderen?", + "delete-asset-text": "Opgelet, na de bevestiging worden de asset en alle gerelateerde gegevens onherstelbaar.", + "delete-assets-title": "Weet u zeker dat u { count, plural, =1 {1 asset} andere {# assets} } wilt verwijderen?", + "delete-assets-action-title": "Verwijder { count, plural, =1 {1 asset} andere {# assets} }", + "delete-assets-text": "Opgelet, na de bevestiging worden alle geselecteerde assets verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "make-public-asset-title": "Weet je zeker dat je de asset '{{assetName}}' openbaar wilt maken?", + "make-public-asset-text": "Na de bevestiging worden de asset en alle bijbehorende gegevens openbaar en toegankelijk gemaakt voor anderen.", + "make-private-asset-title": "Weet je zeker dat je de asset '{{assetName}}' privé wilt maken?", + "make-private-asset-text": "Na de bevestiging worden de asset en al zijn gegevens privé gemaakt en zijn ze niet toegankelijk voor anderen.", + "unassign-asset-title": "Weet je zeker dat je de toewijzing van de asset '{{assetName}}' ongedaan wilt maken?", + "unassign-asset-text": "Na de bevestiging wordt de toewijzing van de asset ongedaan gemaakt en is het niet toegankelijk voor de klant.", + "unassign-asset": "Toewijzing van asset ongedaan maken", + "unassign-assets-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 asset} andere {# assets} } wilt opheffen?", + "unassign-assets-text": "Na de bevestiging worden alle geselecteerde assets ongedaan gemaakt en zijn ze niet toegankelijk voor de klant.", + "copyId": "Item-ID kopiëren", + "idCopiedMessage": "Item-ID is gekopieerd naar het klembord", + "select-asset": "Selecteer asset", + "no-assets-matching": "Er zijn geen assets gevonden die overeenkomen met '{{entity}}'.", + "asset-required": "Asset is vereist", + "name-starts-with": "Expressie van itemnaam", + "help-text": "Gebruik '%' naar behoefte: '%asset_name_contains%', '%asset_name_ends', 'asset_starts_with'.", + "search": "Assets zoeken", + "select-group-to-add": "Selecteer doelgroep om geselecteerde assets toe te voegen", + "select-group-to-move": "Selecteer de doelgroep om geselecteerde assets te verplaatsen", + "remove-assets-from-group": "Weet je zeker dat je { count, plural, =1 {1 asset} andere {# assets} } uit groep '{{entityGroup}}' wilt verwijderen?", + "group": "Groep van assets", + "list-of-groups": "{ count, plural, =1 {One asset group} andere {List of # asset groups} }", + "group-name-starts-with": "Asset groepen waarvan de naam begint met '{{prefix}}'", + "import": "Asset importeren", + "asset-file": "Asset bestand", + "label": "Etiket", + "assign-asset-to-edge": "Asset(s) toewijzen aan Edge", + "unassign-asset-from-edge": "Toewijzing van asset ongedaan maken", + "unassign-asset-from-edge-title": "Weet je zeker dat je de toewijzing van de asset '{{assetName}}' ongedaan wilt maken?", + "unassign-asset-from-edge-text": "Na de bevestiging wordt de toewijzing van de asset ongedaan gemaakt en is het niet toegankelijk via de edge.", + "unassign-assets-from-edge-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 asset} andere {# assets} } wilt opheffen?", + "unassign-assets-from-edge-text": "Na de bevestiging worden alle geselecteerde assets ongedaan gemaakt en zijn ze niet toegankelijk via de edge.", + "selected-assets": "{ count, plural, =1 {1 asset} andere {# assets} } geselecteerd" + }, + "attribute": { + "attributes": "Attributen", + "latest-telemetry": "Nieuwste telemetrie", + "attributes-scope": "Bereik van entiteits attributen", + "scope-latest-telemetry": "Nieuwste telemetrie", + "scope-client": "Attributen van de klant", + "scope-server": "Server-attributen", + "scope-shared": "Gedeelde attributen", + "add": "Attribuut toevoegen", + "add-attribute-prompt": "Voeg attribuut toe", + "key": "Sleutel", + "key-max-length": "Sleutel moet kleiner zijn dan 256 tekens tekens", + "last-update-time": "Laatste update tijd", + "key-required": "Attribuutsleutel is vereist.", + "value": "Waarde", + "value-required": "Kenmerkwaarde is vereist.", + "delete-attributes-title": "Weet u zeker dat u { count, plural, =1 {1 attribute} andere {# attributes} } wilt verwijderen?", + "delete-attributes-text": "Opgelet, na de bevestiging worden alle geselecteerde attributen verwijderd.", + "delete-attributes": "Attributen verwijderen", + "enter-attribute-value": "Kenmerkwaarde invoeren", + "show-on-widget": "Toon op widget", + "widget-mode": "Widget-modus", + "next-widget": "Volgende widget", + "prev-widget": "Vorige widget", + "add-to-dashboard": "Toevoegen aan dashboard", + "add-widget-to-dashboard": "Widget toevoegen aan dashboard", + "selected-attributes": "{ count, plural, =1 {1 attribute} andere {# attributes} } geselecteerd", + "selected-telemetry": "{ count, plural, =1 {1 telemetry unit} andere {# telemetry units} } geselecteerd", + "no-attributes-text": "Geen attributen gevonden", + "no-telemetry-text": "Geen telemetrie gevonden", + "copy-key": "Kopieer sleutel", + "copy-value": "Waarde kopiëren" + }, + "api-usage": { + "api-features": "API-functies", + "api-usage": "API-gebruik", + "alarm": "Alarm", + "alarms-created": "Alarmen gemaakt", + "alarms-created-daily-activity": "Alarmen creëerden dagelijkse activiteit", + "alarms-created-hourly-activity": "Alarmen creëerden activiteit per uur", + "alarms-created-monthly-activity": "Alarmen creëerden maandelijkse activiteit", + "data-points": "Datapunten", + "data-points-storage-days": "Opslagdagen voor datapunten", + "device-api": "Device-API", + "email": "E-mail", + "email-messages": "E-mailberichten", + "email-messages-daily-activity": "Dagelijkse activiteit e-mailberichten", + "email-messages-monthly-activity": "Maandelijkse activiteit e-mailberichten", + "exceptions": "Uitzonderingen", + "executions": "Executies", + "javascript": "JavaScript", + "javascript-executions": "JavaScript-uitvoeringen", + "javascript-functions": "JavaScript-functies", + "javascript-functions-daily-activity": "JavaScript-functies dagelijkse activiteit", + "javascript-functions-hourly-activity": "JavaScript-functies activiteit per uur", + "javascript-functions-monthly-activity": "JavaScript-functies maandelijkse activiteit", + "latest-error": "Laatste error", + "messages": "Berichten", + "notifications": "Meldingen", + "notifications-email-sms": "Meldingen (e-mail/sms)", + "notifications-hourly-activity": "Meldingen activiteit per uur", + "permanent-failures": "${entityName} Permanente storingen", + "permanent-timeouts": "Permanente time-outs van $ {entityName}", + "processing-failures": "${entityName} Verwerkingsfouten", + "processing-failures-and-timeouts": "Verwerkingsfouten en time-outs", + "processing-timeouts": "${entityName} time-outs voor verwerking", + "queue-stats": "Queue Statistieken", + "rule-chain": "Rule chain", + "rule-engine": "Rule engine", + "rule-engine-daily-activity": "Dagelijkse activiteit van de rule engine", + "rule-engine-executions": "Uitvoeringen van rule engine", + "rule-engine-hourly-activity": "Rule engine uurlijkse activiteit", + "rule-engine-monthly-activity": "Maandelijkse activiteit van Rule Engine", + "rule-engine-statistics": "Rule Engine-statistieken", + "rule-node": "Regel Knooppunt", + "sms": "SMS", + "sms-messages": "SMS-berichten", + "sms-messages-daily-activity": "Dagelijkse activiteit SMS-berichten", + "sms-messages-monthly-activity": "SMS-berichten maandelijkse activiteit", + "successful": "${entityName} Succesvol", + "telemetry": "Telemetrie", + "telemetry-persistence": "Persistentie van telemetrie", + "telemetry-persistence-daily-activity": "Dagelijkse activiteit met behoud van telemetrie", + "telemetry-persistence-hourly-activity": "Telemetriepersistentie activiteit per uur", + "telemetry-persistence-monthly-activity": "Maandelijkse activiteit voor telemetriepersistentie", + "transport": "Vervoer", + "transport-daily-activity": "Vervoer dagelijkse activiteit", + "transport-data-points": "Datapunten voor transport", + "transport-hourly-activity": "Vervoer per uur", + "transport-messages": "Berichten vervoeren", + "transport-monthly-activity": "Maandelijkse activiteit Transport", + "view-details": "Bekijk details", + "view-statistics": "Statistieken bekijken" + }, + "audit-log": { + "audit": "Audit", + "audit-logs": "Audit Logboeken", + "timestamp": "Tijdstempel", + "entity-type": "Type entiteit", + "entity-name": "Naam van de entiteit", + "user": "Gebruiker", + "type": "Type", + "status": "Status", + "details": "Details", + "type-added": "Toegevoegd", + "type-deleted": "Verwijderd", + "type-updated": "Bijgewerkt", + "type-attributes-updated": "Attributen geüpdatet", + "type-attributes-deleted": "Attributen verwijderd", + "type-rpc-call": "RPC-oproep", + "type-credentials-updated": "Inloggegevens bijgewerkt", + "type-assigned-to-customer": "Toegewezen aan klant", + "type-unassigned-from-customer": "Toewijzing van klant ongedaan gemaakt", + "type-assigned-to-edge": "Toegewezen aan Edge", + "type-unassigned-from-edge": "Toewijzing van Edge ongedaan gemaakt", + "type-activated": "Geactiveerd", + "type-suspended": "Latent", + "type-credentials-read": "Referenties gelezen", + "type-attributes-read": "Gelezen attributen", + "type-added-to-entity-group": "Toegevoegd aan groep", + "type-removed-from-entity-group": "Verwijderd uit groep", + "type-relation-add-or-update": "Relatie geüpdatet", + "type-relation-delete": "Relatie verwijderd", + "type-relations-delete": "Alle relaties verwijderd", + "type-alarm-ack": "Erkend", + "type-alarm-clear": "Uitgeschakeld", + "type-alarm-assign": "Toegewezen", + "type-alarm-unassign": "Toegewezen", + "type-added-comment": "Reactie toegevoegd", + "type-updated-comment": "Bijgewerkte reactie", + "type-deleted-comment": "Verwijderde reactie", + "type-rest-api-rule-engine-call": "REST API-aanroep van rule engine", + "type-made-public": "Openbaar gemaakt", + "type-made-private": "Privé gemaakt", + "type-login": "Inloggen", + "type-logout": "Logout", + "type-lockout": "Lockout", + "status-success": "Succes", + "status-failure": "Fout", + "audit-log-details": "Details van het auditlogboek", + "no-audit-logs-prompt": "Geen logboeken gevonden", + "action-data": "Actie gegevens", + "failure-details": "Details van de fout", + "search": "Auditlogboeken doorzoeken", + "clear-search": "Zoekopdracht wissen", + "type-assigned-from-tenant": "Toegewezen door tenant", + "type-assigned-to-tenant": "Toegewezen aan tenant", + "type-provision-success": "Device ingericht", + "type-provision-failure": "Het inrichten van devices is mislukt", + "type-timeseries-updated": "Telemetrie bijgewerkt", + "type-timeseries-deleted": "Telemetrie verwijderd", + "type-owner-changed": "Eigenaar gewijzigd" + }, + "confirm-on-exit": { + "message": "U hebt niet-opgeslagen wijzigingen. Weet je zeker dat je deze pagina wilt verlaten?", + "html-message": "U hebt niet-opgeslagen wijzigingen.
Weet je zeker dat je deze pagina wilt verlaten?", + "title": "Niet-opgeslagen wijzigingen" + }, + "contact": { + "country": "Land", + "city": "Stad", + "state": "Staat / Provincie", + "postal-code": "Postcode", + "postal-code-invalid": "Ongeldige postcode notatie.", + "address": "Adres", + "address2": "Adres 2", + "phone": "Telefoon", + "email": "E-mail", + "no-address": "Geen adres", + "state-max-length": "De lengte van de staat moet kleiner zijn dan 256 tekens tekens", + "phone-max-length": "Telefoonnummer moet minder zijn dan 256 tekens tekens", + "city-max-length": "De opgegeven stad moet kleiner zijn dan 256 tekens tekens" + }, + "common": { + "username": "Gebruikersnaam", + "password": "Wachtwoord", + "enter-username": "Gebruikersnaam invoeren", + "enter-password": "Wachtwoord invoeren", + "enter-search": "Zoekopdracht invoeren", + "created-time": "Gecreëerde tijd", + "loading": "Laden...", + "proceed": "Doorgaan", + "open-details-page": "Detailpagina openen" + }, + "converter": { + "converter": "Gegevens converteren", + "converters": "Data-converters", + "select-converter": "Selecteer gegevensomzetter", + "no-converters-matching": "Er zijn geen gegevensconverters gevonden die overeenkomen met '{{entity}}'.", + "no-converters-found": "Geen dataconverters gevonden.", + "converter-required": "Dataconverter is vereist", + "delete": "Converter verwijderen", + "management": "Beheer van dataconverters", + "add-converter-text": "Nieuwe gegevensconverter toevoegen", + "no-converters-text": "Geen dataconverters gevonden", + "selected-converters": "{ count, plural, =1 {1 data converter} andere {# data converters} } geselecteerd", + "delete-converter-title": "Weet u zeker dat u de dataconverter '{{converterName}}' wilt verwijderen?", + "delete-converter-text": "Opgelet, na de bevestiging worden de gegevensomzetter en alle gerelateerde gegevens onherstelbaar.", + "delete-converters-title": "Weet u zeker dat u { count, plural, =1 {1 data converter} andere {# data converters} } wilt verwijderen?", + "delete-converters-action-title": "Verwijder { count, plural, =1 {1 data converter} andere {# data converters} }", + "delete-converters-text": "Opgelet, na de bevestiging worden alle geselecteerde gegevensconverters verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "events": "Events", + "add": "Gegevensconverter toevoegen", + "search": "Gegevensconverters zoeken", + "converter-details": "Details van de gegevensconverter", + "details": "Details", + "copyId": "Kopieer converter-ID", + "idCopiedMessage": "Converter-ID is gekopieerd naar klembord", + "debug-mode": "Foutopsporingsmodus", + "created-time": "Gecreëerde tijd", + "name": "Naam", + "name-required": "Naam is verplicht.", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "description": "Omschrijving: __________", + "decoder": "Decoder", + "encoder": "Coderingsprogramma", + "test-decoder-fuction": "Test decoder functie", + "test-encoder-fuction": "Encoderfunctie testen", + "decoder-input-params": "Ingangsparameters decoder", + "encoder-input-params": "Ingangsparameters van de encoder", + "payload": "Nettolading", + "payload-content-type": "Inhoudstype payload", + "payload-content": "Inhoud van payload", + "message": "Bericht", + "message-type": "Soort bericht", + "message-type-required": "Berichttype is vereist", + "test": "Test", + "metadata": "Metagegevens", + "metadata-required": "Metagegevensvermeldingen mogen niet leeg zijn.", + "integration-metadata": "Integratie metadata", + "integration-metadata-required": "Vermeldingen in integratiemetagegevens mogen niet leeg zijn.", + "output": "Uitvoer", + "import": "Converter importeren", + "export": "Converter exporteren", + "export-failed-error": "Kan converter niet exporteren: {{error}}", + "create-new-converter": "Nieuwe converter maken", + "converter-file": "Converter bestand", + "invalid-converter-file-error": "Kan converter niet importeren: Ongeldige gegevensstructuur van converter.", + "type": "Type", + "type-required": "Type is vereist.", + "type-uplink": "Uplink", + "type-downlink": "Downlink" + }, + "content-type": { + "json": "Json", + "text": "Sms", + "binary": "Binair (Base64)" + }, + "color": { + "color-picker": "Kleurkiezer", + "primary-colors": "Primaire kleuren", + "accent-colors": "Accent kleuren", + "no-color-selected": "Geen kleur geselecteerd" + }, + "customer": { + "all": "Alle", + "all-customers": "Alle klanten", + "groups": "Groepen", + "shared": "Gedeeld", + "hierarchy": "Hiërarchie", + "customer": "Klant", + "customers": "Klanten", + "management": "Klantenbeheer", + "dashboard": "Klantendashboard", + "dashboards": "Dashboards voor klanten", + "devices": "Devices van klanten", + "entity-views": "Weergaven van klantentiteiten", + "assets": "Assets van klanten", + "public-dashboards": "Openbare dashboards", + "public-devices": "Openbare devices", + "public-assets": "Publieke assets", + "public-entity-views": "Weergaven van openbare entiteit-views", + "add": "Klant toevoegen", + "delete": "Klant verwijderen", + "manage-customer-user-groups": "Gebruikersgroepen van klanten beheren", + "manage-customer-groups": "Klantgroepen beheren", + "manage-customer-device-groups": "Asset groepen van klanten beheren", + "manage-customer-asset-groups": "Asset groepen van klanten beheren", + "manage-customer-entity-view-groups": "Weergavegroepen voor klantentiteiten beheren", + "manage-customer-edge-groups": "Edge-groepen voor klanten beheren", + "manage-customer-dashboard-groups": "Groepen klantendashboards beheren", + "manage-customer-users": "Klantgebruikers beheren", + "manage-customers": "Klanten beheren", + "manage-customer-devices": "Devices van klanten beheren", + "manage-customer-entity-views": "Weergaven van klantentiteiten beheren", + "manage-customer-dashboards": "Klantdashboards beheren", + "manage-public-devices": "Openbare devices beheren", + "manage-public-dashboards": "Openbare dashboards beheren", + "manage-customer-assets": "Klant devices beheren", + "manage-customer-edges": "Beheer klant edges", + "manage-public-assets": "Openbare asset beheren", + "add-customer-text": "Nieuwe klant toevoegen", + "no-customers-text": "Geen klanten gevonden", + "customer-details": "Klantgegevens", + "delete-customer-title": "Weet je zeker dat je de '{{customerTitle}}' van de klant wilt verwijderen?", + "delete-customer-text": "Let op, na de bevestiging worden de klant en alle gerelateerde gegevens onherstelbaar.", + "delete-customers-title": "Weet u zeker dat u { count, plural, =1 {1 customer} andere {# customers} } wilt verwijderen?", + "delete-customers-action-title": "Verwijder { count, plural, =1 {1 customer} andere {# customers} }", + "delete-customers-text": "Opgelet, na de bevestiging worden alle geselecteerde klanten verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "manage-user-groups": "Gebruikersgroepen beheren", + "manage-asset-groups": "Asset groepen beheren", + "manage-device-groups": "Asset groepen beheren", + "manage-dashboard-groups": "Dashboardgroepen beheren", + "manage-entity-view-groups": "Entiteitsweergavegroepen beheren", + "manage-edge-groups": "Edge-groepen beheren", + "manage-users": "Gebruikers beheren", + "manage-assets": "Assets beheren", + "manage-devices": "Devices beheren", + "manage-dashboards": "Dashboards beheren", + "manage-entity-views": "Entiteitsweergaven beheren", + "title": "Titel", + "title-required": "Titel is vereist.", + "title-max-length": "Titel moet kleiner zijn dan 256 tekens", + "description": "Omschrijving: __________", + "details": "Details", + "events": "Events", + "copyId": "Kopieer klant-ID", + "idCopiedMessage": "Klant-ID is gekopieerd naar klembord", + "select-customer": "Selecteer klant", + "no-customers-matching": "Er zijn geen klanten gevonden die overeenkomen met '{{entity}}'.", + "customer-required": "Klant is verplicht", + "select-group-to-add": "Selecteer doelgroep om geselecteerde klanten toe te voegen", + "select-group-to-move": "Selecteer doelgroep om geselecteerde klanten te verhuizen", + "remove-customers-from-group": "Weet je zeker dat je { count, plural, =1 {1 customer} andere {# customers} } uit groep '{{entityGroup}}' wilt verwijderen?", + "group": "Groep klanten", + "list-of-groups": "{ count, plural, =1 {One customer group} andere {List of # customer groups} }", + "group-name-starts-with": "Klantgroepen waarvan de naam begint met '{{prefix}}'", + "select-default-customer": "Selecteer standaardklant", + "default-customer": "Standaard klant", + "default-customer-required": "Standaardklant is vereist om fouten op te sporen in het dashboard op tenantniveau", + "allow-white-labeling": "White Labeling toestaan", + "search": "Klanten zoeken", + "selected-customers": "{ count, plural, =1 {1 customer} andere {# customers} } geselecteerd", + "edges": "Edge-instanties van de klant", + "manage-edges": "Edge beheren" + }, + "customers-hierarchy": { + "customers-hierarchy": "Hiërarchie van klanten", + "open-nav-tree": "Navigatiestructuur openen", + "return-to-top-level": "Terug naar het hoogste niveau" + }, + "custom-menu": { + "custom-menu": "Aangepast menu", + "custom-menu-hint": "Definieer hieronder de JSON van het aangepaste menu. Deze JSON bevat een lijst met aangepaste menu-items." + }, + "custom-translation": { + "custom-translation": "Aangepaste vertaling", + "translation-map": "Vertaling kaart", + "key": "Vertaling sleutel", + "import": "Vertaling importeren", + "export": "Vertaling exporteren", + "export-data": "Vertaalgegevens exporteren", + "import-data": "Vertaalgegevens importeren", + "translation-file": "Vertaal bestand", + "invalid-translation-file-error": "Kan vertaalbestand niet importeren: Ongeldige gegevensstructuur voor vertalingen.", + "custom-translation-hint": "Definieer hieronder de JSON voor aangepaste vertalingen. Deze JSON overschrijft de standaardvertaling. Klik op 'Download locale file' om een bestaande vertaling te krijgen. U kunt het gedownloade bestand ook gebruiken als referentie voor beschikbare sleutel-waardeparen voor vertalingen.", + "download-locale-file": "Landinstellingsbestand downloaden" + }, + "datetime": { + "date-from": "Datum van", + "time-from": "Tijd van", + "date-to": "Datum tot", + "time-to": "Tijd om" + }, + "dashboard": { + "all": "Alle", + "all-dashboards": "Alle dashboards", + "groups": "Groepen", + "shared": "Gedeeld", + "dashboard": "Dashboard", + "dashboards": "Dashboards", + "management": "Beheer van dashboards", + "view-dashboards": "Dashboards bekijken", + "add": "Dashboard toevoegen", + "assign-dashboard-to-customer": "Dashboard(s) toewijzen aan klant", + "assign-dashboard-to-customer-text": "Selecteer de dashboards die u aan de klant wilt toewijzen", + "assign-to-customer-text": "Selecteer de klant om de dashboard(s) toe te wijzen", + "assign-to-customer": "Toewijzen aan klant", + "unassign-from-customer": "Toewijzing van klant ongedaan maken", + "make-public": "Dashboard openbaar maken", + "make-private": "Dashboard privé maken", + "manage-assigned-customers": "Toegewezen klanten beheren", + "assigned-customers": "Toegewezen klanten", + "assign-to-customers": "Dashboard(s) toewijzen aan klanten", + "assign-to-customers-text": "Selecteer de klanten om de dashboard(s) toe te wijzen", + "unassign-from-customers": "Toewijzing van dashboard(s) van klanten ongedaan maken", + "unassign-from-customers-text": "Selecteer de klanten die u wilt opheffen in de dashboard(s)", + "no-dashboards-text": "Geen dashboards gevonden", + "no-widgets": "Geen widgets geconfigureerd", + "add-widget": "Nieuwe widget toevoegen", + "title": "Titel", + "image": "Dashboard afbeelding", + "mobile-app-settings": "Instellingen voor mobiele applicaties", + "mobile-order": "Dashboardbestelling in mobiele applicatie", + "mobile-hide": "Dashboard verbergen in mobiele applicatie", + "update-image": "Dashboardafbeelding bijwerken", + "take-screenshot": "Screenshot maken", + "select-widget-title": "Selecteer widget", + "select-widget-value": "{{title}}: Widget selecteren", + "select-widget-subtitle": "Lijst met beschikbare widgettypen", + "delete": "Dashboard verwijderen", + "title-required": "Titel is vereist.", + "title-max-length": "Titel moet kleiner zijn dan 256 tekens tekens", + "description": "Omschrijving: __________", + "details": "Details", + "dashboard-details": "Details van het dashboard", + "add-dashboard-text": "Nieuw dashboard toevoegen", + "assign-dashboards": "Dashboards toewijzen", + "assign-new-dashboard": "Nieuw dashboard toewijzen", + "assign-dashboards-text": "Wijs { count, plural, =1 {1 dashboard} andere {# dashboards} } toe aan klanten", + "unassign-dashboards-action-text": "Toewijzing { count, plural, =1 {1 dashboard} andere {# dashboards} } van klanten ongedaan maken", + "delete-dashboards": "Dashboards verwijderen", + "unassign-dashboards": "Toewijzing van dashboards ongedaan maken", + "unassign-dashboards-action-title": "Toewijzing { count, plural, =1 {1 dashboard} andere {# dashboards} } van klant ongedaan maken", + "delete-dashboard-title": "Weet je zeker dat je de '{{dashboardTitle}}' van het dashboard wilt verwijderen?", + "delete-dashboard-text": "Opgelet, na de bevestiging worden het dashboard en alle gerelateerde gegevens onherstelbaar.", + "delete-dashboards-title": "Weet u zeker dat u { count, plural, =1 {1 dashboard} andere {# dashboards} } wilt verwijderen?", + "delete-dashboards-action-title": "Verwijder { count, plural, =1 {1 dashboard} andere {# dashboards} }", + "delete-dashboards-text": "Opgelet, na de bevestiging worden alle geselecteerde dashboards verwijderd en worden alle gerelateerde gegevens onherstelbaar.", + "unassign-dashboard-title": "Weet u zeker dat u de toewijzing van het dashboard '{{dashboardTitle}}' wilt opheffen?", + "unassign-dashboard-text": "Na de bevestiging wordt de toewijzing van het dashboard ongedaan gemaakt en is het niet toegankelijk voor de klant.", + "unassign-dashboard": "Toewijzing dashboard ongedaan maken", + "unassign-dashboards-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 dashboard} andere {# dashboards} } wilt opheffen?", + "unassign-dashboards-text": "Na de bevestiging worden alle geselecteerde dashboards ongedaan gemaakt en zijn ze niet toegankelijk voor de klant.", + "public-dashboard-title": "Dashboard is nu openbaar", + "public-dashboard-text": "De {{dashboardTitle}} van uw dashboard is nu openbaar en toegankelijk via de volgende openbare link:", + "public-dashboard-notice": "notitie: Vergeet niet om gerelateerde devices openbaar te maken om toegang te krijgen tot hun gegevens.", + "public-dashboard-link": "Koppeling naar openbaar dashboard", + "public-dashboard-link-text": "Uw openbare dashboard {{dashboardTitle}} is toegankelijk via de volgende openbare link:", + "public-dashboard-link-notice": "notitie: Vergeet niet om gerelateerde Devices, asset en entiteitsweergaven openbaar te maken om toegang te krijgen tot hun gegevens.", + "make-private-dashboard-title": "Weet je zeker dat je het dashboard '{{dashboardTitle}}' privé wilt maken?", + "make-private-dashboard-text": "Na de bevestiging wordt het dashboard privé gemaakt en is het niet toegankelijk voor anderen.", + "make-private-dashboard": "Dashboard privé maken", + "socialshare-text": "'{{dashboardTitle}}' mogelijk gemaakt door ThingsBoard", + "socialshare-title": "'{{dashboardTitle}}' mogelijk gemaakt door ThingsBoard", + "select-dashboard": "Selecteer dashboard", + "no-dashboards-matching": "Er zijn geen dashboards gevonden die overeenkomen met '{{entity}}'.", + "dashboard-required": "Dashboard is vereist.", + "select-existing": "Bestaand dashboard selecteren", + "create-new": "Nieuw dashboard maken", + "new-dashboard-title": "Nieuwe dashboardtitel", + "open-dashboard": "Dashboard openen", + "set-background": "Achtergrond instellen", + "background-color": "Achtergrondkleur", + "background-image": "Achtergrondafbeelding", + "background-size-mode": "Modus voor achtergrondgrootte", + "no-image": "Geen afbeelding geselecteerd", + "empty-image": "Geen afbeelding", + "drop-image": "Zet een afbeelding neer of klik om een bestand te selecteren om te uploaden.", + "maximum-upload-file-size": "Maximale bestandsgrootte uploaden: {{ size }}", + "cannot-upload-file": "Kan bestand niet uploaden", + "settings": "Instellingen", + "layout-settings": "Lay-out instellingen", + "columns-count": "Aantal kolommen", + "columns-count-required": "Het aantal kolommen is vereist.", + "min-columns-count-message": "Er is slechts een minimum van 10 kolommen toegestaan.", + "max-columns-count-message": "Er is slechts een maximum van 1000 kolommen toegestaan.", + "widgets-margins": "Marge tussen widgets", + "margin-required": "Margewaarde is vereist.", + "min-margin-message": "Alleen 0 is toegestaan als minimale margewaarde.", + "max-margin-message": "Slechts 50 is toegestaan als maximale margewaarde.", + "horizontal-margin": "Horizontale marge", + "horizontal-margin-required": "Horizontale margewaarde is vereist.", + "min-horizontal-margin-message": "Alleen 0 is toegestaan als minimale horizontale margewaarde.", + "max-horizontal-margin-message": "Slechts 50 is toegestaan als maximale horizontale margewaarde.", + "vertical-margin": "Verticale marge", + "vertical-margin-required": "Verticale margewaarde is vereist.", + "min-vertical-margin-message": "Alleen 0 is toegestaan als minimale verticale margewaarde.", + "max-vertical-margin-message": "Slechts 50 is toegestaan als maximale verticale margewaarde.", + "apply-outer-margin": "Marges toepassen op de zijkanten van de lay-out", + "autofill-height": "Lay-outhoogte automatisch vullen", + "mobile-layout": "Mobiele lay-outinstellingen", + "mobile-row-height": "Mobiele rijhoogte, px", + "mobile-row-height-required": "De waarde van de rijhoogte van de mobiele rij is vereist.", + "min-mobile-row-height-message": "Er zijn slechts 5 pixels toegestaan als minimale waarde voor de rijhoogte van mobiele rijen.", + "max-mobile-row-height-message": "Er zijn slechts 200 pixels toegestaan als maximale waarde voor de rijhoogte van mobiele Devices.", + "title-settings": "Titelinstellingen", + "display-title": "Dashboardtitel weergeven", + "title-color": "Titel kleur", + "toolbar-settings": "Werkbalk-instellingen", + "hide-toolbar": "Werkbalk verbergen", + "toolbar-always-open": "Werkbalk open houden", + "display-dashboards-selection": "Dashboardselectie weergeven", + "display-entities-selection": "Selectie van weergave-entiteiten", + "display-filters": "Filters weergeven", + "display-dashboard-timewindow": "Tijdvenster weergeven", + "display-dashboard-export": "Export weergeven", + "display-update-dashboard-image": "Afbeelding van updatedashboard weergeven", + "dashboard-logo-settings": "Instellingen voor dashboardlogo's", + "display-dashboard-logo": "Logo weergeven in volledig scherm dashboard", + "dashboard-logo-image": "Afbeelding van het dashboardlogo", + "advanced-settings": "Geavanceerde instellingen", + "dashboard-css": "Dashboard CSS", + "import": "Dashboard importeren", + "export": "Dashboard exporteren", + "export-failed-error": "Dashboard kan niet worden geëxporteerd: {{error}}", + "export-pdf": "Exporteren als PDF", + "export-png": "Exporteren als PNG", + "export-jpg": "Exporteren als JPEG", + "export-json-config": "JSON-configuratie exporteren", + "download-dashboard-progress": "Dashboard genereren {{reportType}} ...", + "create-new-dashboard": "Nieuw dashboard maken", + "dashboard-file": "Dashboard bestand", + "invalid-dashboard-file-error": "Dashboard kan niet worden geïmporteerd: Ongeldige gegevensstructuur van het dashboard.", + "dashboard-import-missing-aliases-title": "Aliassen configureren die worden gebruikt door geïmporteerd dashboard", + "create-new-widget": "Nieuwe widget maken", + "import-widget": "Widget importeren", + "widget-file": "Widget bestand", + "invalid-widget-file-error": "Widget kan niet worden geïmporteerd: Ongeldige gegevensstructuur van de widget.", + "widget-import-missing-aliases-title": "Aliassen configureren die worden gebruikt door geïmporteerde widgets", + "open-toolbar": "Dashboardwerkbalk openen", + "close-toolbar": "Werkbalk sluiten", + "configuration-error": "Configuratie fout", + "alias-resolution-error-title": "Configuratiefout voor dashboardaliassen", + "invalid-aliases-config": "Kan geen devices vinden die overeenkomen met sommige aliassenfilter.
Neem contact op met uw beheerder om dit probleem op te lossen.", + "select-devices": "Devices selecteren", + "assignedToCustomer": "Toegewezen aan klant", + "assignedToCustomers": "Toegewezen aan klanten", + "public": "Publiek", + "copyId": "Dashboard-id kopiëren", + "idCopiedMessage": "Dashboard-id is gekopieerd naar klembord", + "public-link": "Openbare link", + "copy-public-link": "Kopieer openbare link", + "public-link-copied-message": "De openbare koppeling naar het dashboard is gekopieerd naar het klembord", + "manage-states": "Dashboardstatussen beheren", + "states": "Statussen van dashboards", + "search-states": "Statussen van zoekdashboard", + "selected-states": "{ count, plural, =1 {1 dashboard state} andere {# dashboard states} } geselecteerd", + "edit-state": "Dashboardstatus bewerken", + "delete-state": "Dashboardstatus verwijderen", + "add-state": "Dashboardstatus toevoegen", + "no-states-text": "Geen staten gevonden", + "state": "Status van het dashboard", + "state-name": "Naam", + "state-name-required": "De naam van de dashboardstatus is vereist.", + "state-id": "Staats-ID", + "state-id-required": "Status-id van het dashboard is vereist.", + "state-id-exists": "De status van het dashboard met dezelfde id bestaat al.", + "is-root-state": "Wortel staat", + "delete-state-title": "Dashboardstatus verwijderen", + "delete-state-text": "Weet u zeker dat u de status van het dashboard met de naam '{{stateName}}' wilt verwijderen?", + "show-details": "Details weergeven", + "hide-details": "Verberg details", + "select-state": "Selecteer de doelstatus", + "state-controller": "Controle van de staat", + "search": "Dashboards doorzoeken", + "selected-dashboards": "{ count, plural, =1 {1 dashboard} andere {# dashboards} } geselecteerd", + "home-dashboard": "Startpagina dashboard", + "home-dashboard-hide-toolbar": "Verberg de werkbalk van het startdashboard", + "select-group-to-add": "Selecteer doelgroep om geselecteerde dashboards toe te voegen", + "select-group-to-move": "Selecteer de doelgroep om geselecteerde dashboards te verplaatsen", + "remove-dashboards-from-group": "Weet je zeker dat je { count, plural, =1 {1 dashboard} andere {# dashboards} } uit groep '{{entityGroup}}' wilt verwijderen?", + "group": "Groep dashboards", + "list-of-groups": "{ count, plural, =1 {One dashboard group} andere {List of # dashboard groups} }", + "group-name-starts-with": "Dashboardgroepen waarvan de naam begint met '{{prefix}}'", + "unassign-dashboard-from-edge-text": "Na de bevestiging wordt de toewijzing van het dashboard ongedaan gemaakt en is het niet toegankelijk voor de edge.", + "unassign-dashboards-from-edge-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 dashboard} andere {# dashboards} } wilt opheffen?", + "unassign-dashboards-from-edge-text": "Na de bevestiging worden alle geselecteerde dashboards ongedaan gemaakt en zijn ze niet toegankelijk voor de edge.", + "assign-dashboard-to-edge": "Dashboard(s) toewijzen aan Edge", + "assign-dashboard-to-edge-text": "Selecteer de dashboards die u aan de edge wilt toewijzen", + "non-existent-dashboard-state-error": "Dashboardstatus met id '{{ stateId }}' is niet gevonden" + }, + "datakey": { + "settings": "Instellingen", + "advanced": "Geavanceerd", + "label": "Etiket", + "color": "Kleur", + "units": "Speciaal symbool om naast waarde weer te geven", + "decimals": "Aantal cijfers na drijvende komma", + "data-generation-func": "Functie voor het genereren van gegevens", + "use-data-post-processing-func": "Gebruik de functie voor het nabewerken van gegevens", + "configuration": "Configuratie van gegevenssleutels", + "timeseries": "Timeseries", + "attributes": "Attributen", + "entity-field": "Entiteit veld", + "alarm": "Alarmvelden", + "timeseries-required": "Timeseries van entiteiten zijn vereist.", + "timeseries-or-attributes-required": "Timeseries/attributen van entiteiten zijn vereist.", + "alarm-fields-timeseries-or-attributes-required": "Alarmvelden of tijdreeksen/attributen van entiteiten zijn vereist.", + "maximum-timeseries-or-attributes": "Maximaal { count, plural, =1 {1 timeseries/attribute is allowed.} andere {# timeseries/attributes are allowed} }", + "alarm-fields-required": "Alarmvelden zijn verplicht.", + "function-types": "Soorten functies", + "function-type": "Soort functie", + "function-types-required": "Functietypes zijn vereist.", + "alarm-keys": "Alarmgegevens toetsen", + "alarm-key": "Sleutel voor alarmgegevens", + "alarm-key-functions": "Functies van de alarmtoets", + "alarm-key-function": "Alarmtoets functie", + "latest-keys": "Nieuwste gegevenssleutels", + "latest-key": "Meest recente gegevenssleutel", + "latest-key-functions": "Nieuwste sleutelfuncties", + "latest-key-function": "Nieuwste toetsfunctie", + "timeseries-keys": "Gegevenssleutels voor tijdreeksen", + "timeseries-key": "Gegevenssleutel tijdreeksen", + "timeseries-key-functions": "Timeseries belangrijkste functies", + "timeseries-key-function": "Tijdreeks-sleutelfunctie", + "maximum-function-types": "Maximaal { count, plural, =1 {1 function type is allowed.} andere {# function types are allowed} }", + "time-description": "tijdstempel van de huidige waarde;", + "value-description": "de huidige waarde;", + "prev-value-description": "resultaat van de vorige functieaanroep;", + "time-prev-description": "tijdstempel van de vorige waarde;", + "prev-orig-value-description": "oorspronkelijke vorige waarde;", + "aggregation": "Aggregatie", + "aggregation-type-hint-common": "Om prestatieredenen is de berekening van de geaggregeerde waarden alleen beschikbaar voor vaste tijdsintervallen zoals 'huidige dag', 'huidige maand', enz., en niet voor schuifvensterintervallen zoals 'laatste 30 minuten' of 'laatste 24 uur'.", + "aggregation-type-none-hint": "Neem de laatste waarde.", + "aggregation-type-min-hint": "Zoek de minimumwaarde tussen gegevenspunten binnen een geselecteerd tijdvenster.", + "aggregation-type-max-hint": "Zoek de maximale waarde tussen gegevenspunten binnen een geselecteerd tijdvenster.", + "aggregation-type-avg-hint": "Bereken een gemiddelde waarde tussen gegevenspunten binnen een geselecteerd tijdvenster.", + "aggregation-type-sum-hint": "Tel alle waarden van de gegevenspunten binnen een geselecteerd tijdvenster bij elkaar op.", + "aggregation-type-count-hint": "Het totale aantal gegevenspunten binnen een geselecteerd tijdvenster.", + "delta-calculation": "Delta-berekening", + "enable-delta-calculation": "Deltaberekening inschakelen", + "enable-delta-calculation-hint": "Als deze optie is ingeschakeld, wordt de waarde van de gegevenssleutel berekend op basis van de geaggregeerde waarden voor een geselecteerd tijdvenster en een opgegeven vergelijkingsperiode. Om prestatieredenen is de deltaberekening alleen beschikbaar voor historische tijdvensters en niet voor realtimewaarden. U kunt bijvoorbeeld de delta berekenen tussen het energieverbruik van gisteren ten opzichte van het energieverbruik van eergisteren.", + "delta-calculation-result": "Resultaat van de deltaberekening", + "delta-calculation-result-previous-value": "Vorige waarde", + "delta-calculation-result-delta-absolute": "Delta (absoluut)", + "delta-calculation-result-delta-percent": "Delta (procent)" + }, + "datasource": { + "type": "Type gegevensbron", + "name": "Naam", + "label": "Etiket", + "add-datasource-prompt": "Voeg gegevensbron toe" + }, + "details": { + "details": "Details", + "edit-mode": "Modus bewerken", + "edit-json": "JSON bewerken", + "toggle-edit-mode": "Bewerkingsmodus in-/uitschakelen" + }, + "device": { + "all": "Alle", + "all-devices": "Alle Devices", + "groups": "Groepen", + "shared": "Gedeeld", + "device": "Device", + "device-required": "Device is vereist.", + "devices": "Devices", + "management": "Device beheer", + "view-devices": "Devices bekijken", + "device-alias": "Alias van het device", + "device-type-max-length": "Device type moet kleiner zijn dan 256 tekens", + "aliases": "Aliassen van Devices", + "no-alias-matching": "'{{alias}}' niet gevonden.", + "no-aliases-found": "Geen aliassen gevonden.", + "no-key-matching": "'{{key}}' niet gevonden.", + "no-keys-found": "Geen sleutels gevonden.", + "create-new-alias": "Maak een nieuwe aan!", + "create-new-key": "Maak een nieuwe aan!", + "duplicate-alias-error": "Dubbele alias gevonden '{{alias}}'.
Apparaataliassen moeten uniek zijn binnen het dashboard.", + "configure-alias": "Configureer de alias '{{alias}}'", + "no-devices-matching": "Er zijn geen devices gevonden die overeenkomen met '{{entity}}'.", + "alias": "Alias", + "alias-required": "Device alias is vereist.", + "remove-alias": "Device alias verwijderen", + "add-alias": "Device alias toevoegen", + "name-starts-with": "Expressie van device naam", + "help-text": "Gebruik '%' naar behoefte: '%device_name_contains%', '%device_name_ends', 'device_starts_with'.", + "device-list": "Lijst met Devices", + "use-device-name-filter": "Filter gebruiken", + "device-list-empty": "Geen devices geselecteerd.", + "device-name-filter-required": "Apparaatnaamfilter is vereist.", + "device-name-filter-no-device-matched": "Er zijn geen devices gevonden die beginnen met '{{device}}'.", + "add": "Device toevoegen", + "assign-to-customer": "Toewijzen aan klant", + "assign-device-to-customer": "Device(en) toewijzen aan klant", + "assign-device-to-customer-text": "Selecteer de devices die u aan de klant wilt toewijzen", + "make-public": "Device openbaar maken", + "make-private": "Device privé maken", + "no-devices-text": "Geen devices gevonden", + "assign-to-customer-text": "Selecteer de klant om het/het device(en) toe te wijzen", + "device-details": "Gegevens van het device", + "add-device-text": "Nieuw device toevoegen", + "credentials": "Geloofsbrief", + "manage-credentials": "Inloggegevens beheren", + "delete": "Device verwijderen", + "assign-devices": "Devices toewijzen", + "assign-devices-text": "Wijs { count, plural, =1 {1 device} andere {# devices} } toe aan de klant", + "delete-devices": "Devices verwijderen", + "unassign-from-customer": "Toewijzing van klant ongedaan maken", + "unassign-devices": "Toewijzing van devices ongedaan maken", + "unassign-devices-action-title": "Toewijzing { count, plural, =1 {1 device} andere {# devices} } van klant ongedaan maken", + "unassign-device-from-edge-title": "Weet u zeker dat u de toewijzing van het device '{{deviceName}}' wilt opheffen?", + "unassign-device-from-edge-text": "Na de bevestiging wordt de toewijzing van het device ongedaan gemaakt en is het niet toegankelijk via de edge.", + "unassign-devices-from-edge": "Toewijzing van devices aan de edge ongedaan maken", + "assign-new-device": "Nieuw device toewijzen", + "make-public-device-title": "Weet je zeker dat je het device '{{deviceName}}' openbaar wilt maken?", + "make-public-device-text": "Na de bevestiging worden het device en al zijn gegevens openbaar gemaakt en toegankelijk gemaakt voor anderen.", + "make-private-device-title": "Weet je zeker dat je het device '{{deviceName}}' privé wilt maken?", + "make-private-device-text": "Na de bevestiging worden het device en al zijn gegevens privé gemaakt en zijn ze niet toegankelijk voor anderen.", + "view-credentials": "Inloggegevens bekijken", + "delete-device-title": "Weet u zeker dat u de '{{deviceName}}' van het device wilt verwijderen?", + "delete-device-text": "Opgelet, na de bevestiging worden het device en alle gerelateerde gegevens onherstelbaar.", + "delete-devices-title": "Weet u zeker dat u { count, plural, =1 {1 device} andere {# devices} } wilt verwijderen?", + "delete-devices-action-title": "Verwijder { count, plural, =1 {1 device} andere {# devices} }", + "delete-devices-text": "Opgelet, na de bevestiging worden alle geselecteerde devices verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "unassign-device-title": "Weet u zeker dat u de toewijzing van het device '{{deviceName}}' wilt opheffen?", + "unassign-device-text": "Na de bevestiging wordt de toewijzing van het device ongedaan gemaakt en is het niet toegankelijk voor de klant.", + "unassign-device": "Toewijzing van device ongedaan maken", + "unassign-devices-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 device} andere {# devices} } wilt opheffen?", + "unassign-devices-text": "Na de bevestiging worden alle geselecteerde devices ongedaan gemaakt en zijn ze niet toegankelijk voor de klant.", + "device-credentials": "Inloggegevens van het device", + "loading-device-credentials": "Devicereferenties worden geladen...", + "credentials-type": "Type referenties", + "access-token": "Toegang token", + "access-token-required": "Toegangstoken is vereist.", + "access-token-invalid": "De lengte van het toegangstoken moet tussen de 1 en 32 tekens zijn.", + "certificate-pem-format": "Certificaat in PEM-formaat", + "certificate-pem-format-required": "Certificaat is vereist.", + "copy-access-token": "Toegangstoken kopiëren", + "copy-certificate": "Kopie certificaat", + "copy-client-id": "Client-ID kopiëren", + "copy-user-name": "Gebruikersnaam kopiëren", + "copy-password": "Kopieer wachtwoord", + "generate-client-id": "Client-ID genereren", + "generate-user-name": "Gebruikersnaam genereren", + "generate-password": "Wachtwoord genereren", + "generate-access-token": "Toegangstoken genereren", + "lwm2m-security-config": { + "identity": "Identiteit van de klant", + "identity-required": "Clientidentiteit is vereist.", + "identity-tooltip": "De PSK-identifier is een willekeurige PSK-identifier van maximaal 128 bytes, zoals beschreven in de standaard [RFC7925].\nDe PSK-id MOET eerst worden geconverteerd naar een tekenreeks en vervolgens worden gecodeerd in octetten met behulp van UTF-8.", + "client-key": "Client-sleutel", + "client-key-required": "Clientsleutel is vereist.", + "client-key-tooltip-prk": "RPK openbare sleutel of id moet in de standaard [RFC7250] en gecodeerd zijn naar Base64-indeling!", + "client-key-tooltip-psk": "PSK-sleutel moet in het standaard [RFC4279] en HexDec-formaat zijn: 32, 64, 128 tekens!", + "endpoint": "Naam van endpoint", + "endpoint-required": "De naam van de endpoint is vereist.", + "client-public-key": "Openbare sleutel van client", + "client-public-key-hint": "Als de openbare sleutel van de client leeg is, wordt het vertrouwde certificaat gebruikt", + "client-public-key-tooltip": "De openbare sleutel X509 moet in DER-gecodeerd X509v3-formaat zijn en uitsluitend het EC-algoritme ondersteunen en vervolgens worden gecodeerd naar het Base64-formaat!", + "mode": "Beveiligingsconfiguratiemodus", + "client-tab": "Configuratie voor clientbeveiliging", + "client-certificate": "Certificaat van de klant", + "bootstrap-tab": "Bootstrap-client", + "bootstrap-server": "Bootstrap-server", + "lwm2m-server": "LwM2M-server", + "client-publicKey-or-id": "Openbare sleutel of id van de client", + "client-publicKey-or-id-required": "De openbare sleutel of id van de client is vereist.", + "client-publicKey-or-id-tooltip-psk": "De PSK-identifier is een willekeurige PSK-identifier van maximaal 128 bytes, zoals beschreven in de standaard [RFC7925].\nDe PSK-id MOET eerst worden geconverteerd naar een tekenreeks en vervolgens worden gecodeerd in octetten met behulp van UTF-8.", + "client-publicKey-or-id-tooltip-rpk": "RPK openbare sleutel of id moet in de standaard [RFC7250] en gecodeerd zijn naar Base64-indeling!", + "client-publicKey-or-id-tooltip-x509": "De openbare X509-sleutel moet in DER-gecodeerd X509v3-formaat zijn en uitsluitend het EC-algoritme ondersteunen en vervolgens worden gecodeerd in Base64-indeling", + "client-secret-key": "Geheime sleutel van de client", + "client-secret-key-required": "Client Secret Key is vereist.", + "client-secret-key-tooltip-psk": "PSK-sleutel moet in het standaard [RFC4279] en HexDec-formaat zijn: 32, 64, 128 tekens!", + "client-secret-key-tooltip-prk": "De geheime RPK-sleutel moet in PKCS_8 formaat zijn (DER-codering, standaard [RFC5958]) en vervolgens worden gecodeerd in Base64-formaat!", + "client-secret-key-tooltip-x509": "De geheime sleutel X509 moet in PKCS_8 formaat zijn (DER-codering, standaard [RFC5958]) en vervolgens worden gecodeerd in Base64-formaat!" + }, + "client-id": "Client-ID", + "client-id-pattern": "Bevat een ongeldig teken.", + "user-name": "Gebruikersnaam", + "user-name-required": "Gebruikersnaam is vereist.", + "client-id-or-user-name-necessary": "Client-ID en/of gebruikersnaam zijn noodzakelijk", + "password": "Wachtwoord", + "secret": "Geheim", + "secret-required": "Geheim is vereist.", + "device-type": "Device type", + "device-type-required": "Device type is vereist.", + "select-device-type": "Selecteer device type", + "enter-device-type": "Voer het device type in", + "any-device": "Elk device", + "no-device-types-matching": "Er zijn geen device typen gevonden die overeenkomen met '{{entitySubtype}}'.", + "device-type-list-empty": "Geen device typen geselecteerd.", + "device-types": "Device sorrten", + "name": "Naam", + "name-required": "Naam is verplicht.", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens tekens", + "label-max-length": "Etiket moet kleiner zijn dan 256 tekens tekens", + "description": "Omschrijving: __________", + "label": "Etiket", + "events": "Events", + "details": "Details", + "copyId": "Device-ID kopiëren", + "copyAccessToken": "Toegangstoken kopiëren", + "copy-mqtt-authentication": "MQTT-inloggegevens kopiëren", + "idCopiedMessage": "Device-ID is gekopieerd naar klembord", + "accessTokenCopiedMessage": "Token voor apparaattoegang is gekopieerd naar het klembord", + "mqtt-authentication-copied-message": "MQTT-verificatie van device is gekopieerd naar klembord", + "assignedToCustomer": "Toegewezen aan klant", + "unable-delete-device-alias-title": "Kan apparaatalias niet verwijderen", + "unable-delete-device-alias-text": "Device alias '{{deviceAlias}}' kan niet worden verwijderd omdat deze wordt gebruikt door de volgende widget(s):
{{widgetsList}}", + "is-gateway": "Is gateway", + "overwrite-activity-time": "Activiteitstijd overschrijven voor verbonden device", + "device-filter": "Device filter", + "device-filter-title": "Device filter", + "filter-title": "Filter", + "device-state": "Status van het device", + "state": "Staat", + "any": "Enig", + "active": "Actief", + "inactive": "Inactief", + "public": "Publiek", + "device-public": "Device is openbaar", + "select-device": "Selecteer device", + "select-group-to-add": "Selecteer de doelgroep om geselecteerde devices toe te voegen", + "select-group-to-move": "Selecteer de doelgroep om geselecteerde devices te verplaatsen", + "remove-devices-from-group": "Weet je zeker dat je { count, plural, =1 {1 device} andere {# devices} } uit groep '{{entityGroup}}' wilt verwijderen?", + "group": "Device groep", + "list-of-groups": "{ count, plural, =1 {One device group} andere {List of # device groups} }", + "group-name-starts-with": "Asset groepen waarvan de naam begint met '{{prefix}}'", + "import": "Device importeren", + "device-file": "Device bestand", + "search": "Devices zoeken", + "selected-devices": "{ count, plural, =1 {1 device} andere {# devices} } geselecteerd", + "device-configuration": "Configuratie van het device", + "transport-configuration": "Configuratie van het transport", + "wizard": { + "device-wizard": "Device Wizard", + "device-details": "Gegevens van het device", + "new-device-profile": "Nieuw device profiel maken", + "existing-device-profile": "Bestaand device profiel selecteren", + "specific-configuration": "Specifieke configuratie", + "customer-to-assign-device": "Klant om het device toe te wijzen", + "add-credentials": "Inloggegevens toevoegen" + }, + "unassign-devices-from-edge-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 device} andere {# devices} } wilt opheffen?", + "unassign-devices-from-edge-text": "Na de bevestiging worden alle geselecteerde devices ongedaan gemaakt en zijn ze niet toegankelijk via de edge." + }, + "asset-profile": { + "asset-profile": "Asset profiel", + "asset-profiles": "Asset profielen", + "all-asset-profiles": "Alle", + "add": "Asset profiel toevoegen", + "edit": "Asset profiel bewerken", + "asset-profile-details": "Details van de asset profiel", + "no-asset-profiles-text": "Geen assetprofielen gevonden", + "search": "Assetprofielen zoeken", + "selected-asset-profiles": "{ count, plural, =1 {1 asset profile} andere {# asset profiles} } geselecteerd", + "no-asset-profiles-matching": "Er zijn geen asset profielen gevonden die overeenkomen met '{{entity}}'.", + "asset-profile-required": "Asset profiel is vereist", + "idCopiedMessage": "De ID van het itemprofiel is gekopieerd naar het klembord", + "set-default": "Itemprofiel instellen als standaard", + "delete": "Asset profiel verwijderen", + "copyId": "Itemprofiel-ID kopiëren", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "new-device-profile-name": "Naam van itemprofiel", + "new-device-profile-name-required": "De naam van de asset profiel is vereist.", + "name": "Naam", + "name-required": "Naam is verplicht.", + "image": "Afbeelding van assetprofiel", + "description": "Omschrijving: __________", + "default": "Verstek", + "default-rule-chain": "Keten van standaardregels", + "default-edge-rule-chain": "Standaard rule chain", + "default-edge-rule-chain-hint": "Wordt aan de edge gebruikt als rule chain om inkomende gegevens voor asset van dit asset profiel te verwerken", + "mobile-dashboard": "Mobiel dashboard", + "mobile-dashboard-hint": "Gebruikt door mobiele applicatie als dashboard met activagegevens", + "select-queue-hint": "Maak een keuze uit een vervolgkeuzelijst.", + "delete-asset-profile-title": "Weet je zeker dat je de asset profiel '{{assetProfileName}}' wilt verwijderen?", + "delete-asset-profile-text": "Let op, na de bevestiging worden de asset profiel en alle gerelateerde gegevens onherstelbaar.", + "delete-asset-profiles-title": "Weet u zeker dat u { count, plural, =1 {1 asset profile} andere {# asset profiles} } wilt verwijderen?", + "delete-asset-profiles-text": "Opgelet, na de bevestiging worden alle geselecteerde asset profielen verwijderd en worden alle gerelateerde gegevens onherstelbaar.", + "set-default-asset-profile-title": "Weet u zeker dat u de asset profiel standaard op '{{assetProfileName}}' wilt zetten?", + "set-default-asset-profile-text": "Na de bevestiging wordt de asset profiel gemarkeerd als standaard en wordt het gebruikt voor nieuwe asset waarvoor geen profiel is opgegeven.", + "no-asset-profiles-found": "Geen assetprofielen gevonden.", + "create-new-asset-profile": "Maak een nieuwe aan!", + "create-asset-profile": "Nieuw asset profiel maken", + "import": "Asset profiel importeren", + "export": "Asset profiel exporteren", + "export-failed-error": "Kan itemprofiel niet exporteren: {{error}}", + "asset-profile-file": "Asset profiel bestand", + "invalid-asset-profile-file-error": "Kan itemprofiel niet importeren: Ongeldige gegevensstructuur van asset profiel." + }, + "device-profile": { + "device-profile": "Device profiel", + "device-profiles": "Device profielen", + "all-device-profiles": "Alle", + "add": "Device profiel toevoegen", + "edit": "Device profiel bewerken", + "device-profile-details": "Details van device profiel", + "no-device-profiles-text": "Geen device profielen gevonden", + "search": "Device profielen zoeken", + "selected-device-profiles": "{ count, plural, =1 {1 device profile} andere {# device profiles} } geselecteerd", + "no-device-profiles-matching": "Er zijn geen device profielen gevonden die overeenkomen met '{{entity}}'.", + "device-profile-required": "Device profiel is vereist", + "idCopiedMessage": "Device profiel-ID is gekopieerd naar klembord", + "set-default": "Device profiel standaard instellen", + "delete": "Device profiel verwijderen", + "copyId": "Device profiel-ID kopiëren", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens tekens", + "new-device-profile-name": "Profielnaam device", + "new-device-profile-name-required": "De naam van het device profiel is vereist.", + "name": "Naam", + "name-required": "Naam is verplicht.", + "type": "Type profiel", + "type-required": "Profieltype is vereist.", + "type-default": "Verstek", + "image": "Profielafbeelding van device", + "transport-type": "Soort vervoer", + "transport-type-required": "Transporttype is vereist.", + "transport-type-default": "Verstek", + "transport-type-default-hint": "Ondersteunt standaard MQTT-, HTTP- en CoAP-transport", + "transport-type-mqtt": "MQTT", + "transport-type-mqtt-hint": "Maakt geavanceerde MQTT-transportinstellingen mogelijk", + "transport-type-coap": "CoAP", + "transport-type-coap-hint": "Maakt geavanceerde CoAP-transportinstellingen mogelijk", + "transport-type-lwm2m": "LWM2M", + "transport-type-lwm2m-hint": "LWM2M transporttype", + "transport-type-snmp": "SNMP", + "transport-type-snmp-hint": "SNMP-transportconfiguratie opgeven", + "description": "Omschrijving: __________", + "default": "Verstek", + "profile-configuration": "Profiel configuratie", + "transport-configuration": "Configuratie van het transport", + "default-rule-chain": "Standaard rule chain", + "default-edge-rule-chain": "Standaard edge rule chain", + "default-edge-rule-chain-hint": "Wordt aan de edge rule chain om inkomende gegevens te verwerken voor devices met dit device profiel", + "mobile-dashboard": "Mobiel dashboard", + "mobile-dashboard-hint": "Gebruikt door mobiele applicatie als dashboard met device details", + "select-queue-hint": "Maak een keuze uit een vervolgkeuzelijst.", + "delete-device-profile-title": "Weet u zeker dat u het device profiel '{{deviceProfileName}}' wilt verwijderen?", + "delete-device-profile-text": "Opgelet, na de bevestiging worden het device profiel en alle gerelateerde gegevens, inclusief bijbehorende OTA-updates, onherstelbaar.", + "delete-device-profiles-title": "Weet u zeker dat u { count, plural, =1 {1 device profile} andere {# device profiles} } wilt verwijderen?", + "delete-device-profiles-text": "Opgelet, na de bevestiging worden alle geselecteerde device profielen verwijderd en kunnen alle gerelateerde gegevens, inclusief bijbehorende OTA-updates, niet meer worden hersteld.", + "set-default-device-profile-title": "Weet u zeker dat u het device profiel standaard '{{deviceProfileName}}' wilt maken?", + "set-default-device-profile-text": "Na de bevestiging wordt het device profiel als standaard gemarkeerd en wordt het gebruikt voor nieuwe devices waarvoor geen profiel is opgegeven.", + "no-device-profiles-found": "Geen device profielen gevonden.", + "create-new-device-profile": "Maak een nieuwe aan!", + "mqtt-device-topic-filters": "Onderwerpfilters voor MQTT-Devices", + "mqtt-device-topic-filters-unique": "Onderwerpfilters voor MQTT-Devices moeten uniek zijn.", + "mqtt-device-topic-filters-spark-plug": "MQTT Bougie B Edge van het netwerk (EoN) knooppunt.", + "mqtt-device-topic-filters-spark-plug-hint": "Sta verbindingen toe vanaf EoN-rule nodes met Sparkplug B-payload en onderwerpindeling.", + "mqtt-device-topic-filters-spark-plug-attribute-metric-names": "SparkPlug-statistieken om op te slaan als attributen.", + "mqtt-device-topic-filters-spark-plug-attribute-metric-names-hint": "Namen van SparkPlug-statistieken die worden opgeslagen als device attributen. Alle andere metrische gegevens worden opgeslagen als device telemetrie.", + "mqtt-device-payload-type": "Nuttige waarde van het MQTT-device", + "mqtt-device-payload-type-json": "JSON", + "mqtt-device-payload-type-proto": "Protobuf", + "mqtt-enable-compatibility-with-json-payload-format": "Schakel compatibiliteit met andere payload-indelingen in.", + "mqtt-enable-compatibility-with-json-payload-format-hint": "Indien ingeschakeld, gebruikt het platform standaard een Protobuf payload-indeling. Als parsen mislukt, probeert het platform de JSON-payloadindeling te gebruiken. Handig voor achterwaartse compatibiliteit tijdens firmware-updates. De eerste release van de firmware gebruikt bijvoorbeeld Json, terwijl de nieuwe release Protobuf gebruikt. Tijdens het proces van firmware-update voor de vloot van devices, is het vereist om zowel Protobuf als JSON tegelijkertijd te ondersteunen. De compatibiliteitsmodus introduceert een lichte prestatievermindering, dus het wordt aanbevolen om deze modus uit te schakelen zodra alle devices zijn bijgewerkt.", + "mqtt-use-json-format-for-default-downlink-topics": "Json-indeling gebruiken voor standaard downlink-onderwerpen", + "mqtt-use-json-format-for-default-downlink-topics-hint": "Indien ingeschakeld, gebruikt het platform de Json-payloadindeling om attributen en RPC te pushen via de volgende onderwerpen: v1/devices/me/attributes/response/$request_id, v1/devices/me/attributes, v1/devices/me/rpc/request/$request_id, v1/devices/me/rpc/response/$request_id. Deze instelling heeft geen invloed op kenmerk- en rpc-abonnementen die worden verzonden met behulp van nieuwe (v2) onderwerpen: v2/a/res/$request_id, v2/a, v2/r/req/$request_id, v2/r/res/$request_id. Waarbij $request_id een id van een geheel getal is.", + "mqtt-send-ack-on-validation-exception": "PUBACK verzenden bij mislukte validatie van PUBLISH-bericht", + "mqtt-send-ack-on-validation-exception-hint": "Standaard sluit het platform de MQTT-sessie bij mislukte berichtvalidatie. Indien ingeschakeld, stuurt het platform een publicatiebevestiging in plaats van de sessie te sluiten.", + "snmp-add-mapping": "SNMP-toewijzing toevoegen", + "snmp-mapping-not-configured": "Geen toewijzing voor OID aan tijdreeks/telemetrie geconfigureerd", + "snmp-timseries-or-attribute-name": "Tijdreeks-/kenmerknaam voor toewijzing", + "snmp-timseries-or-attribute-type": "Tijdreeks/kenmerktype voor toewijzing", + "snmp-method-pdu-type-get-request": "GetRequest (GetAanvraag)", + "snmp-method-pdu-type-get-next-request": "VolgendeAanvraag", + "snmp-oid": "OID", + "transport-device-payload-type-json": "JSON", + "transport-device-payload-type-proto": "Protobuf", + "mqtt-payload-type-required": "Payload-type is vereist.", + "coap-device-type": "Type CoAP-device", + "coap-device-payload-type": "Nuttige lading van CoAP-device", + "coap-device-type-required": "Het type CoAP-device is vereist.", + "coap-device-type-default": "Verstek", + "coap-device-type-efento": "Efento NB-IoT", + "support-level-wildcards": "Enkele [+] en multi-level [#] jokertekens worden ondersteund.", + "telemetry-topic-filter": "Onderwerpfilter voor telemetrie", + "telemetry-topic-filter-required": "Telemetrie-onderwerpfilter is vereist.", + "attributes-topic-filter": "Attributen topic filter", + "attributes-subscribe-topic-filter": "Attributen topic subscribe filter", + "attributes-topic-filter-required": "Attributen topic filter is vereist.", + "attributes-subscribe-topic-filter-required": "Attributen topic subscribe is vereist", + "telemetry-proto-schema": "Telemetrie proto-schema", + "telemetry-proto-schema-required": "Telemetrie proto-schema is vereist.", + "attributes-proto-schema": "Attributen proto-schema", + "attributes-proto-schema-required": "Attributen proto-schema is vereist.", + "rpc-response-proto-schema": "RPC-respons proto-schema", + "rpc-response-proto-schema-required": "RPC-respons proto-schema is vereist.", + "rpc-response-topic-filter": "Onderwerpfilter voor RPC-reacties", + "rpc-response-topic-filter-required": "RPC-responsonderwerpfilter is vereist.", + "rpc-request-proto-schema": "RPC-aanvraag proto-schema", + "rpc-request-proto-schema-required": "RPC-aanvraag proto-schema is vereist.", + "rpc-request-proto-schema-hint": "RPC-aanvraagbericht moet altijd velden bevatten: tekenreeksmethode = 1; int32 requestId = 2; en params = 3 van elk gegevenstype.", + "not-valid-pattern-topic-filter": "Ongeldig topic pattern filter", + "not-valid-single-character": "Ongeldig gebruik van een jokerteken op één niveau", + "not-valid-multi-character": "Ongeldig gebruik van een jokerteken met meerdere niveaus", + "single-level-wildcards-hint": "[+] is geschikt voor elk topic filter niveau. Bijv.: v1/devices/+/telemetry of +/devices/+/attributen.", + "multi-level-wildcards-hint": "[#] kan de topic filter zelf vervangen en moet het laatste symbool van de topic zijn. Bijv.: # of v1/Devices/ik/#.", + "alarm-rules": "Alarm regels", + "alarm-rules-with-count": "Alarmregels ({{count}})", + "no-alarm-rules": "Geen alarmregels geconfigureerd", + "add-alarm-rule": "Alarmregel toevoegen", + "edit-alarm-rule": "Alarmregel bewerken", + "alarm-type": "Soort alarm", + "alarm-type-required": "Alarmtype is vereist.", + "alarm-type-unique": "Het alarmtype moet uniek zijn binnen de alarmregels van het device profiel.", + "alarm-type-max-length": "Alarmtype moet kleiner zijn dan 256 tekens tekens", + "create-alarm-pattern": "Creëer {{alarmType}} alarm", + "create-alarm-rules": "Alarmregels maken", + "no-create-alarm-rules": "Geen voorwaarden voor het creëren van alarmen+ geconfigureerd", + "add-create-alarm-rule-prompt": "Voeg een alarmregel toe", + "clear-alarm-rule": "Duidelijke alarmregel", + "no-clear-alarm-rule": "Geen duidelijke voorwaarde geconfigureerd", + "add-create-alarm-rule": "Voorwaarde voor maken toevoegen", + "add-clear-alarm-rule": "Duidelijke voorwaarde toevoegen", + "select-alarm-severity": "Selecteer de ernst van het alarm", + "alarm-severity-required": "De ernst van het alarm is vereist.", + "condition-duration": "Duur van de conditie", + "condition-duration-value": "Duur waarde", + "condition-duration-time-unit": "Tijdseenheid", + "condition-duration-value-range": "De duurwaarde moet tussen 1 en 2147483647 liggen.", + "condition-duration-value-pattern": "De waarde van de duur moet gehele getallen zijn.", + "condition-duration-value-required": "Duurwaarde is vereist.", + "condition-duration-time-unit-required": "Tijdseenheid is vereist.", + "advanced-settings": "Geavanceerde instellingen", + "alarm-rule-details": "Details", + "alarm-rule-details-hint": "Tip: gebruik ${keyName} om waarden van de attribuut- of telemetriesleutels te vervangen die worden gebruikt in de alarmregelvoorwaarde.", + "add-alarm-rule-details": "Voeg details toe", + "alarm-rule-mobile-dashboard": "Mobiel dashboard", + "alarm-rule-mobile-dashboard-hint": "Gebruikt door mobiele applicatie als dashboard met alarmdetails", + "alarm-rule-no-mobile-dashboard": "Geen dashboard geselecteerd", + "propagate-alarm": "Alarm doorgeven aan verwante entiteiten", + "alarm-rule-relation-types-list": "Relatietypen die moeten worden gepropageerd", + "alarm-rule-relation-types-list-hint": "Als Relatietypen doorgeven niet is geselecteerd, worden alarmen doorgegeven zonder te filteren op relatietype.", + "propagate-alarm-to-owner": "Alarm doorgeven aan entiteitseigenaar (klant of tenant)", + "propagate-alarm-to-owner-hierarchy": "Alarm doorgeven aan de hiërarchie van entiteitseigenaren", + "propagate-alarm-to-tenant": "Alarm doorgeven aan tenant", + "alarm-details": "Details van het alarm", + "alarm-rule-condition": "Voorwaarde van de alarmregel", + "enter-alarm-rule-condition-prompt": "Voeg de voorwaarde van de alarmregel toe", + "edit-alarm-rule-condition": "Voorwaarde van de alarmregel bewerken", + "device-provisioning": "Inrichting van Devices", + "provision-strategy": "Provisioning-strategie", + "provision-strategy-required": "Provisioning-strategie is vereist.", + "provision-strategy-disabled": "Provisioning-strategie uitgeschakeld ", + "provision-strategy-created-new": "Toestaan om nieuwe provisioning-strategie aan te maken", + "provision-strategy-check-pre-provisioned": "Controleren op vooraf geprovisioneerde devices", + "provision-device-key": "Provision device sleutel", + "provision-device-key-required": "Provision device sleutel is vereist.", + "copy-provision-key": "Provisioningsleutel kopiëren", + "provision-key-copied-message": "Provisioningsleutel is gekopieerd naar klembord", + "provision-device-secret": "Provion device geheim", + "provision-device-secret-required": "Provision device geheim is vereist.", + "copy-provision-secret": "Provisioning geheim kopiëren", + "provision-secret-copied-message": "Provisioningsgeheim is gekopieerd naar klembord", + "provision-strategy-x509": { + "certificate-chain": "X509 Certificaten Keten", + "certificate-chain-hint": "De X.509-certificatenstrategie wordt gebruikt om devices in te richten op clientcertificaten in tweerichtings-TLS-communicatie.", + "allow-create-new-devices": "Nieuwe devices maken", + "allow-create-new-devices-hint": "Indien geselecteerd, worden nieuwe devices gemaakt en wordt het clientcertificaat gebruikt als apparaatreferenties.", + "certificate-value": "Certificaat in PEM-formaat", + "certificate-value-required": "Certificaat in PEM-formaat is vereist", + "cn-regex-variable": "CN Reguliere expressie variabele", + "cn-regex-variable-required": "CN Regular Expression variabele is vereist", + "cn-regex-variable-hint": "Vereist om de device naam op te halen uit de algemene naam van het X509-certificaat van het device." + }, + "condition": "Conditie", + "condition-type": "Conditie type", + "condition-type-simple": "Eenvoudig", + "condition-type-duration": "Duur", + "condition-during": "Tijdens {{during}}", + "condition-during-dynamic": "Tijdens \"{{ attribute }}\" ({{during}})", + "condition-type-repeating": "Herhalende", + "condition-type-required": "Conditietype is vereist.", + "condition-repeating-value": "Aantal gebeurtenissen", + "condition-repeating-value-range": "Het aantal gebeurtenissen moet tussen 1 en 2147483647 liggen.", + "condition-repeating-value-pattern": "Het aantal gebeurtenissen moet gehele getallen zijn.", + "condition-repeating-value-required": "Het aantal gebeurtenissen is vereist.", + "condition-repeat-times": "Herhalingen { count, plural, =1 {1 time} andere {# times} }", + "condition-repeat-times-dynamic": "Herhaalt \"{ attribute }\" ({ count, plural, =1 {1 time} andere {# times} })", + "schedule-type": "Type planner", + "schedule-type-required": "Het type planner is vereist.", + "schedule": "Rooster", + "edit-schedule": "Alarmschema bewerken", + "schedule-any-time": "Altijd actief", + "schedule-specific-time": "Actief op een bepaald tijdstip", + "schedule-custom": "Gewoonte", + "schedule-day": { + "monday": "Maandag", + "tuesday": "Dinsdag", + "wednesday": "Woensdag", + "thursday": "Donderdag", + "friday": "Vrijdag", + "saturday": "Zaterdag", + "sunday": "Zondag" + }, + "schedule-days": "Dagen", + "schedule-time": "Tijd", + "schedule-time-from": "Van", + "schedule-time-to": "Aan", + "schedule-days-of-week-required": "Er moet ten minste één dag van de week worden geselecteerd.", + "create-device-profile": "Nieuw device profiel maken", + "import": "Device profiel importeren", + "export": "Device profiel exporteren", + "export-failed-error": "Device profiel kan niet worden geëxporteerd: {{error}}", + "device-profile-file": "Bestand met device profiel", + "invalid-device-profile-file-error": "Kan device profiel niet importeren: Ongeldige gegevensstructuur van het device profiel.", + "power-saving-mode": "Energiebesparende modus", + "power-saving-mode-type": { + "default": "Energiebesparende modus voor device profiel gebruiken", + "psm": "Energiebesparende modus (PSM)", + "drx": "Discontinue ontvangst (DRX)", + "edrx": "Uitgebreide discontinue ontvangst (eDRX)" + }, + "edrx-cycle": "eDRX-cyclus", + "edrx-cycle-required": "eDRX-cyclus is vereist.", + "edrx-cycle-pattern": "De eDRX-cyclus moet een positief geheel getal zijn.", + "edrx-cycle-min": "Het minimale aantal eDRX-cycli is {{ min }} seconden.", + "paging-transmission-window": "Transmissievenster voor oproepen", + "paging-transmission-window-required": "Oproeptransmissievenster is vereist.", + "paging-transmission-window-pattern": "Het zendvenster van de paging-transmissie moet een positief geheel getal zijn.", + "paging-transmission-window-min": "Het minimale aantal paging-transmissievensters is {{ min }} seconden.", + "psm-activity-timer": "PSM-activiteitstimer", + "psm-activity-timer-required": "PSM-activiteitstimer is vereist.", + "psm-activity-timer-pattern": "PSM-activiteitstimer moet een positief geheel getal zijn.", + "psm-activity-timer-min": "Het minimale aantal PSM-activiteitstimers is {{ min }} seconden.", + "lwm2m": { + "object-list": "Lijst met objecten", + "object-list-empty": "Geen objecten geselecteerd.", + "no-objects-found": "Geen objecten gevonden.", + "no-objects-matching": "Er zijn geen objecten gevonden die overeenkomen met '{{object}}'.", + "model-tab": "LWM2M Model", + "add-new-instances": "Nieuwe instanties toevoegen", + "instances-list": "Lijst met instanties", + "instances-list-required": "Een lijst met instanties is vereist.", + "instance-id-pattern": "Instantie-id moet een positief geheel getal zijn.", + "instance-id-max": "Maximale exemplaar-id-waarde {{max}}.", + "instance": "Voorbeeld", + "resource-label": "#ID Naam van de bron", + "observe-label": "Waarnemen", + "attribute-label": "Attribuut", + "telemetry-label": "Telemetrie", + "edit-observe-select": "Telemetrie of attribuut bewerken om te bewerken, te observeren", + "edit-attributes-select": "Als u attributen wilt bewerken, selecteert u telemetrie of kenmerk", + "no-attributes-set": "Geen attributen ingesteld", + "key-name": "Naam van de sleutel", + "key-name-required": "Sleutelnaam is vereist", + "attribute-name": "Naam attribuut", + "attribute-name-required": "Naamattribuut is vereist.", + "attribute-value": "Attribuutwaarde", + "attribute-value-required": "Kenmerkwaarde is vereist.", + "attribute-value-pattern": "De kenmerkwaarde moet een positief geheel getal zijn.", + "edit-attributes": "Attributen bewerken: {{ name }}", + "view-attributes": "Bekijk attributen: {{ name }}", + "add-attribute": "Attribuut toevoegen", + "edit-attribute": "Attribuut bewerken", + "view-attribute": "Bekijk attribuut", + "remove-attribute": "Attribuut verwijderen", + "delete-server-text": "Opgelet, na de bevestiging wordt de serverconfiguratie onherstelbaar.", + "delete-server-title": "Weet je zeker dat je de server wilt verwijderen?", + "mode": "Beveiligingsconfiguratiemodus", + "bootstrap-tab": "Opstarten", + "bootstrap-server-legend": "Bootstrap-server (ShortId...)", + "lwm2m-server-legend": "LwM2M-server (ShortId...)", + "server": "Server", + "short-id": "Korte server-ID", + "short-id-tooltip": "Server-id kort Id. Wordt gebruikt als koppeling naar het Object-exemplaar van de koppeling.\nDeze id identificeert elke LwM2M-server die is geconfigureerd voor de LwM2M-client op unieke wijze.\nResource MOET worden ingesteld wanneer de Bootstrap-Server Resource een waarde van 'false' heeft.\nDe waarden ID:0 en ID:65535 mogen NIET worden gebruikt voor het identificeren van de LwM2M-server.", + "short-id-required": "Een korte server-ID is vereist.", + "short-id-range": "Korte server-ID moet tussen 1 en 65534 liggen.", + "short-id-pattern": "Korte server-ID moet een positief geheel getal zijn.", + "lifetime": "Levensduur klantregistratie", + "lifetime-required": "Levenslange registratie van klanten is vereist.", + "lifetime-pattern": "De levensduur van clientregistratie moet een positief geheel getal zijn.", + "default-min-period": "Min. periode tussen twee kennisgeving(en)", + "default-min-period-tooltip": "De standaardwaarde die de LwM2M-client moet gebruiken voor de minimale periode van een waarneming als deze parameter niet in een waarneming is opgenomen.", + "default-min-period-required": "Minimumperiode is vereist.", + "default-min-period-pattern": "De minimumperiode moet een positief geheel getal zijn.", + "notification-storing": "Melding opslaan wanneer uitgeschakeld of offline", + "binding": "Bindend", + "binding-type": { + "u": "U: Cliënt is te allen tijde bereikbaar via de UDP-binding.", + "m": "M: Opdrachtgever is te allen tijde bereikbaar via de MQTT-binding.", + "h": "H: Client is op elk moment bereikbaar via de HTTP-binding.", + "t": "T: Cliënt is te allen tijde bereikbaar via de TCP-binding.", + "s": "S: Cliënt is te allen tijde bereikbaar via de SMS-binding.", + "n": "N: Client MOET het antwoord op een dergelijk verzoek verzenden via de niet-IP-binding (wordt ondersteund sinds LWM2M 1.1).", + "uq": "UQ: UDP-verbinding in wachtrijmodus (wordt niet meer ondersteund sinds LWM2M 1.1)", + "uqs": "UQS: zowel UDP- als SMS-verbindingen actief; UDP in wachtrijmodus, SMS in standaardmodus (wordt niet ondersteund sinds LWM2M 1.1)", + "tq": "TQ: TCP-verbinding in wachtrijmodus (wordt niet meer ondersteund sinds LWM2M 1.1)", + "tqs": "TQS: zowel TCP- als SMS-verbindingen actief; TCP in wachtrijmodus, SMS in standaardmodus (wordt niet ondersteund sinds LWM2M 1.1)", + "sq": "SQ: SMS-verbinding in wachtrijmodus (wordt niet meer ondersteund sinds LWM2M 1.1)" + }, + "binding-tooltip": "Dit is de lijst in de \"bindende\" bron van het LwM2M-serverobject - /1/x/7.\nGeeft de ondersteunde bindingsmodi in de LwM2M-client aan.\nDeze waarde MOET hetzelfde zijn als de waarde in de bron \"Ondersteunde bindingen en modi\" in het apparaatobject (/3/0/16).\nHoewel meerdere transporten worden ondersteund, kan er slechts één transportbinding worden gebruikt tijdens de gehele transportsessie.\nWanneer bijvoorbeeld UDP en SMS beide worden ondersteund, kunnen de LwM2M-client en de LwM2M-server ervoor kiezen om tijdens de gehele transportsessie via UDP of sms te communiceren.", + "bootstrap-server": "Bootstrap-server", + "lwm2m-server": "LwM2M-server", + "include-bootstrap-server": "Bootstrap-serverupdates opnemen", + "bootstrap-update-title": "U hebt Bootstrap Server al geconfigureerd. Weet je zeker dat je de updates wilt uitsluiten?", + "bootstrap-update-text": "Opgelet, na de bevestiging worden de configuratiegegevens van de Bootstrap-server onherstelbaar.", + "server-host": "Server host", + "server-host-required": "Server host is vereist.", + "server-port": "Haven", + "server-port-required": "Poort is vereist.", + "server-port-pattern": "Poort moet een positief geheel getal zijn.", + "server-port-range": "De poort moet tussen 1 en 65535 liggen.", + "server-public-key": "Openbare sleutel van de server", + "server-public-key-required": "De openbare sleutel van de server is vereist.", + "client-hold-off-time": "Wacht met de tijd", + "client-hold-off-time-required": "Wachttijd is vereist.", + "client-hold-off-time-pattern": "Hold Off Time moet een positief geheel getal zijn.", + "client-hold-off-time-tooltip": "Client Hold Off Time alleen voor gebruik met een Bootstrap-Server", + "account-after-timeout": "Account na de time-out", + "account-after-timeout-required": "Account na de time-out is vereist.", + "account-after-timeout-pattern": "Account na de time-out moet een positief geheel getal zijn.", + "account-after-timeout-tooltip": "Bootstrap-Server-account na de time-outwaarde die door deze resource wordt opgegeven.", + "server-type": "Type server", + "add-new-server-title": "Nieuwe serverconfiguratie toevoegen", + "add-server-config": "Serverconfiguratie toevoegen", + "add-lwm2m-server-config": "LwM2M-server toevoegen", + "no-config-servers": "Geen servers geconfigureerd", + "others-tab": "Overige instellingen", + "client-strategy": "Klantstrategie bij het verbinden", + "client-strategy-label": "Strategie", + "client-strategy-only-observe": "Observeer het verzoek aan de client pas na de eerste verbinding", + "client-strategy-read-all": "Lees alle bronnen en observeer het verzoek aan de klant na registratie", + "fw-update": "Firmware-update", + "fw-update-strategy": "Strategie voor firmware-updates", + "fw-update-strategy-data": "Firmware-update pushen als binair bestand met behulp van Object 19 en Resource 0 (gegevens)", + "fw-update-strategy-package": "Firmware-update pushen als binair bestand met behulp van Object 5 en Resource 0 (pakket)", + "fw-update-strategy-package-uri": "Genereer automatisch een unieke CoAP-URL om het pakket te downloaden en de firmware-update te pushen als Object 5 en Resource 1 (pakket-URI)", + "sw-update": "Bijwerken van de software", + "sw-update-strategy": "Strategie voor software-updates", + "sw-update-strategy-package": "Binair bestand pushen met Object 9 en Resource 2 (pakket)", + "sw-update-strategy-package-uri": "Genereer automatisch een unieke CoAP-URL om het pakket te downloaden en software-update te pushen met behulp van Object 9 en Resource 3 (pakket-URI)", + "fw-update-resource": "CoAP-bron voor firmware-update", + "fw-update-resource-required": "CoAP-bron voor firmware-update is vereist.", + "sw-update-resource": "CoAP-bron voor software-update", + "sw-update-resource-required": "Software-update CoAP-bron is vereist.", + "config-json-tab": "Json Config Profile-device", + "attributes-name": { + "min-period": "Minimale periode", + "max-period": "Maximale periode", + "greater-than": "Groter dan", + "less-than": "Minder dan", + "step": "Stap", + "min-evaluation-period": "Minimale evaluatieperiode", + "max-evaluation-period": "Maximale evaluatieperiode" + }, + "composite-operations-support": "Ondersteunt samengestelde lees-/schrijf-/observatiebewerkingen" + }, + "snmp": { + "add-communication-config": "Communicatieconfiguratie toevoegen", + "add-mapping": "Toewijzing toevoegen", + "authentication-passphrase": "Wachtwoordzin voor verificatie", + "authentication-passphrase-required": "Wachtwoordzin voor verificatie is vereist.", + "authentication-protocol": "Authenticatie protocol", + "authentication-protocol-required": "Verificatieprotocol is vereist.", + "communication-configs": "Communicatie configs", + "community": "Tekenreeks van de gemeenschap", + "community-required": "Community-tekenreeks is vereist.", + "context-name": "Naam van de context", + "data-key": "Gegevenssleutel", + "data-key-required": "Gegevenssleutel is vereist.", + "data-type": "Soort gegevens", + "data-type-required": "Gegevenstype is vereist.", + "engine-id": "Motor-ID", + "host": "Server host", + "host-required": "Server host is vereist.", + "oid": "OID", + "oid-pattern": "Ongeldige OID-indeling.", + "oid-required": "OID is vereist.", + "please-add-communication-config": "Gelieve communicatieconfiguratie toe te voegen", + "please-add-mapping-config": "Voeg a.u.b. toewijzingsconfiguratie toe", + "port": "Haven", + "port-format": "Ongeldige poortindeling.", + "port-required": "Poort is vereist.", + "privacy-passphrase": "Wachtwoordzin voor privacy", + "privacy-passphrase-required": "Privacywachtwoordzin is vereist.", + "privacy-protocol": "Privacybeleid protocol", + "privacy-protocol-required": "Privacyprotocol is vereist.", + "protocol-version": "Protocolversie", + "protocol-version-required": "Protocolversie is vereist.", + "querying-frequency": "Frequentie van vragen, ms", + "querying-frequency-invalid-format": "De frequentie van query's moet een positief geheel getal zijn.", + "querying-frequency-required": "Queryfrequentie is vereist.", + "retries": "Pogingen", + "retries-invalid-format": "Pogingen voor nieuwe pogingen moeten een positief geheel getal zijn.", + "retries-required": "Opnieuw proberen is vereist.", + "scope": "Draagwijdte", + "scope-required": "Scope is vereist.", + "security-name": "Naam van de beveiliging", + "security-name-required": "Beveiligingsnaam is vereist.", + "timeout-ms": "Time-out, ms", + "timeout-ms-invalid-format": "Time-out moet een positief geheel getal zijn.", + "timeout-ms-required": "Er is een time-out vereist.", + "user-name": "Gebruikersnaam", + "user-name-required": "Gebruikersnaam is vereist." + } + }, + "dialog": { + "close": "Dialoogvenster sluiten", + "error-message-title": "Foutmelding:", + "error-details-title": "Details van de fout" + }, + "direction": { + "column": "Kolom", + "row": "Rijen" + }, + "edge": { + "all": "Alle", + "all-edges": "Alle edges", + "groups": "Groepen", + "shared": "Gedeeld", + "edge": "Edge", + "edge-instances": "Edge-instanties", + "instances": "Exemplaren", + "edge-file": "Edge-bestand", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "label-max-length": "Etiket moet kleiner zijn dan 256 tekens", + "type-max-length": "Type moet kleiner zijn dan 256 tekens", + "management": "Edge-beheer", + "no-edges-matching": "Er zijn geen edges gevonden die overeenkomen met '{{entity}}'.", + "add": "Edge toevoegen", + "no-edges-text": "Geen edges gevonden", + "edge-details": "Details van de edge", + "add-edge-text": "Nieuwe edge toevoegen", + "delete": "Edge verwijderen", + "delete-edge-title": "Weet je zeker dat je de edge '{{edgeName}}' wilt verwijderen?", + "delete-edge-text": "Opgelet, na de bevestiging worden de edge en alle gerelateerde gegevens onherstelbaar.", + "delete-edges-title": "Weet je zeker dat je { count, plural, =1 {1 edge} andere {# edges} } wilt bevoordelen?", + "delete-edges-text": "Opgelet, na de bevestiging worden alle geselecteerde edges verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "name": "Naam", + "name-starts-with": "Edge naam begint met", + "name-required": "Naam is verplicht.", + "edge-license-key": "Edge-licentiesleutel", + "edge-license-key-required": "Edge-licentiecode is vereist.", + "edge-license-key-max-length": "Edge-licentiesleutel moet kleiner zijn dan 31", + "edge-license-key-hint": "BELANGRIJKE OPMERKING: standaard edge-licentiesleutel wordt alleen verstrekt voor evaluatiedoeleinden.
Deze sleutel is slechts 30 dagen na activering actief. De whitelabeling-functie is uitgeschakeld.
Om uw licentiesleutel te verkrijgen, navigeert u naar de pagina pricing en selecteert u de beste licentieoptie voor uw geval.", + "cloud-endpoint": "Cloud-eindpunt", + "cloud-endpoint-required": "Cloud Endpoint is vereist.", + "cloud-endpoint-max-length": "Cloud-eindpunt moet kleiner zijn dan 256 tekens", + "cloud-endpoint-hint": "Edge vereist HTTP(s)-toegang tot Cloud (ThingsBoard PE) om de licentiesleutel te verifiëren. Geef de cloud-URL op waarmee Edge verbinding kan maken.", + "description": "Omschrijving: __________", + "details": "Details", + "events": "Events", + "copy-id": "Edge-ID kopiëren", + "id-copied-message": "Edge Id is gekopieerd naar klembord", + "sync": "Edge synchroniseren", + "edge-required": "Edge vereist", + "edge-type": "Type edge", + "edge-type-required": "Edge type is vereist.", + "event-action": "Actie voor event", + "entity-id": "Entiteit-ID", + "select-edge-type": "Edge type selecteren", + "assign-to-customer": "Toewijzen aan klant", + "assign-to-customer-text": "Selecteer de klant om de edge(en) toe te wijzen", + "assign-edge-to-customer": "Edge(s) toewijzen aan klant", + "assign-edge-to-customer-text": "Selecteer de edges die u aan de klant wilt toewijzen", + "assignedToCustomer": "Toegewezen aan klant", + "edge-public": "Edge is openbaar", + "assigned-to-customer": "Toegewezen aan: {{customerTitle}}", + "unassign-from-customer": "Toewijzing van klant ongedaan maken", + "unassign-edge-title": "Weet u zeker dat u de toewijzing van de edge '{{edgeName}}' wilt opheffen?", + "unassign-edge-text": "Na de bevestiging wordt de toewijzing van de edge ongedaan gemaakt en is deze niet toegankelijk voor de klant.", + "unassign-edges-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 edge} andere {# edges} } wilt opheffen?", + "unassign-edges-text": "Na de bevestiging worden alle geselecteerde edges ongedaan gemaakt en zijn ze niet toegankelijk voor de klant.", + "make-public": "Edge openbaar maken", + "make-public-edge-title": "Weet je zeker dat je de edge '{{edgeName}}' openbaar wilt maken?", + "make-public-edge-text": "Na de bevestiging worden de edge en al zijn gegevens openbaar gemaakt en toegankelijk gemaakt voor anderen.", + "make-private": "Maak edge privé", + "public": "Publiek", + "make-private-edge-title": "Weet je zeker dat je de edge '{{edgeName}}' privé wilt maken?", + "make-private-edge-text": "Na de bevestiging worden de edge en al zijn gegevens privé gemaakt en zijn ze niet toegankelijk voor anderen.", + "import": "Edge importeren", + "install-connect-instructions": "Installatie- en verbindingsinstructies", + "label": "Etiket", + "load-entity-error": "Gegevens kunnen niet worden geladen. Entiteit is verwijderd.", + "assign-new-edge": "Nieuwe edge toewijzen", + "unassign-from-edge": "Toewijzing van edge ongedaan maken", + "edge-key": "Edge sleutel", + "copy-edge-key": "Edge sleutel kopiëren", + "edge-key-copied-message": "Edge sleutel is gekopieerd naar klembord", + "edge-secret": "Het geheim van de edge", + "copy-edge-secret": "Kopieer Edge geheim", + "edge-secret-copied-message": "Edge-geheim is gekopieerd naar klembord", + "manage-assets": "Assets beheren", + "manage-devices": "Devices beheren", + "manage-entity-views": "Entiteitsweergaven beheren", + "manage-dashboards": "Dashboards beheren", + "manage-rulechains": "Rule chains beheren", + "assets": "Edge-asset", + "devices": "Edge-Devices", + "entity-views": "Edge-entiteitsweergaven", + "dashboard": "Edge-dashboard", + "dashboards": "Edge-dashboards", + "rulechain-templates": "Sjablonen voor rule chains", + "edge-rulechain-templates": "Sjablonen voor edge rule chains", + "converter-templates": "Converter sjablonen", + "edge-converter-templates": "Sjablonen voor edge-converters", + "integration-templates": "Integratie sjablonen", + "edge-integration-templates": "Sjablonen voor edge-integratie", + "rulechains": "Edge rule chains", + "integrations": "Integraties", + "search": "Edge zoeken", + "selected-edges": "{ count, plural, =1 {1 edge} andere {# edges} } geselecteerd", + "any-edge": "Elke edge", + "no-edge-types-matching": "Er zijn geen edge typen gevonden die overeenkomen met '{{entitySubtype}}'.", + "edge-type-list-empty": "Geen edge typen geselecteerd.", + "edge-types": "Soorten edges", + "enter-edge-type": "Voer edge type in", + "deployed": "Ingezet", + "pending": "In behandeling", + "downlinks": "Downlinks", + "no-downlinks-prompt": "Geen downlinks gevonden", + "sync-process-started-successfully": "Het synchronisatieproces is succesvol gestart!", + "missing-related-rule-chains-title": "Edge heeft ontbrekende gerelateerde rule chain(s)", + "missing-related-rule-chains-text": "Toegewezen aan rule chain(s) Gebruik rule nodes die bericht(en) doorsturen naar rule chain(s) die niet aan deze edge zijn toegewezen.

Lijst met ontbrekende rule chain(s):
{{missingRuleChains}}", + "widget-datasource-error": "Deze widget ondersteunt alleen de gegevensbron van de EDGE-entiteit", + "assign-to-edge": "Toewijzen aan edge", + "assign-to-edge-title": "Entiteitsgroep(en) toewijzen aan Edge", + "manage-edge-user-groups": "Edge-gebruikersgroepen beheren", + "manage-edge-asset-groups": "Edge-activagroepen beheren", + "manage-edge-device-groups": "Edge-apparaatgroepen beheren", + "manage-edge-entity-view-groups": "Edge-entiteitsweergavegroepen beheren", + "manage-edge-dashboard-groups": "Edge-dashboardgroepen beheren", + "manage-edge-rule-chains": "Ketens van randregels beheren", + "manage-edge-integrations": "Edge-integraties beheren", + "manage-edge-scheduler-events": "Edge-scheduler events beheren", + "select-group-to-add": "Selecteer de doelgroep om geselecteerde edges toe te voegen", + "select-group-to-move": "Selecteer de doelgroep om geselecteerde edges te verplaatsen", + "remove-edges-from-group": "Weet je zeker dat je { count, plural, =1 {1 edge} andere {# edges} } uit groep '{entityGroup}' wilt verwijderen?", + "group": "Groep edges", + "list-of-groups": "{ count, plural, =1 {One edge group} andere {List of # edge groups} }", + "group-name-starts-with": "Edge-groepen waarvan de naam begint met '{{prefix}}'", + "unassign-entity-group-from-edge-title": "Weet u zeker dat u de toewijzing van de entiteitsgroep '{{ entityGroupName }}' wilt opheffen?", + "unassign-entity-group-from-edge-text": "Na de bevestiging wordt de toewijzing van de entiteitsgroep ongedaan gemaakt en is deze niet toegankelijk via de edge.", + "unassign-entity-group-from-edge": "Toewijzing van entiteitsgroep aan edge ongedaan maken", + "unassign-entity-groups-from-edge-title": "Weet u zeker dat u de toewijzing van {{count}} entiteitsgroepen wilt opheffen?", + "unassign-entity-groups-from-edge-text": "Na de bevestiging wordt de toewijzing van entiteitsgroepen ongedaan gemaakt en zijn ze niet toegankelijk via de edge.", + "unassign-entity-groups-from-edge": "Toewijzing van entiteitsgroepen aan de edge ongedaan maken", + "unassign-scheduler-events-from-edge": "Toewijzing van scheduler events van edge ongedaan maken", + "unassign-scheduler-event-from-edge-title": "Weet u zeker dat u de toewijzing van de '{{schedulerEventName}}' van de planningsgebeurtenis wilt intrekken?", + "unassign-scheduler-event-from-edge-text": "Na de bevestiging wordt de toewijzing van de planningsgebeurtenis ongedaan gemaakt en is deze niet toegankelijk via de edge.", + "unassign-scheduler-events-from-edge-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 scheduler event} andere {# scheduler events} } wilt opheffen?", + "unassign-scheduler-events-from-edge-text": "Na de bevestiging worden alle geselecteerde scheduler events ongedaan gemaakt en zijn ze niet toegankelijk voor de edge.", + "manage-user-groups": "Gebruikersgroepen beheren", + "manage-asset-groups": "Asset groepen beheren", + "manage-device-groups": "Asset groepen beheren", + "manage-dashboard-groups": "Dashboardgroepen beheren", + "manage-entity-view-groups": "Entiteitsweergavegroepen beheren", + "manage-scheduler-events": "Scheduler-events beheren", + "manage-integrations": "Integraties beheren", + "assign-scheduler-event-to-edge-title": "Scheduler-gebeurtenissen toewijzen aan Edge", + "assign-scheduler-event-to-edge-text": "Selecteer de scheduler events die u aan de edge wilt toewijzen", + "assign-entity-groups-to-edge-text": "Selecteer de entiteitsgroepen die u aan de edge wilt toewijzen", + "assign-integration-to-edge-title": "Integraties toewijzen aan Edge", + "assign-integration-to-edge-text": "Selecteer de integraties die u aan de edge wilt toewijzen", + "missing-attributes-title": "Edge heeft ontbrekende attribuut(en)", + "missing-attributes-text": "Integratie(s) die aan de edge zijn toegewezen, hebben tijdelijke aanduidingen voor attributen die niet beschikbaar zijn aan deze edge.

Lijst met ontbrekende edge kenmerken:
{{missingEdgeAttributes}}", + "missing-all-related-attributes-title": "Edge(en) hebben ontbrekende attribuut(en)", + "missing-all-related-attributes-text": "Edge(s), gerelateerd aan integratie, hebben geen attributen die aanwezig zijn in de integratieconfiguratie als tijdelijke aanduidingen voor attributen.

Lijst met ontbrekende edge kenmerken:
{{missingEdgeAttributes}}", + "quick-overview-widget-header": "{{edgeName}} Snel overzicht" + }, + "edge-event": { + "type-dashboard": "Dashboard", + "type-asset": "Asset", + "type-device": "Device", + "type-device-profile": "Device Profiel", + "type-asset-profile": "Asset Profiel", + "type-entity-view": "Entiteit Weergave", + "type-alarm": "Alarm", + "type-entity-group": "Entiteitsgroep", + "type-rule-chain": "Rule chain", + "type-rule-chain-metadata": "Metagegevens van rule chain", + "type-edge": "Edge", + "type-user": "Gebruiker", + "type-customer": "Klant", + "type-relation": "Relatie", + "type-widgets-bundle": "Widgets Bundel", + "type-widgets-type": "Widgets Type", + "type-admin-settings": "Admin-instellingen", + "type-scheduler-event": "Scheduler Evenement", + "type-white-labeling": "White labelling", + "type-login-white-labeling": "Inloggen White Labeling", + "type-custom-translation": "Aangepaste vertaling", + "type-role": "Rol", + "type-group-permission": "Toestemming voor groepen", + "type-integration": "Integratie", + "type-converter": "Conversie type", + "action-type-added": "Toegevoegd", + "action-type-deleted": "Verwijderd", + "action-type-updated": "Bijgewerkt", + "action-type-post-attributes": "Attributen posten", + "action-type-attributes-updated": "Attributen bijgewerkt", + "action-type-attributes-deleted": "Attributen verwijderd", + "action-type-timeseries-updated": "Tijdreeks bijgewerkt", + "action-type-credentials-updated": "Inloggegevens bijgewerkt", + "action-type-assigned-to-customer": "Toegewezen aan klant", + "action-type-unassigned-from-customer": "Toewijzing van klant ongedaan gemaakt", + "action-type-relation-add-or-update": "Relatie toevoegen of bijwerken", + "action-type-relation-deleted": "Relatie verwijderd", + "action-type-rpc-call": "RPC-oproep", + "action-type-alarm-ack": "Alarm Ack", + "action-type-alarm-clear": "Alarm wissen", + "action-type-assigned-to-edge": "Toegewezen aan Edge", + "action-type-unassigned-from-edge": "Toewijzing van Edge ongedaan gemaakt", + "action-type-credentials-request": "Inloggegevens aanvragen", + "action-type-entity-merge-request": "Aanvraag voor samenvoeging van entiteiten", + "action-type-added-to-entity-group": "Toegevoegd aan entiteitsgroep", + "action-type-removed-from-entity-group": "Verwijderd uit entiteitsgroep", + "action-type-change-owner": "Eigenaar wijzigen", + "action-type-relations-deleted": "Relaties verwijderd" + }, + "error": { + "unable-to-connect": "Kan geen verbinding maken met de server! Controleer uw internetverbinding.", + "unhandled-error-code": "Onverwerkte foutcode: {{errorCode}}", + "unknown-error": "Onbekende fout" + }, + "entity": { + "entity": "Entiteit", + "entities": "Entiteiten", + "entities-count": "Aantal entiteiten", + "alarms-count": "Aantal alarmen", + "aliases": "Aliassen van entiteiten", + "entity-alias": "Alias van entiteit", + "unable-delete-entity-alias-title": "Entiteitsalias kan niet worden verwijderd", + "unable-delete-entity-alias-text": "Entiteitsalias '{{entityAlias}}' kan niet worden verwijderd omdat deze wordt gebruikt door de volgende widget(s):
{{widgetsList}}", + "duplicate-alias-error": "Dubbele alias gevonden '{{alias}}'.
Aliassen van entiteiten moeten uniek zijn binnen het dashboard.", + "missing-entity-filter-error": "Filter ontbreekt voor alias '{{alias}}'.", + "configure-alias": "Configureer de alias '{{alias}}'", + "alias": "Alias", + "alias-required": "Entiteitsalias is vereist.", + "remove-alias": "Entiteitsalias verwijderen", + "add-alias": "Entiteitsalias toevoegen", + "entity-list": "Lijst met entiteiten", + "entity-type": "Type entiteit", + "entity-types": "Soorten entiteiten", + "entity-type-list": "Lijst met entiteitstypen", + "any-entity": "Elke entiteit", + "enter-entity-type": "Entiteitstype invoeren", + "no-entities-matching": "Er zijn geen entiteiten gevonden die overeenkomen met '{{entity}}'.", + "no-entity-types-matching": "Er zijn geen entiteitstypen gevonden die overeenkomen met '{{entityType}}'.", + "name-starts-with": "Naam expressie", + "help-text": "Gebruik '%' naar behoefte: '%entity_name_contains%', '%entity_name_ends', 'entity_starts_with'.", + "use-entity-name-filter": "Filter gebruiken", + "entity-list-empty": "Geen entiteiten geselecteerd.", + "entity-type-list-empty": "Er zijn geen entiteitstypen geselecteerd.", + "entity-name-filter-required": "Filter voor entiteitsnamen is vereist.", + "entity-name-filter-no-entity-matched": "Er zijn geen entiteiten gevonden die beginnen met '{{entity}}'.", + "all-subtypes": "Alle", + "select-entities": "Entiteiten selecteren", + "no-aliases-found": "Geen aliassen gevonden.", + "no-alias-matching": "'{{alias}}' niet gevonden.", + "create-new-alias": "Maak een nieuwe aan!", + "key": "Sleutel", + "key-name": "Naam van de sleutel", + "no-keys-found": "Geen sleutels gevonden.", + "no-key-matching": "'{{key}}' niet gevonden.", + "create-new-key": "Maak een nieuwe aan!", + "type": "Type", + "type-required": "Entiteitstype is vereist.", + "type-device": "Device", + "type-devices": "Devices", + "list-of-devices": "{ count, plural, =1 {One device} andere {List of # devices} }", + "device-name-starts-with": "Devices waarvan de naam begint met '{{prefix}}'", + "type-device-profile": "Device profiel", + "type-device-profiles": "Device profielen", + "list-of-device-profiles": "{ count, plural, =1 {One device profile} andere {List of # device profiles} }", + "device-profile-name-starts-with": "Device profielen waarvan de naam begint met '{{prefix}}'", + "type-asset-profile": "Asset profiel", + "type-asset-profiles": "Asset profielen", + "list-of-asset-profiles": "{ count, plural, =1 {One asset profile} andere {List of # asset profiles} }", + "asset-profile-name-starts-with": "Assetprofielen waarvan de naam begint met '{{prefix}}'", + "type-asset": "Asset", + "type-assets": "Assets", + "list-of-assets": "{ count, plural, =1 {One asset} andere {List of # assets} }", + "asset-name-starts-with": "Assets waarvan de naam begint met '{{prefix}}'", + "type-entity-view": "Entiteit Weergave", + "type-entity-views": "Entiteitsweergaven", + "list-of-entity-views": "{ count, plural, =1 {One entity view} andere {List of # entity views} }", + "entity-view-name-starts-with": "Entiteitsweergaven waarvan de naam begint met '{{prefix}}'", + "type-rule": "Regel", + "type-rules": "Reglement", + "list-of-rules": "{ count, plural, =1 {One rule} andere {List of # rules} }", + "rule-name-starts-with": "Regels waarvan de naam begint met '{{prefix}}'", + "type-plugin": "Plug-in", + "type-plugins": "Insteekplaatsen", + "list-of-plugins": "{ count, plural, =1 {One plugin} andere {List of # plugins} }", + "plugin-name-starts-with": "Plug-ins waarvan de naam begint met '{{prefix}}'", + "type-tenant": "Tenant", + "type-tenants": "Tenants", + "list-of-tenants": "{ count, plural, =1 {One tenant} andere {List of # tenants} }", + "tenant-name-starts-with": "Tenants van wie de naam begint met '{{prefix}}'", + "type-tenant-profile": "Profiel van de tenant", + "type-tenant-profiles": "Profielen van tenants", + "list-of-tenant-profiles": "{ count, plural, =1 {One tenant profile} andere {List of # tenant profiles} }", + "tenant-profile-name-starts-with": "Tentant profielen waarvan de naam begint met '{{prefix}}'", + "type-customer": "Klant", + "type-customers": "Klanten", + "list-of-customers": "{ count, plural, =1 {One customer} andere {List of # customers} }", + "customer-name-starts-with": "Klanten van wie de naam begint met '{{prefix}}'", + "type-user": "Gebruiker", + "type-users": "Gebruikers", + "list-of-users": "{ count, plural, =1 {One user} andere {List of # users} }", + "user-name-starts-with": "Gebruikers van wie de naam begint met '{{prefix}}'", + "type-dashboard": "Dashboard", + "type-dashboards": "Dashboards", + "list-of-dashboards": "{ count, plural, =1 {One dashboard} andere {List of # dashboards} }", + "dashboard-name-starts-with": "Dashboards waarvan de naam begint met '{{prefix}}'", + "type-alarm": "Alarm", + "type-alarms": "Alarmen", + "list-of-alarms": "{ count, plural, =1 {One alarm} andere {List of # alarms} }", + "alarm-name-starts-with": "Alarmen waarvan de naam begint met '{{prefix}}'", + "type-rulechain": "Rule chains", + "type-rulechains": "Rule chains", + "list-of-rulechains": "{ count, plural, =1 {One rule chain} andere {List of # rule chains} }", + "rulechain-name-starts-with": "Rule chains waarvan de naam begint met '{{prefix}}'", + "type-scheduler-event": "Scheduler-event", + "type-scheduler-events": "Scheduler-events", + "list-of-scheduler-events": "{ count, plural, =1 {One scheduler event} andere {List of # scheduler events} }", + "scheduler-event-name-starts-with": "Scheduler-events waarvan de naam begint met '{{prefix}}'", + "type-blob-entity": "Blob-entiteit", + "type-blob-entities": "Blob-entiteiten", + "list-of-blob-entities": "{ count, plural, =1 {One blob entity} andere {List of # blob entities} }", + "blob-entity-name-starts-with": "Blob-entiteiten waarvan de naam begint met '{{prefix}}'", + "type-rulenode": "Rule node", + "type-rulenodes": "Rule nodes", + "list-of-rulenodes": "{ count, plural, =1 {One rule node} andere {List of # rule nodes} }", + "rulenode-name-starts-with": "Rule node waarvan de naam begint met '{{prefix}}'", + "type-current-customer": "Huidige klant", + "type-current-tenant": "Huidige tenant", + "type-current-user": "Huidige gebruiker", + "type-current-user-owner": "Huidige gebruikerseigenaar", + "type-widgets-bundle": "Widgets bundel", + "type-widgets-bundles": "Widgets bundels", + "list-of-widgets-bundles": "{ count, plural, =1 {One widgets bundle} andere {List of # widget bundles} }", + "search": "Entiteiten zoeken", + "selected-entities": "{ count, plural, =1 {1 entity} andere {# entities} } geselecteerd", + "entity-name": "Naam van de entiteit", + "entity-label": "Entiteitslabel", + "details": "Gegevens van de entiteit", + "no-entities-prompt": "Geen entiteiten gevonden", + "no-data": "Geen gegevens om weer te geven", + "columns-to-display": "Weer te geven kolommen", + "type-api-usage-state": "Api-gebruiksstatus", + "type-entity-group": "Entiteitsgroep", + "type-converter": "Gegevens converteren", + "type-converters": "Data-converters", + "list-of-converters": "{ count, plural, =1 {One data converter} andere {List of # data converters} }", + "converter-name-starts-with": "Dataconverters waarvan de naam begint met \"{{prefix}}\"", + "type-integration": "Integratie", + "type-integrations": "Integraties", + "list-of-integrations": "{ count, plural, =1 {One integration} andere {List of # integrations} }", + "integration-name-starts-with": "Integraties waarvan de naam begint met '{{prefix}}'", + "type-role": "Rol", + "type-roles": "Rollen", + "list-of-roles": "{ count, plural, =1 {One role} andere {List of # roles} }", + "role-name-starts-with": "Rollen waarvan de naam begint met '{{prefix}}'", + "type-group-permission": "Toestemming voor groepen", + "type-edge": "Edge", + "type-edges": "Edge", + "list-of-edges": "{ count, plural, =1 {One edge} andere {List of # edges} }", + "edge-name-starts-with": "Edge waarvan de naam begint met '{{prefix}}'", + "type-tb-resource": "Hulpbron", + "type-ota-package": "OTA-pakket", + "type-rpc": "RPC", + "type-queue": "Rij", + "type-notification": "Bekendmaking", + "type-notification-rule": "Meldingsregel", + "type-notification-target": "Ontvanger van de melding", + "type-notification-request": "Verzoek om kennisgeving", + "type-notification-template": "Kennisgeving sjabloon", + "customer-name": "Naam van de klant", + "sub-customer-name": "Naam van de subklant", + "parent-customer-name": "Naam van bovenliggende klant", + "parent-sub-customer-name": "Naam van bovenliggende subklant", + "include-customer-entities": "Klantentiteiten opnemen", + "include-sub-customer-entities": "Entiteiten van subklanten opnemen", + "groups": "Groepen" + }, + "entity-group": { + "entity-group": "Entiteitsgroep", + "details": "Details", + "columns": "Kolommen", + "add-column": "Kolom toevoegen", + "column-value": "Waarde", + "column-value-required": "Kolomwaarde is vereist.", + "column-title": "Titel", + "default-sort-order": "Standaard sorteervolgorde", + "default-sort-order-required": "De standaard sorteervolgorde is vereist.", + "hide-in-mobile-view": "Mobiel verborgen", + "use-cell-style-function": "Celstijlfunctie gebruiken", + "use-cell-content-function": "De functie voor celinhoud gebruiken", + "edit-column": "Kolom bewerken", + "column-details": "Kolom details", + "actions": "Acties", + "settings": "Instellingen", + "search": "Entiteitsgroepen zoeken", + "delete": "Entiteitsgroep verwijderen", + "name": "Naam", + "name-required": "Naam is verplicht.", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "description": "Omschrijving: __________", + "add": "Entiteitsgroep toevoegen", + "open-entity-group": "Entiteitsgroep openen", + "add-entity-group-text": "Nieuwe entiteitsgroep toevoegen", + "no-entity-groups-text": "Geen entiteitsgroepen gevonden", + "entity-group-details": "Details van entiteitsgroep", + "selected-entity-groups": "{ count, plural, =1 {1 entity group} andere {# entity groups} } geselecteerd", + "delete-entity-groups": "Entiteitsgroepen verwijderen", + "delete-entity-group-title": "Weet u zeker dat u de entiteitsgroep '{{entityGroupName}}' wilt verwijderen?", + "delete-entity-group-text": "Let op, na de bevestiging worden de entiteitsgroep en alle gerelateerde gegevens onherstelbaar.", + "delete-entity-groups-title": "Weet u zeker dat u { count, plural, =1 {1 entity group} andere {# entity groups} } wilt verwijderen?", + "delete-entity-groups-action-title": "Verwijder { count, plural, =1 {1 entity group} andere {# entity groups} }", + "delete-entity-groups-text": "Opgelet, na de bevestiging worden alle geselecteerde entiteitsgroepen verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "device-groups": "Asset groepen", + "shared-device-groups": "Groepen met gedeelde devices", + "asset-groups": "Asset groepen", + "shared-asset-groups": "Gedeelde activagroepen", + "customer-groups": "Klantengroepen", + "shared-customer-groups": "Gedeelde klantgroepen", + "device-group": "Apparaatgroep", + "asset-group": "Activagroep", + "user-group": "Gebruikersgroep", + "user-groups": "Gebruikersgroepen", + "customer-group": "Klantengroep", + "entity-view-groups": "Groepen voor entiteitsweergaven", + "shared-entity-view-groups": "Groepen met gedeelde entiteitsweergave", + "entity-view-group": "Groep voor entiteitsweergave", + "edge-groups": "Randgroepen", + "shared-edge-groups": "Gedeelde randgroepen", + "edge-group": "Edge groep", + "dashboard-groups": "Dashboard groepen", + "shared-dashboard-groups": "Gedeelde dashboardgroepen", + "dashboard-group": "Dashboard groep", + "fetch-more": "Haal meer op", + "column-type": { + "column-type": "Type kolom", + "client-attribute": "Cliënt attribuut", + "shared-attribute": "Gedeeld attribuut", + "server-attribute": "Server-attribuut", + "timeseries": "Timeseries", + "entity-field": "Entiteit veld" + }, + "column-type-required": "Kolomtype is vereist.", + "entity-field": { + "created-time": "Gecreëerde tijd", + "name": "Naam", + "type": "Type", + "device_profile": "Device profiel", + "asset_profile": "Asset profiel", + "assigned_customer": "Toegewezen klant", + "authority": "Autoriteit", + "first_name": "Voornaam", + "last_name": "Achternaam", + "email": "E-mail", + "title": "Titel", + "country": "Land", + "state": "Staat", + "city": "Stad", + "address": "Adres", + "address2": "Adres 2", + "zip": "Ritssluiting", + "phone": "Telefoon", + "label": "Etiket" + }, + "sort-order": { + "asc": "Oplopend", + "desc": "Aflopende", + "none": "Geen" + }, + "details-mode": { + "on-row-click": "Klik op rij", + "on-action-button-click": "Klik op de knop Details", + "disabled": "Invalide" + }, + "change-owner": "Eigenaar wijzigen", + "select-target-owner": "Selecteer doeleigenaar", + "no-owners-matching": "Er zijn geen eigenaren gevonden die overeenkomen met '{{owner}}'.", + "target-owner-required": "Doeleigenaar is vereist.", + "confirm-change-owner-title": "Weet u zeker dat u van eigenaar wilt veranderen voor { count, plural, =1 {1 selected entity} andere {# selected entities} }?", + "confirm-change-owner-text": "Opgelet, na de bevestiging worden alle geselecteerde entiteiten verwijderd van de huidige eigenaar en worden ze geplaatst in de groep 'Alle' van de doeleigenaar.", + "add-to-group": "Toevoegen aan groep", + "move-to-group": "Verplaatsen naar groep", + "select-entity-group": "Entiteitsgroep selecteren", + "no-entity-groups-matching": "Er zijn geen entiteitsgroepen gevonden die overeenkomen met '{{entityGroup}}'.", + "create-new-entity-group": "Maak een nieuwe aan!", + "target-entity-group-required": "Doelgroep is vereist.", + "select-user-group": "Selecteer gebruikersgroep", + "no-user-groups-matching": "Er zijn geen gebruikersgroepen gevonden die overeenkomen met '{{entityGroup}}'.", + "target-user-group-required": "Doelgroep is vereist.", + "remove-from-group": "Verwijderen uit groep", + "group-table-title": "Titel van groepstabel", + "enable-search": "Zoeken naar entiteiten inschakelen", + "enable-add": "Entiteiten toevoegen inschakelen", + "enable-delete": "Entiteiten verwijderen inschakelen", + "enable-selection": "Selectie van entiteiten inschakelen", + "enable-group-transfer": "Acties voor groepsoverdracht inschakelen", + "display-pagination": "Paginering weergeven", + "default-page-size": "Standaard paginaformaat", + "enable-assignment-actions": "Toewijzingsacties inschakelen", + "enable-credentials-management": "Beheer van referenties inschakelen", + "enable-login-as-user": "Inloggen als gebruikersactie inschakelen", + "enable-users-management": "Gebruikersbeheer inschakelen", + "enable-customers-management": "Klantenbeheer inschakelen", + "enable-assets-management": "Asset beheer inschakelen", + "enable-devices-management": "Device beheer inschakelen", + "enable-entity-views-management": "Beheer van entiteitsweergaven inschakelen", + "enable-edges-management": "Edge beheer inschakelen", + "enable-dashboards-management": "Dashboardbeheer inschakelen", + "enable-scheduler-events-management": "Beheer van scheduler events inschakelen", + "open-details-on": "Entiteitsdetails openen op", + "select-existing": "Bestaande entiteitsgroep selecteren", + "create-new": "Nieuwe entiteitsgroep maken", + "new-entity-group-name": "Naam van nieuwe entiteitsgroep", + "entity-group-list": "Lijst met entiteitsgroepen", + "entity-group-list-empty": "Geen entiteitsgroepen geselecteerd.", + "name-starts-with": "De naam van de entiteitsgroep begint met", + "entity-group-name-filter-required": "Filter voor de naam van de entiteitsgroep is vereist.", + "roles": "Rollen", + "permissions": "Machtigingen", + "public": "Publiek", + "entity-group-public": "Entiteitsgroep is openbaar", + "make-public": "Entiteitsgroep openbaar maken", + "make-private": "Entiteitsgroep privé maken", + "make-public-entity-group-title": "Weet u zeker dat u de entiteitsgroep '{{entityGroupName}}' openbaar wilt maken?", + "make-public-entity-group-text": "Na de bevestiging worden de entiteitengroep en al haar entiteiten openbaar gemaakt en toegankelijk gemaakt voor anderen.", + "make-private-entity-group-title": "Weet u zeker dat u de entiteitsgroep '{{entityGroupName}}' privé wilt maken?", + "make-private-entity-group-text": "Na de bevestiging worden de entiteitengroep en al zijn entiteiten privé gemaakt en zijn ze niet toegankelijk voor anderen.", + "share": "Entiteitsgroep delen", + "copyId": "Entiteitsgroep-id kopiëren", + "idCopiedMessage": "Entiteitsgroep-id is gekopieerd naar klembord", + "entity-group-name": "Naam van entiteitsgroep", + "all-users": "Alle gebruikers", + "owner": "Eigenaar", + "owner-required": "Eigenaar is verplicht.", + "manage-owner-and-groups": "Eigenaar en groepen beheren", + "owner-and-groups": "Eigenaar en groepen" + }, + "entity-field": { + "created-time": "Gecreëerde tijd", + "name": "Naam", + "type": "Type", + "first-name": "Voornaam", + "last-name": "Achternaam", + "email": "E-mail", + "title": "Titel", + "country": "Land", + "state": "Staat", + "city": "Stad", + "address": "Adres", + "address2": "Adres 2", + "zip": "Ritssluiting", + "phone": "Telefoon", + "label": "Etiket", + "configuration": "Configuratie", + "schedule": "Rooster", + "originatorId": "Initiator-ID", + "originatorType": "Type opsteller" + }, + "entity-view": { + "all": "Alle", + "all-entity-views": "Alle entiteitsweergaven", + "groups": "Groepen", + "shared": "Gedeeld", + "entity-view": "Entiteit Weergave", + "entity-view-required": "Entiteitsweergave is vereist.", + "entity-views": "Entiteitsweergaven", + "management": "Beheer van entiteitsweergaven", + "view-entity-views": "Entiteitsweergaven weergeven", + "entity-view-alias": "Alias voor entiteitsweergave", + "aliases": "Aliassen voor entiteitsweergave", + "no-alias-matching": "'{{alias}}' niet gevonden.", + "no-aliases-found": "Geen aliassen gevonden.", + "no-key-matching": "'{{key}}' niet gevonden.", + "no-keys-found": "Geen sleutels gevonden.", + "create-new-alias": "Maak een nieuwe aan!", + "create-new-key": "Maak een nieuwe aan!", + "duplicate-alias-error": "Dubbele alias gevonden '{{alias}}'.
Aliassen voor entiteitsweergave moeten uniek zijn binnen het dashboard.", + "configure-alias": "Configureer de alias '{{alias}}'", + "no-entity-views-matching": "Er zijn geen entiteitsweergaven gevonden die overeenkomen met '{{entity}}'.", + "public": "Publiek", + "alias": "Alias", + "alias-required": "Alias voor entiteitsweergave is vereist.", + "remove-alias": "Alias voor entiteitsweergave verwijderen", + "add-alias": "Alias voor entiteitsweergave toevoegen", + "name-starts-with": "Naamexpressie entiteitsweergave", + "help-text": "Gebruik '%' naar behoefte: '%entity-view_name_contains%', '%entity-view_name_ends', 'entity-view_starts_with'.", + "entity-view-list": "Lijst met entiteitsweergaven", + "use-entity-view-name-filter": "Filter gebruiken", + "entity-view-list-empty": "Geen entiteitsweergaven geselecteerd.", + "entity-view-name-filter-required": "Het naamfilter voor de entiteitsweergave is vereist.", + "entity-view-name-filter-no-entity-view-matched": "Er zijn geen entiteitsweergaven gevonden die beginnen met '{{entityView}}'.", + "add": "Entiteitsweergave toevoegen", + "entity-view-public": "Entiteitsweergave is openbaar", + "assign-to-customer": "Toewijzen aan klant", + "assign-entity-view-to-customer": "Entiteitsweergave(n) toewijzen aan klant", + "assign-entity-view-to-customer-text": "Selecteer de entiteitsweergaven die u aan de klant wilt toewijzen", + "no-entity-views-text": "Geen entiteitsweergaven gevonden", + "assign-to-customer-text": "Selecteer de klant om de entiteitsweergave(n) toe te wijzen", + "entity-view-details": "Details van entiteitsweergave", + "add-entity-view-text": "Nieuwe entiteitsweergave toevoegen", + "delete": "Entiteitsweergave verwijderen", + "assign-entity-views": "Entiteitsweergaven toewijzen", + "assign-entity-views-text": "Wijs { count, plural, =1 {1 entity view} andere {# entity views} } toe aan de klant", + "delete-entity-views": "Entiteitsweergaven verwijderen", + "make-public": "Entiteitsweergave openbaar maken", + "make-private": "Entiteitsweergave privé maken", + "unassign-from-customer": "Toewijzing van klant ongedaan maken", + "unassign-entity-views": "Toewijzing van entiteitsweergaven intrekken", + "unassign-entity-views-action-title": "Toewijzing { count, plural, =1 {1 entity view} andere {# entity views} } van klant ongedaan maken", + "assign-new-entity-view": "Nieuwe entiteitsweergave toewijzen", + "delete-entity-view-title": "Weet u zeker dat u de entiteitsweergave '{{entityViewName}}' wilt verwijderen?", + "delete-entity-view-text": "Opgelet, na de bevestiging worden de entiteitsweergave en alle gerelateerde gegevens onherstelbaar.", + "delete-entity-views-title": "Weet u zeker dat u { count, plural, =1 {1 entity view} andere {# entity views} } wilt verwijderen?", + "delete-entity-views-action-title": "Verwijder { count, plural, =1 {1 entity view} andere {# entity views} }", + "delete-entity-views-text": "Opgelet, na de bevestiging worden alle geselecteerde entiteitsweergaven verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "make-public-entity-view-title": "Weet u zeker dat u de entiteitsweergave '{{entityViewName}}' openbaar wilt maken?", + "make-public-entity-view-text": "Na de bevestiging worden de entiteitsweergave en al haar gegevens openbaar en toegankelijk gemaakt voor anderen.", + "make-private-entity-view-title": "Weet u zeker dat u de entiteitsweergave '{{entityViewName}}' privé wilt maken?", + "make-private-entity-view-text": "Na de bevestiging worden de entiteitsweergave en al zijn gegevens privé gemaakt en zijn ze niet toegankelijk voor anderen.", + "unassign-entity-view-title": "Weet u zeker dat u de toewijzing van de entiteitsweergave '{{entityViewName}}' wilt opheffen?", + "unassign-entity-view-text": "Na de bevestiging wordt de toewijzing van de entiteitsweergave ongedaan gemaakt en is deze niet toegankelijk voor de klant.", + "unassign-entity-view": "Toewijzing van entiteitsweergave ongedaan maken", + "unassign-entity-views-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 entity view} andere {# entity views} } wilt opheffen?", + "unassign-entity-views-text": "Na de bevestiging worden alle geselecteerde entiteitsweergaven ongedaan gemaakt en zijn ze niet toegankelijk voor de klant.", + "entity-view-type": "Type entiteitsweergave", + "entity-view-type-required": "Het type Entiteitsweergave is vereist.", + "select-entity-view-type": "Weergavetype entiteit selecteren", + "enter-entity-view-type": "Entiteitsweergavetype invoeren", + "any-entity-view": "Elke entiteitsweergave", + "no-entity-view-types-matching": "Er zijn geen entiteitsweergavetypen gevonden die overeenkomen met '{{entitySubtype}}'.", + "entity-view-type-list-empty": "Er zijn geen types entiteitsweergaven geselecteerd.", + "entity-view-types": "Typen entiteitsweergaven", + "created-time": "Gecreëerde tijd", + "name": "Naam", + "name-required": "Naam is verplicht.", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "type-max-length": "Het type entiteitsweergave moet kleiner zijn dan 256 tekens", + "description": "Omschrijving: __________", + "events": "Events", + "details": "Details", + "copyId": "Entiteitsweergave-id kopiëren", + "idCopiedMessage": "Entiteitsweergave-id is gekopieerd naar klembord", + "assignedToCustomer": "Toegewezen aan klant", + "unable-entity-view-device-alias-title": "Kan alias voor entiteitsweergave niet verwijderen", + "unable-entity-view-device-alias-text": "Entiteitsweergave device alias '{{entityViewAlias}}' kan niet worden verwijderd omdat deze wordt gebruikt door de volgende widget(s):
{{widgetsList}}", + "select-entity-view": "Entiteitsweergave selecteren", + "start-date": "Begindatum", + "start-ts": "Begintijd", + "end-date": "Einddatum", + "end-ts": "Eindtijd", + "date-limits": "Datumlimieten", + "client-attributes": "Attributen van de klant", + "shared-attributes": "Gedeelde attributen", + "server-attributes": "Server-attributen", + "timeseries": "Timeseries", + "client-attributes-placeholder": "Attributen van de klant", + "shared-attributes-placeholder": "Gedeelde attributen", + "server-attributes-placeholder": "Server-attributen", + "timeseries-placeholder": "Timeseries", + "target-entity": "Doelentiteit", + "attributes-propagation": "Doorgifte van attributen", + "attributes-propagation-hint": "Entiteitsweergave kopieert automatisch gespecificeerde attributen van doelentiteit telkens wanneer u deze entiteitsweergave opslaat of bijwerkt. Om prestatieredenen worden de attributen van de doelentiteit niet doorgegeven aan de entiteitsweergave bij elke kenmerkwijziging. U kunt automatische doorgifte inschakelen door het rulenode 'kopiëren naar weergave' in uw rule chain te configureren en berichten 'Attributen posten' en 'Attributen bijgewerkt' te koppelen aan het nieuwe rule node.", + "timeseries-data": "Tijdreeksgegevens", + "timeseries-data-hint": "Configureer timeseries sleutels van de doelentiteit die toegankelijk zijn voor de entiteitsweergave. Deze timeseries gegevens zijn niet editeerbaar.", + "select-group-to-add": "Selecteer de doelgroep om geselecteerde entiteitsweergaven toe te voegen", + "select-group-to-move": "Selecteer de doelgroep om geselecteerde entiteitsweergaven te verplaatsen", + "remove-entity-views-from-group": "Weet je zeker dat je { count, plural, =1 {1 entity view} andere {# entity views} } uit groep '{{entityGroup}}' wilt verwijderen?", + "group": "Groep entiteitsweergaven", + "list-of-groups": "{ count, plural, =1 {One entity view group} andere {List of # entity view groups} }", + "group-name-starts-with": "Entiteitsweergavegroepen waarvan de naam begint met '{{prefix}}'", + "search": "Entiteitsweergaven zoeken", + "selected-entity-views": "{ count, plural, =1 {1 entity view} andere {# entity views} } geselecteerd", + "assign-entity-view-to-edge": "Entiteitsweergave(n) toewijzen aan edge", + "assign-entity-view-to-edge-text": "Selecteer de entiteitsweergaven die u aan de edge wilt toewijzen", + "unassign-entity-view-from-edge-title": "Weet u zeker dat u de toewijzing van de entiteitsweergave '{{entityViewName}}' wilt opheffen?", + "unassign-entity-view-from-edge-text": "Na de bevestiging wordt de toewijzing van de entiteitsweergave ongedaan gemaakt en is deze niet toegankelijk via de edge.", + "unassign-entity-views-from-edge-action-title": "Toewijzing { count, plural, =1 {1 entity view} andere {# entity views} } van edge ongedaan maken", + "unassign-entity-view-from-edge": "Toewijzing van entiteitsweergave ongedaan maken", + "unassign-entity-views-from-edge-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 entity view} andere {# entity views} } wilt opheffen?", + "unassign-entity-views-from-edge-text": "Na de bevestiging worden alle geselecteerde entiteitsweergaven ongedaan gemaakt en zijn ze niet toegankelijk via de edge." + }, + "event": { + "events": "Events", + "event-type": "Type event", + "events-filter": "Events filter", + "clean-events": "Events wissen", + "type-error": "Fout", + "type-lc-event": "Levens cyclus event", + "type-stats": "Statistiek", + "type-debug-converter": "Debuggen", + "type-debug-integration": "Debuggen", + "type-debug-rule-node": "Debuggen", + "type-debug-rule-chain": "Debuggen", + "no-events-prompt": "Geen events gevonden", + "error": "Fout", + "alarm": "Alarm", + "event-time": "Tijd voor de event", + "server": "Server", + "body": "Body", + "method": "Methode", + "type": "Type", + "in": "In", + "out": "Buiten", + "metadata": "Metagegevens", + "message": "Bericht", + "entity": "Entiteit", + "message-id": "Bericht-ID", + "copy-message-id": "Kopieer bericht-ID", + "message-type": "Type bericht", + "data-type": "Soort gegevens", + "relation-type": "Relatie Type", + "data": "Data", + "event": "Event", + "status": "Status", + "success": "Succes", + "failed": "Mislukt", + "messages-processed": "Verwerkte berichten", + "max-messages-processed": "Maximum aantal verwerkte berichten", + "min-messages-processed": "Minimaal aantal verwerkte berichten", + "errors-occurred": "Er zijn fouten opgetreden", + "max-errors-occurred": "Maximale fouten opgetreden", + "min-errors-occurred": "Er zijn minimale fouten opgetreden", + "min-value": "Minimale waarde is 0.", + "all-events": "Alle", + "has-error": "Heeft fout", + "entity-id": "Entiteit-ID", + "copy-entity-id": "Entiteits-ID kopiëren", + "entity-type": "Type entiteit", + "clear-filter": "Filter wissen", + "clear-request-title": "Wis alle events", + "clear-request-text": "Weet je zeker dat je alle events wilt wissen?", + "started": "Begon", + "updated": "Bijgewerkt", + "stopped": "Gestopt" + }, + "extension": { + "extensions": "Extensies", + "selected-extensions": "{ count, plural, =1 {1 extension} andere {# extensions} } geselecteerd", + "type": "Type", + "key": "Sleutel", + "value": "Waarde", + "id": "Legitimatiebewijs", + "extension-id": "Extensie-id", + "extension-type": "Type extensie", + "transformer-json": "JSON *", + "unique-id-required": "De huidige extensie-id bestaat al.", + "delete": "Extensie verwijderen", + "add": "Extensie toevoegen", + "edit": "Extensie bewerken", + "view": "Bekijk extensie", + "delete-extension-title": "Weet je zeker dat je de extensie '{{extensionId}}' wilt verwijderen?", + "delete-extension-text": "Opgelet, na de bevestiging worden de extensie en alle gerelateerde gegevens onherstelbaar.", + "delete-extensions-title": "Weet u zeker dat u { count, plural, =1 {1 extension} andere {# extensions} } wilt verwijderen?", + "delete-extensions-text": "Opgelet, na de bevestiging worden alle geselecteerde extensies verwijderd.", + "converters": "Converters", + "converter-id": "Converter-id", + "configuration": "Configuratie", + "converter-configurations": "Converter configuraties", + "token": "Beveiligingstoken", + "add-converter": "Converter toevoegen", + "add-config": "Converterconfiguratie toevoegen", + "device-name-expression": "Expressie van device naam", + "device-type-expression": "Expressie van device type", + "custom": "Gewoonte", + "to-double": "Verdubbelen", + "transformer": "Transformator", + "json-required": "Transformator json is vereist.", + "json-parse": "Kan transformator json niet parseren.", + "attributes": "Attributen", + "add-attribute": "Attribuut toevoegen", + "add-map": "Toewijzingselement toevoegen", + "timeseries": "Timeseries", + "add-timeseries": "Timeseries toevoegen", + "field-required": "Veld is verplicht", + "brokers": "Brokers", + "add-broker": "Broker toevoegen", + "host": "Server host", + "port": "Haven", + "port-range": "De poort moet tussen 1 en 65535 liggen.", + "ssl": "Ssl", + "credentials": "Inloggegevens", + "username": "Gebruikersnaam", + "password": "Wachtwoord", + "retry-interval": "Interval voor opnieuw proberen in milliseconden", + "sas": "Handtekening voor gedeelde toegang", + "anonymous": "Anoniem", + "basic": "Basis", + "pem": "PEM", + "ca-cert": "CA-certificaatbestand *", + "private-key": "Bestand met privésleutel *", + "cert": "Certificaat bestand *", + "no-file": "Geen bestand geselecteerd.", + "drop-file": "Zet een bestand neer of klik om een bestand te selecteren om te uploaden.", + "mapping": "Kartering", + "topic-filter": "Onderwerp filter", + "converter-type": "Type converter", + "converter-json": "Json", + "json-name-expression": "JSON-expressie voor device naam", + "topic-name-expression": "Topic expressie device naam", + "json-type-expression": "json-expressie van device type", + "topic-type-expression": "Topic expressie van device type", + "attribute-key-expression": "Expressie van kenmerksleutel", + "attr-json-key-expression": "Json-expressie van kenmerksleutel", + "attr-topic-key-expression": "Topic expressie van kenmerk", + "request-id-expression": "ID-expressie aanvragen", + "request-id-json-expression": "Aanvraag-id json-expressie", + "request-id-topic-expression": "Topic expressie voor aanvraag-id", + "response-topic-expression": "Expressie van topic response", + "value-expression": "Waarde expressie", + "topic": "Onderwerp", + "timeout": "Time-out in milliseconden", + "converter-json-required": "Converter json is vereist.", + "converter-json-parse": "Kan converter json niet parseren.", + "filter-expression": "Expressie filteren", + "connect-requests": "Verbind aanvragen", + "add-connect-request": "Verbindingsverzoek toevoegen", + "disconnect-requests": "Verzoeken om de verbinding te verbreken", + "add-disconnect-request": "Verzoek tot verbroken verbinding toevoegen", + "attribute-requests": "Attribuut aanvragen", + "add-attribute-request": "Attribuutaanvraag toevoegen", + "attribute-updates": "Updates van attributen", + "add-attribute-update": "Attribuutupdate toevoegen", + "server-side-rpc": "RPC aan de serverzijde", + "add-server-side-rpc-request": "RPC-verzoek aan serverzijde toevoegen", + "device-name-filter": "Filter voor device naam", + "attribute-filter": "Attribuut filter", + "method-filter": "Methode filter", + "request-topic-expression": "Topic expressie aanvragen", + "response-timeout": "Time-out voor respons in milliseconden", + "topic-expression": "Onderwerp expressie", + "client-scope": "Toepassingsgebied van de klant", + "add-device": "Device toevoegen", + "opc-server": "Servers", + "opc-add-server": "Server toevoegen", + "opc-add-server-prompt": "Gelieve server toe te voegen", + "opc-application-name": "Naam van de toepassing", + "opc-application-uri": "Applicatie uri", + "opc-scan-period-in-seconds": "Scanperiode in seconden", + "opc-security": "Veiligheid", + "opc-identity": "Identiteit", + "opc-keystore": "Sleutel opslag", + "opc-type": "Type", + "opc-keystore-type": "Type", + "opc-keystore-location": "Plaats*", + "opc-keystore-password": "Wachtwoord", + "opc-keystore-alias": "Alias", + "opc-keystore-key-password": "Sleutel wachtwoord", + "opc-device-node-pattern": "Knooppuntpatroon van het device", + "opc-device-name-pattern": "Patroon van device naam", + "modbus-server": "Servers", + "modbus-add-server": "Server toevoegen", + "modbus-add-server-prompt": "Gelieve server toe te voegen", + "modbus-transport": "Vervoer", + "modbus-tcp-reconnect": "Automatisch opnieuw verbinding maken", + "modbus-rtu-over-tcp": "RTU via TCP", + "modbus-port-name": "Naam seriële poort", + "modbus-encoding": "Codering", + "modbus-parity": "Pariteit", + "modbus-baudrate": "Baudrate", + "modbus-databits": "Data bits gegevens", + "modbus-stopbits": "Data bits stop", + "modbus-databits-range": "Data bits moeten tussen 7 en 8 liggen.", + "modbus-stopbits-range": "Stop bits moeten in een bereik van 1 tot 2 liggen.", + "modbus-unit-id": "Eenheid-ID", + "modbus-unit-id-range": "De eenheids-ID moet tussen 1 en 247 liggen.", + "modbus-device-name": "Naam van het device", + "modbus-poll-period": "Enquête periode (ms)", + "modbus-attributes-poll-period": "Attributen enquêteperiode (ms)", + "modbus-timeseries-poll-period": "Tijdreeks-enquêteperiode (ms)", + "modbus-poll-period-range": "De enquêteperiode moet een positieve waarde hebben.", + "modbus-tag": "Label", + "modbus-function": "Functie", + "modbus-register-address": "Adres registreren", + "modbus-register-address-range": "Het registratieadres moet tussen 0 en 65535 liggen.", + "modbus-register-bit-index": "De index van het bit", + "modbus-register-bit-index-range": "De bitindex moet tussen 0 en 15 liggen.", + "modbus-register-count": "Aantal registreren", + "modbus-register-count-range": "Het aantal registers moet een positieve waarde zijn.", + "modbus-byte-order": "Byte volgorde", + "sync": { + "status": "Status", + "sync": "Sync", + "not-sync": "Niet synchroniseren", + "last-sync-time": "Laatste synchronisatietijd", + "not-available": "Niet beschikbaar" + }, + "export-extensions-configuration": "Configuratie van extensies exporteren", + "import-extensions-configuration": "Configuratie van extensies importeren", + "import-extensions": "Extensies importeren", + "import-extension": "Extensie importeren", + "export-extension": "Export extensie", + "file": "Extensies bestand", + "invalid-file-error": "Ongeldig extensiebestand", + "text": "SMS", + "json": "JSON", + "binary": "BINAIR", + "hex": "HEX" + }, + "feature": { + "advanced-features": "Geavanceerde functies" + }, + "filter": { + "add": "Filter toevoegen", + "edit": "Filter bewerken", + "name": "Naam van filter", + "name-required": "Filternaam is vereist.", + "duplicate-filter": "Filter met dezelfde naam bestaat al.", + "filters": "Filters", + "unable-delete-filter-title": "Filter kan niet worden verwijderd", + "unable-delete-filter-text": "Filter '{{filter}}' kan niet worden verwijderd omdat het wordt gebruikt door de volgende widget(s):
{{widgetsList}}", + "duplicate-filter-error": "Duplicaatfilter gevonden '{{filter}}'.
Filters moeten uniek zijn binnen het dashboard.", + "missing-key-filters-error": "Sleutelfilters ontbreken voor filter '{{filter}}'.", + "filter": "Filter", + "editable": "Bewerkbaar", + "no-filters-found": "Geen filters gevonden.", + "no-filter-text": "Geen filter gespecificeerd", + "add-filter-prompt": "Filter toevoegen", + "no-filter-matching": "'{{filter}}' niet gevonden.", + "create-new-filter": "Maak een nieuwe aan!", + "filter-required": "Filter is vereist.", + "operation": { + "operation": "Operatie", + "equal": "gelijk", + "not-equal": "Niet gelijk", + "starts-with": "begint met", + "ends-with": "eindigt met", + "contains": "Bevat", + "not-contains": "Bevat niet", + "greater": "groter dan", + "less": "minder dan", + "greater-or-equal": "groter of gelijk", + "less-or-equal": "minder of gelijk aan", + "and": "en", + "or": "of", + "in": "in", + "not-in": "Niet in" + }, + "ignore-case": "Hoofdlettergebruik negeren", + "value": "Waarde", + "remove-filter": "Filter verwijderen", + "duplicate-filter-action": "Filter dupliceren", + "preview": "Voorbeeld van filter", + "no-filters": "Geen filters geconfigureerd", + "add-filter": "Filter toevoegen", + "add-complex-filter": "Complex filter toevoegen", + "add-complex": "Complex toevoegen", + "complex-filter": "Complex filter", + "edit-complex-filter": "Complex filter bewerken", + "edit-filter-user-params": "Gebruikersparameters voor filter predicate bewerken", + "filter-user-params": "Gebruikersparameters voor predicaten filteren", + "user-parameters": "Parameters van de gebruiker", + "display-label": "Label om weer te geven", + "autogenerated-label": "Automatisch label genereren", + "order-priority": "Prioriteit voor veldorders", + "key-filter": "Toets filter", + "key-filters": "Belangrijkste filters", + "key-name": "Naam van de sleutel", + "key-name-required": "De naam van de sleutel is vereist.", + "key-type": { + "key-type": "Type sleutel", + "attribute": "Attribuut", + "timeseries": "Timeseries", + "entity-field": "Entiteit veld", + "constant": "Constant" + }, + "value-type": { + "value-type": "Soort waarde", + "string": "Snaar", + "numeric": "Numeriek", + "boolean": "Booleaans", + "date-time": "Datum/tijd" + }, + "value-type-required": "Het type sleutelwaarde is vereist.", + "key-value-type-change-title": "Weet u zeker dat u het type sleutelwaarde wilt wijzigen?", + "key-value-type-change-message": "Als u het nieuwe waardetype bevestigt, worden alle ingevoerde toetsfilters verwijderd.", + "no-key-filters": "Geen toetsfilters geconfigureerd", + "add-key-filter": "Sleutelfilter toevoegen", + "remove-key-filter": "Sleutelfilter verwijderen", + "edit-key-filter": "Sleutelfilter bewerken", + "date": "Datum", + "time": "Tijd", + "current-tenant": "Huidige tenant", + "current-customer": "Huidige klant", + "current-user": "Huidige gebruiker", + "current-device": "Huidig device", + "default-value": "Standaardwaarde", + "dynamic-source-type": "Dynamisch brontype", + "dynamic-value": "Dynamische waarde", + "no-dynamic-value": "Geen dynamische waarde", + "source-attribute": "Bron attribuut", + "switch-to-dynamic-value": "Overschakelen naar dynamische waarde", + "switch-to-default-value": "Overschakelen naar standaardwaarde", + "inherit-owner": "Erven van eigenaar", + "source-attribute-not-set": "Als het bronkenmerk niet is ingesteld" + }, + "fullscreen": { + "expand": "Uitvouwen naar volledig scherm", + "exit": "Volledig scherm afsluiten", + "toggle": "Modus voor volledig scherm in- en uitschakelen", + "fullscreen": "Volledig scherm" + }, + "function": { + "function": "Functie" + }, + "gateway": { + "add-entry": "Configuratie toevoegen", + "connector-add": "Nieuwe connector toevoegen", + "connector-enabled": "Connector inschakelen", + "connector-name": "Naam van de connector", + "connector-name-required": "De naam van de connector is vereist.", + "connector-type": "Type aansluiting", + "connector-type-required": "Het type connector is vereist.", + "connectors": "Configuratie van connectoren", + "create-new-gateway": "Een nieuwe gateway maken", + "create-new-gateway-text": "Weet u zeker dat u een nieuwe gateway wilt maken met de naam: '{{gatewayName}}'?", + "delete": "Configuratie verwijderen", + "download-tip": "Configuratiebestand downloaden", + "gateway": "Gateway", + "gateway-exists": "Device met dezelfde naam bestaat al.", + "gateway-name": "Naam van de gateway", + "gateway-name-required": "De naam van de gateway is vereist.", + "gateway-saved": "Gatewayconfiguratie succesvol opgeslagen.", + "json-parse": "Ongeldige JSON.", + "json-required": "Het veld mag niet leeg zijn.", + "no-connectors": "Geen connectoren", + "no-data": "Geen configuraties", + "no-gateway-found": "Geen gateway gevonden.", + "no-gateway-matching": "'{{item}}' niet gevonden.", + "path-logs": "Pad naar logbestanden", + "path-logs-required": "Pad is vereist.", + "remote": "Configuratie op afstand", + "remote-logging-level": "Registratie niveau", + "remove-entry": "Configuratie verwijderen", + "save-tip": "Configuratiebestand opslaan", + "security-type": "Soort beveiliging", + "security-types": { + "access-token": "Toegang tot token", + "tls": "TLS (TLS)" + }, + "storage": "Opslag", + "storage-max-file-records": "Maximum aantal records in bestand", + "storage-max-files": "Maximaal aantal bestanden", + "storage-max-files-min": "Minimum aantal is 1.", + "storage-max-files-pattern": "Nummer is niet geldig.", + "storage-max-files-required": "Nummer is vereist.", + "storage-max-records": "Maximum aantal records in opslag", + "storage-max-records-min": "Minimum aantal records is 1.", + "storage-max-records-pattern": "Nummer is niet geldig.", + "storage-max-records-required": "Maximale records zijn vereist.", + "storage-pack-size": "Maximale pakketgrootte voor events", + "storage-pack-size-min": "Minimum aantal is 1.", + "storage-pack-size-pattern": "Nummer is niet geldig.", + "storage-pack-size-required": "De maximale pakketgrootte van het event is vereist.", + "storage-path": "Opslag pad", + "storage-path-required": "Opslagpad is vereist.", + "storage-type": "Type opslag", + "storage-types": { + "file-storage": "Opslag van bestanden", + "memory-storage": "Geheugen opslag" + }, + "thingsboard": "Dingen Bord", + "thingsboard-host": "ThingsBoard-gastheer", + "thingsboard-host-required": "Server host is vereist.", + "thingsboard-port": "ThingsBoard-poort", + "thingsboard-port-max": "Het maximale poortnummer is 65535.", + "thingsboard-port-min": "Het minimale poortnummer is 1.", + "thingsboard-port-pattern": "Poort is niet geldig.", + "thingsboard-port-required": "Poort is vereist.", + "tidy": "Ordelijk", + "tidy-tip": "Opgeruimde configuratie JSON", + "title-connectors-json": "Configuratie van connector {{typeName}}", + "tls-path-ca-certificate": "Pad naar CA-certificaat op gateway", + "tls-path-client-certificate": "Pad naar clientcertificaat op gateway", + "tls-path-private-key": "Pad naar privésleutel op gateway", + "toggle-fullscreen": "Volledig scherm in- en uitschakelen", + "transformer-json-config": "Configuratie JSON*", + "update-config": "Configuratie JSON toevoegen/bijwerken" + }, + "grid": { + "delete-item-title": "Weet u zeker dat u dit item wilt verwijderen?", + "delete-item-text": "Opgelet, na de bevestiging zullen dit item en alle gerelateerde gegevens onherstelbaar worden.", + "delete-items-title": "Weet u zeker dat u { count, plural, =1 {1 item} andere {# items} } wilt verwijderen?", + "delete-items-action-title": "Verwijder { count, plural, =1 {1 item} andere {# items} }", + "delete-items-text": "Opgelet, na de bevestiging worden alle geselecteerde items verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "add-item-text": "Nieuw item toevoegen", + "no-items-text": "Geen items gevonden", + "item-details": "Details van het artikel", + "delete-item": "Item verwijderen", + "delete-items": "Items verwijderen", + "scroll-to-top": "Scroll naar bovenzijde" + }, + "help": { + "goto-help-page": "Ga naar de helppagina", + "show-help": "Hulp tonen" + }, + "home": { + "home": "Thuis", + "profile": "Profiel", + "logout": "Logout", + "menu": "Menu", + "avatar": "Avatar", + "open-user-menu": "Gebruikersmenu openen" + }, + "file-input": { + "browse-file": "Blader door het bestand", + "browse-files": "Blader door bestanden" + }, + "image-input": { + "drop-image-or": "Een afbeelding slepen en neerzetten of", + "drop-images-or": "Sleep een afbeelding of", + "no-images": "Geen afbeeldingen geselecteerd", + "images": "beelden" + }, + "import": { + "no-file": "Geen bestand geselecteerd", + "drop-file": "Zet een JSON-bestand neer of klik om een bestand te selecteren om te uploaden.", + "drop-csv-file": "Zet een CSV-bestand neer of klik om een bestand te selecteren om te uploaden.", + "drop-json-file-or": "Een JSON-bestand slepen en neerzetten of", + "drop-file-csv": "Zet een CSV-bestand neer of klik om een bestand te selecteren om te uploaden.", + "drop-file-csv-or": "Een CSV-bestand slepen en neerzetten of", + "column-value": "Waarde", + "column-title": "Titel", + "column-example": "Voorbeeld van waardegegevens", + "column-key": "Kenmerk-/telemetriesleutel", + "credentials": "Geloofsbrief", + "csv-delimiter": "CSV-scheidingsteken", + "csv-first-line-header": "De eerste rule bevat kolomnamen", + "csv-update-data": "Attributen/telemetrie bijwerken", + "details": "Details", + "import-csv-number-columns-error": "Een bestand moet ten minste twee kolommen bevatten", + "import-csv-invalid-format-error": "Ongeldige bestandsindeling. Regel: '{{line}}'", + "column-type": { + "name": "Naam", + "type": "Type", + "label": "Etiket", + "column-type": "Type kolom", + "client-attribute": "Cliënt attribuut", + "shared-attribute": "Gedeeld attribuut", + "server-attribute": "Server-attribuut", + "timeseries": "Timeseries", + "entity-field": "Entiteit veld", + "access-token": "Toegang token", + "x509": "X.509", + "mqtt": { + "client-id": "MQTT-client-id", + "user-name": "MQTT-gebruikersnaam", + "password": "MQTT-wachtwoord" + }, + "lwm2m": { + "client-endpoint": "Naam van de LwM2M-endpoint", + "security-config-mode": "LwM2M-modus voor beveiligingsconfiguratie", + "client-identity": "Identiteit van LwM2M-client", + "client-key": "LwM2M-clientsleutel", + "client-cert": "Openbare sleutel van LwM2M-client", + "bootstrap-server-security-mode": "LwM2M bootstrap-serverbeveiligingsmodus", + "bootstrap-server-secret-key": "LwM2M bootstrap server geheime sleutel", + "bootstrap-server-public-key-id": "LwM2M opstarttrap, server openbare sleutel of id", + "lwm2m-server-security-mode": "LwM2M-server beveiligingsmodus", + "lwm2m-server-secret-key": "Geheime sleutel van de LwM2M-server", + "lwm2m-server-public-key-id": "Openbare sleutel of id van de LwM2M-server" + }, + "isgateway": "Is Gateway", + "activity-time-from-gateway-device": "Activiteitstijd vanaf gateway-device", + "description": "Omschrijving: __________", + "edge-license-key": "Licentiesleutel", + "cloud-endpoint": "Cloud-eindpunt", + "routing-key": "Edge routing sleutel", + "secret": "Edge geheim" + }, + "stepper-text": { + "select-file": "Selecteer een bestand", + "configuration": "Configuratie importeren", + "column-type": "Kolomtype selecteren", + "creat-entities": "Nieuwe entiteiten maken" + }, + "message": { + "create-entities": "{{count}} zijn met succes nieuwe entiteiten gecreëerd.", + "update-entities": "{{count}} entiteiten zijn bijgewerkt.", + "error-entities": "Er is een fout opgetreden bij het maken van {{count}} entiteiten." + } + }, + "integration": { + "integration": "Integratie", + "integrations": "Integraties", + "integrations-center": "Integratiecentrum", + "select-integration": "Selecteer integratie", + "no-integrations-matching": "Er zijn geen integraties gevonden die overeenkomen met '{{entity}}'.", + "integration-required": "Integratie is vereist", + "delete": "Integratie verwijderen", + "management": "Beheer van integraties", + "add-integration-text": "Nieuwe integratie toevoegen", + "no-integrations-text": "Geen integraties gevonden", + "selected-integrations": "{ count, plural, =1 {1 integration} andere {# integrations} } geselecteerd", + "delete-integration-title": "Weet je zeker dat je de integratie '{{integrationName}}' wilt verwijderen?", + "delete-integration-text": "Opgelet, na de bevestiging worden de integratie en alle gerelateerde gegevens onherstelbaar.", + "delete-integrations-title": "Weet u zeker dat u { count, plural, =1 {1 integration} andere {# integrations} } wilt verwijderen?", + "delete-integrations-action-title": "Verwijder { count, plural, =1 {1 integration} andere {# integrations} }", + "delete-integrations-text": "Opgelet, na de bevestiging worden alle geselecteerde integraties verwijderd en worden alle gerelateerde gegevens onherstelbaar.", + "events": "Events", + "enabled": "Integratie inschakelen", + "allow-create-devices-or-assets": "Devices of assets maken toestaan", + "all-types": "Alle integratietypes", + "add": "Integratie toevoegen", + "search": "Integraties zoeken", + "integration-details": "Details van de integratie", + "details": "Details", + "copyId": "Integratie-ID kopiëren", + "idCopiedMessage": "Integratie-id is gekopieerd naar klembord", + "debug-mode": "Foutopsporingsmodus", + "enable-security": "Beveiliging inschakelen", + "enable-security-new": "Beveiliging inschakelen voor automatische tokenupdates", + "headers-filter": "Filter voor kopteksten", + "header": "Rubriek", + "no-headers-filter": "Geen headers filter", + "downlink-url": "Downlink URL", + "downlink-url-required": "Downlink-URL is vereist", + "create-loriot-output": "Uitvoer van Loriot-toepassingen maken", + "send-downlink": "Downlink verzenden", + "server": "Server", + "server-required": "Server is vereist", + "domain": "Domein", + "app-id": "Toepassings-ID", + "app-id-required": "Toepassings-ID is vereist", + "app-token": "Token voor toegang tot toepassing", + "app-token-required": "Application Access Token is vereist", + "email": "E-mail", + "email-required": "E-mail is verplicht", + "application-uri": "Toepassings-URI", + "as-id": "AS ID", + "as-id-required": "AS-ID is vereist.", + "as-key": "AS-toets", + "as-key-required": "AS-sleutel is vereist.", + "client-id-new": "Client-ID", + "client-id-new-required": "Client-ID (login) is vereist (login).", + "client-secret": "Geheim van de klant", + "client-secret-required": "Client Secret (wachtwoord) is vereist (wachtwoord).", + "max-time-diff-in-seconds": "Maximaal tijdsverschil (seconden)", + "max-time-diff-in-seconds-required": "Maximaal tijdsverschil is vereist.", + "created-time": "Gecreëerde tijd", + "name": "Naam", + "name-required": "Naam is verplicht.", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "description": "Omschrijving: __________", + "base-url": "Basis-URL", + "base-url-required": "Basis-URL is vereist", + "security-key": "Beveiligingssleutel", + "http-endpoint": "URL van HTTP-eindpunt", + "replace-no-content-to-ok": "Vervang de reactiestatus van 'Geen inhoud' naar 'OK'", + "copy-http-endpoint-url": "Kopieer de URL van het HTTP-eindpunt", + "http-endpoint-url-copied-message": "De URL van het HTTP-eindpunt is gekopieerd naar het klembord", + "host": "Server host", + "host-required": "Server host is vereist.", + "host-private": "De host moet zich in het openbare netwerk bevinden.", + "url-private": "De URL moet zich in het openbare netwerk bevinden.", + "host-type": "Type host", + "host-type-required": "Hosttype is vereist.", + "api-version": "API v3 gebruiken", + "custom-host": "Aangepaste host", + "custom-host-required": "Aangepaste host is vereist.", + "port": "Poort", + "port-required": "Poort is vereist.", + "port-range": "De poort moet tussen 1 en 65535 liggen.", + "connect-timeout": "Time-out verbinding (sec)", + "connect-timeout-required": "Er is een time-out voor de verbinding vereist.", + "connect-timeout-range": "De time-out van de verbinding moet tussen 1 en 200 liggen.", + "client-id": "Client-ID", + "client-id-required": "Client-ID is vereist.", + "client-id-range": "Client-ID moet tussen de 1 en 23 tekens lang zijn. [MQTT-3.1.3-5]", + "client-id-pattern": "Client-ID moet bestaan uit cijfers, hoofdletters en kleine letters. [MQTT-3.1.3-5]", + "client-id-hint": "Tip: Optioneel. Laat dit veld leeg voor automatisch gegenereerde client-ID. Opgelet bij het opgeven van de Client ID. De meerderheid van de MQTT-brokers staat niet toe dat meerdere verbindingen met dezelfde client-ID worden gebruikt. Om verbinding te maken met dergelijke makelaars, moet uw MQTT-klant-ID uniek zijn.", + "max-bytes-in-message": "Max. aantal bytes in bericht", + "max-bytes-in-message-range": "Het maximale aantal bytes in een bericht moet tussen 1 en 256000000 liggen.", + "device-id": "Device-ID", + "device-id-required": "Device-ID is vereist.", + "device-id-range": "Device-ID moet tussen 1 en 65535 tekens bestaan.", + "device-id-pattern": "Device-ID moet bestaan uit cijfers, hoofdletters en kleine letters. [MQTT-3.1.3-5]", + "group-id": "Groeps-ID", + "group-id-required": "Groeps-ID is vereist.", + "topics": "Onderwerpen", + "topics-required": "Onderwerp is vereist.", + "routing-keys": "Routing sleutels", + "routing-keys-required": "Routingsleutel is vereist.", + "queues": "Queues", + "queues-required": "De naam van de queue is vereist.", + "durable": "Duurzaam", + "exclusive": "Exclusief", + "autoDelete": "Automatisch verwijderen", + "exchange-name": "Naam van de uitwisseling", + "exchange-name-required": "De naam van de uitwisseling is vereist.", + "downlink-topic": "Downlink-onderwerp", + "connection-timeout": "Time-out van de verbinding, ms", + "connection-timeout-min": "Ongeldige time-outwaarde voor verbinding.", + "handshake-timeout": "Time-out voor handdruk, ms", + "handshake-timeout-min": "Ongeldige time-outwaarde voor handdruk.", + "virtual-host": "Virtuele gastheer", + "rabbit-mq-poll-interval": "Polling-interval, ms", + "rabbit-mq-poll-interval-min": "Ongeldige waarde voor de polling-interval.", + "application-server-url": "URL van applicatieserver", + "application-server-url-required": "De URL van de toepassingsserver is vereist.", + "application-server-api-token": "API-token voor toepassingsserver", + "application-server-api-token-required": "API-token van toepassingsserver is vereist.", + "bootstrap-servers": "Bootstrap-servers", + "bootstrap-servers-required": "Bootstrap-servers zijn vereist.", + "poll-interval": "Poll-interval", + "poll-interval-required": "Poll-interval is vereist.", + "poll-interval-min-value": "De waarde van het pollinterval mag niet kleiner zijn dan 1", + "auto-create-topics": "Onderwerpen automatisch maken", + "clean-session": "Vernieuwde sessie", + "enable-ssl": "SSL inschakelen", + "credentials": "Inloggegevens", + "credentials-type": "Type referenties", + "credentials-type-required": "Het type referentie is vereist.", + "username": "Gebruikersnaam", + "username-required": "Gebruikersnaam is vereist.", + "password": "Wachtwoord", + "password-required": "Wachtwoord is vereist.", + "azure-ca-cert": "CA-certificaatbestand", + "ca-cert": "CA-certificaatbestand", + "private-key": "Bestand met privésleutel", + "private-key-password": "Wachtwoord voor privésleutel", + "cert": "Certificaat bestand", + "no-file": "Geen bestand geselecteerd.", + "drop-file": "Zet een bestand neer of klik om een bestand te selecteren om te uploaden.", + "drop-file-or": "Een bestand slepen en neerzetten of", + "check-connection": "Verbinding controleren", + "check-success": "Verbinding tot stand gebracht.", + "topic-filters": "Onderwerp filters", + "remove-topic-filter": "Onderwerpfilter verwijderen", + "add-topic-filter": "Onderwerpfilter toevoegen", + "add-topic-filter-prompt": "Voeg een onderwerpfilter toe", + "topic": "Onderwerp", + "mqtt-qos": "QoS", + "mqtt-qos-at-most-once": "Hoogstens één keer", + "mqtt-qos-at-least-once": "Minstens één keer", + "mqtt-qos-exactly-once": "Precies één keer", + "downlink-topic-pattern": "Patroon voor downlinkonderwerpen", + "downlink-topic-pattern-required": "Downlink-onderwerppatroon is vereist.", + "retained-message": "Behouden", + "aws-access-key-id": "AWS-toegangssleutel-ID", + "aws-secret-access-key": "Geheime AWS-toegangssleutel", + "aws-region": "Regio", + "aws-iot-endpoint": "AWS IoT-eindpunt", + "aws-iot-endpoint-required": "AWS IoT Endpoint is vereist.", + "aws-iot-credentials": "AWS IoT-referenties", + "aws-sqs-polling-period-in-seconds": "Pollingperiode in seconden", + "aws-sqs-queue-url": "URL van SQS-queue", + "aws-sqs-queue-url-required": "SQS Queue URL is vereist", + "aws-sqs-access-key-id-required": "Toegangssleutel-ID is vereist", + "aws-sqs-secret-access-key-required": "Geheime toegangssleutel is vereist", + "application-credentials": "Aanmeldingsgegevens van de toepassing", + "api-key": "API-sleutel", + "api-key-required": "API-sleutel is vereist.", + "api-key-format": "Ongeldige API-sleutelindeling.", + "auth-token": "Authenticatie token", + "auth-token-required": "Verificatietoken is vereist.", + "region": "Regio", + "region-required": "Regio is vereist.", + "application-id": "Toepassings-ID", + "application-id-required": "Toepassings-ID is vereist.", + "access-id": "Toegangs-ID", + "access-id-required": "Toegangs-ID is vereist.", + "access-key": "Toegangssleutel", + "access-key-required": "Toegangssleutel is vereist.", + "access-key-min-length": "Toegangssleutel is te kort.", + "access-key-max-length": "Toegangssleutel is te lang.", + "connection-parameters": "Verbinding parameters", + "service-bus-namespace-name": "Naam van Service Bus-namespace", + "service-bus-namespace-name-required": "Service Bus-namespace naam is vereist.", + "connection-string": "Connectionstring", + "consumer-group": "Consumentengroep", + "connection-string-required": "Aansluitreeks vereist!", + "event-hub-name": "Naam Event Hub", + "event-hub-name-required": "Event Hub-naam is vereist.", + "event-iot-hub-name-required": "Iot Hub-naam is vereist voor downlink", + "sas-key-name": "SAS-sleutelnaam", + "sas-key-name-required": "SAS-sleutelnaam is vereist.", + "sas-key": "SAS-toets", + "sas-key-required": "SAS-sleutel is vereist.", + "iot-hub-name": "IoT Hub-naam (vereist voor downlink)", + "hostname": "Hostnaam", + "hostname-required": "Hostnaam is vereist", + "integration-clazz": "Integratie klasse", + "integration-clazz-required": "Integratie klasse is vereist", + "integration-configuration": "Integratie JSON-configuratie", + "metadata": "Metagegevens", + "type": "Type integratie", + "select-integration-type": "Selecteer integratietype", + "type-required": "Integratietype is vereist.", + "type-not-found": "Integratietype niet gevonden", + "uplink-converter": "Uplink data converter", + "uplink-converter-required": "Uplink-gegevensconverter is vereist.", + "downlink-converter": "Downlink data converter", + "type-http": "HTTP (HTTP)", + "type-http-description": "Protocol voor het overbrengen van tekst- of multimediabestanden.", + "type-ocean-connect": "Oceaan verbinden", + "type-ocean-connect-description": "Integratie van devices met verschillende mogelijkheden met het IoT-platform.", + "type-sigfox": "SigFox", + "type-sigfox-description": "Lichtgewicht protocol voor het verwerken van kleine gegevensoverdrachten.", + "type-thingpark": "ThingPark", + "type-thingpark-description": "Berichtgeoriënteerd protocol voor transportlagen.", + "type-loriot": "Loriot", + "type-loriot-description": "Gedistribueerde LoRaWAN-infrastructuur.", + "type-thingpark-enterprise": "ThingParkEnterprise", + "type-thingpark-enterprise-description": "Berichtenplatform voor het LPWA-netwerk.", + "type-tmobile-iot-cdp": "iotcreators.com (T-Mobile – IoT CDP)", + "type-tmobile-iot-cdp-description": "Mobiele IoT-connectiviteitsservice.", + "type-mqtt": "MQTT", + "type-mqtt-description": "Netwerkprotocol van machine naar machine.", + "type-aws-iot": "AWS IoT", + "type-aws-iot-description": "Beheer-, opslag- en analyseservice.", + "type-aws-sqs": "AWS SQS", + "type-aws-sqs-description": "Volledig beheerde message queuing-service.", + "type-aws-kinesis": "AWS-kinesis", + "type-aws-kinesis-description": "Service voor real-time video- en datastreams.", + "type-ibm-watson-iot": "IBM Watson IoT", + "type-ibm-watson-iot-description": "Volledig beheerde, in de cloud gehoste service.", + "type-ttn": "De Things Stack-gemeenschap", + "type-ttn-description": "Open en gedecentraliseerd LoRaWAN-netwerk.", + "type-tti": "De dingen stapelen industrieën", + "type-tti-description": "Software om private LoRaWAN-netwerken op grote schaal te exploiteren.", + "type-chirpstack": "ChirpStack", + "type-chirpstack-description": "LoRaWAN-netwerkconfiguratieserver.", + "type-azure-event-hub": "Azure Event Hub", + "type-azure-event-hub-description": "Big data-streamingplatform en service voor het opnemen van events.", + "type-azure-iot-hub": "Azure IoT Hub", + "type-azure-iot-hub-description": "In de cloud gehoste berichtenservice.", + "type-opc-ua": "OPC-UA", + "type-opc-ua-description": "Cross-platform voor gegevensuitwisseling van sensoren naar cloud-apps.", + "type-custom": "Gewoonte", + "type-coap": "CoAP", + "type-coap-description": "Netwerkprotocol van machine naar machine voor beperkte Devices.", + "type-udp": "UDP", + "type-udp-description": "Berichtgeoriënteerd protocol voor transportlagen.", + "type-tcp": "TCP", + "type-tcp-description": "Verbindingsgericht protocol.", + "type-kafka": "Kafka", + "type-kafka-description": "Streaming analytics, data-integratie streaming platform.", + "type-rabbitmq": "KonijnMQ", + "type-rabbitmq-description": "Berichtenbroker die ondersteuning biedt voor meerdere berichtenprotocollen.", + "type-pubsub": "Kroeg/Sub", + "type-pubsub-description": "Service voor asynchrone berichten tussen apps.", + "type-apache-pulsar": "Apache Pulsar", + "type-apache-pulsar-description": "Gedistribueerd pub-sub berichten- en streamingplatform.", + "type-tuya": "Tuya", + "type-tuya-description": "In de cloud gehoste berichten. platform van het device.", + "type-azure-service-bus": "Azure Service Bus", + "type-azure-service-bus-description": "Volledig beheerde berichtenmakelaar voor ondernemingen met berichtwachtrijen en onderwerpen voor publiceren en abonneren.", + "opc-ua-application-name": "Naam van de toepassing", + "opc-ua-application-uri": "Applicatie uri", + "opc-ua-scan-period-in-seconds": "Scanperiode in seconden", + "opc-ua-scan-period-in-seconds-required": "Scanperiode is vereist", + "opc-ua-timeout": "Time-out in milliseconden", + "opc-ua-timeout-required": "Time-out is vereist", + "opc-ua-security": "Veiligheid", + "opc-ua-security-required": "Beveiliging is vereist", + "opc-ua-identity": "Identiteit", + "opc-ua-identity-required": "Legitimatie is vereist", + "opc-ua-keystore": "Sleutel opslag", + "add-opc-ua-keystore-prompt": "Gelieve keystore-bestand toe te voegen", + "opc-ua-keystore-required": "Keystore is vereist", + "opc-ua-type": "Type", + "opc-ua-keystore-type": "Type", + "opc-ua-keystore-type-required": "Type is vereist", + "opc-ua-keystore-location": "Plaats*", + "opc-ua-keystore-password": "Wachtwoord", + "opc-ua-keystore-password-required": "Wachtwoord is vereist", + "opc-ua-keystore-alias": "Alias", + "opc-ua-keystore-alias-required": "Alias is vereist", + "opc-ua-keystore-key-password": "Sleutel wachtwoord", + "opc-ua-keystore-key-password-required": "Sleutelwachtwoord is vereist", + "opc-ua-mapping": "Kartering", + "add-opc-ua-mapping-prompt": "Gelieve kaarten toe te voegen", + "opc-ua-mapping-type": "Type toewijzing", + "opc-ua-mapping-type-required": "Toewijzingstype is vereist", + "opc-ua-device-node-pattern": "Patroon van apparaatknooppunten", + "opc-ua-device-node-pattern-required": "Apparaatknooppuntpatroon is vereist", + "opc-ua-namespace": "Naamruimte", + "opc-ua-add-map": "Toewijzingselement toevoegen", + "kinesis-stream-name": "Naam van de stream", + "kinesis-stream-name-required": "Streamnaam is vereist", + "kinesis-region": "Regio", + "kinesis-region-required": "Regio is vereist", + "kinesis-access-key-id": "Toegangssleutel-ID", + "kinesis-access-key-id-required": "Toegangssleutel-ID is vereist", + "kinesis-secret-access-key": "Geheime toegangssleutel", + "kinesis-secret-access-key-required": "Geheime toegangssleutel is vereist", + "kinesis-use-consumers-with-enhanced-fan-out": "Gebruik consumenten met verbeterde fan-out", + "kinesis-use-credentials-from-instance-metadata": "Referenties van de Amazon EC2 Instance Metadata Service gebruiken", + "kinesis-application-name": "Toepassingsnaam (standaard gelijk aan Streamnaam)", + "kinesis-initial-position-in-stream": "Beginpositie in stream", + "kinesis-initial-position-in-stream-required": "Beginpositie in stream vereist", + "kinesis-max-records": "Max. records", + "kinesis-max-records-required": "Max. records is vereist", + "kinesis-max-records-length-range": "De maximale recordlengte moet tussen 1 en 10000 liggen", + "kinesis-request-timeout": "Time-out aanvragen in enkele seconden", + "kinesis-request-timeout-required": "Time-out voor aanvraag is vereist", + "other-properties": "Overige eigenschappen", + "subscription-tags": "Tags voor abonnementen", + "remove-subscription-tag": "Abonnementstag verwijderen", + "add-subscription-tag": "Abonnementstag toevoegen", + "add-subscription-tag-prompt": "Voeg een abonnementstag toe", + "key": "Sleutel", + "path": "Pad", + "required": "Vereist", + "integration-key": "Integratiesleutel", + "copy-integration-key": "Integratiesleutel kopiëren", + "integration-key-copied-message": "Integratiesleutel is gekopieerd naar klembord", + "integration-secret": "Integratie geheim", + "copy-integration-secret": "Integratiegeheim kopiëren", + "integration-secret-copied-message": "Integratiegeheim is gekopieerd naar klembord", + "execute-remotely": "Op afstand uitvoeren", + "remote": "Afgelegen", + "handler-configuration": "Configuratie van de handler", + "handler-configuration-type": "Handler Type", + "so-broadcast": "Uitzending inschakelen - integratie accepteert uitzendadrespakketten", + "so-keepalive-option": "Verzenden van keep-alive-berichten op verbindingsgeoriënteerde stopcontacten mogelijk maken", + "so-reuse-addr": "Bind het proces aan een poort", + "tcp-no-delay": "Dwingt een socket om de gegevens te verzenden zonder buffering (schakel het bufferalgoritme van Nagle uit)", + "fail-fast": "Gegooide uitzondering zodra de decoder merkt dat de lengte van het frame de maximale grootte zal overschrijden", + "strip-delimiter": "Scheidingsteken voor stroken", + "length-field-offset": "Lengte veld offset", + "length-field-offset-required": "Lengte veldverschuiving is vereist.", + "length-field-offset-range": "De lengteveldverschuiving moet tussen 0 en 8 liggen.", + "length-field-length": "Lengte Veldlengte", + "length-field-length-required": "Lengte Veldlengte is vereist.", + "length-field-length-range": "Lengte Veldlengte moet tussen 0 en 8 liggen.", + "length-adjustment": "Lengteaanpassing (de compensatiewaarde die moet worden toegevoegd aan de waarde van het lengteveld)", + "length-adjustment-required": "Lengteaanpassing is vereist.", + "length-adjustment-range": "De lengte-aanpassing moet tussen 0 en 8 liggen.", + "byte-order": "Byte Volgorde van het lengteveld", + "initial-bytes-to-strip": "Aantal eerste bytes dat uit het gedecodeerde frame moet worden verwijderd", + "initial-bytes-to-strip-required": "Het aantal eerste bytes dat uit het gedecodeerde frame moet worden verwijderd, is vereist.", + "initial-bytes-to-strip-range": "Het aantal eerste bytes dat uit het gedecodeerde frame moet worden verwijderd, moet tussen 0 en 8 liggen.", + "so-backlog-option": "Max. aantal in behandeling zijnde verbindingen op het stopcontact", + "so-backlog-option-required": "Het maximale aantal in behandeling zijnde verbindingen op het stopcontact is vereist.", + "so-backlog-option-range": "Het maximale aantal in behandeling zijnde verbindingen op het stopcontact moet tussen 1 en 65535 liggen.", + "so-rcv-buf": "Grootte van de buffer voor inkomende socket (in KB)", + "so-rcv-buf-required": "De grootte van de buffer voor de inkomende socket (in KB) is vereist.", + "so-rcv-buf-range": "De grootte van de buffer voor inkomende socket (in KB) moet tussen 1 en 65535 liggen.", + "so-snd-buf": "Grootte van de buffer voor uitgaande socket (in KB)", + "so-snd-buf-required": "De grootte van de buffer voor uitgaande socket (in KB) is vereist.", + "so-snd-buf-range": "De grootte van de buffer voor uitgaande socket (in KB) moet tussen 1 en 65535 liggen.", + "charset-name": "Naam van de set", + "charset-name-required": "Charset-naam is vereist.", + "message-separator": "Scheidingsteken voor berichten", + "message-separator-required": "Berichtenscheidingsteken is vereist.", + "character-sequence": "Karakter Volgorde", + "character-sequence-required": "Tekenvolgorde is vereist.", + "max-frame-length": "Maximale framelengte (in bytes)", + "max-frame-length-required": "Maximale framelengte (in bytes) is vereist.", + "max-frame-length-range": "De maximale framelengte (in bytes) moet tussen 1 en 65535 liggen.", + "handler-type": "Handler Type", + "message-size": "Grootte van het bericht", + "message-size-required": "Berichtgrootte is vereist.", + "service-url": "URL van de dienst", + "service-url-required": "Service-URL is vereist.", + "subscription-name": "Naam van het abonnement", + "subscription-name-required": "De naam van het abonnement is vereist.", + "max-num-messages": "Max. aantal berichten", + "max-num-messages-required": "Het maximale aantal berichten is vereist.", + "max-num-bytes": "Max. aantal bytes", + "max-num-bytes-required": "Maximaal aantal bytes vereist.", + "timeout-in-ms": "Time-out in milliseconden", + "timeout-in-ms-required": "Time-out in milliseconden is vereist.", + "user-id": "Gebruikersnaam", + "user-id-required": "Gebruikersnaam is vereist.", + "token": "Teken", + "token-required": "Token is vereist.", + "project-id": "Project-ID", + "project-id-required": "Project-ID is vereist.", + "subscription-id": "Abonnements-ID", + "subscription-id-required": "Abonnements-ID is vereist.", + "service-account-key": "Sleutelbestand voor serviceaccount", + "service-account-key-required": "Het sleutelbestand van het serviceaccount is vereist.", + "tcp": { + "system-line-separator": "Systeem Lijnscheider", + "nul-delimiter": "Nul-scheidingsteken", + "byte-order-little-endian": "Kleine Endian", + "byte-order-big-endian": "Grote Endian" + }, + "cache-size": "Cache-grootte", + "cache-time-to-live": "Cachetijd om in minuten te leven", + "min-cache-size": "Cachegrootte kan niet lager zijn 0", + "min-cache-time-to-live": "Cache tijd om te leven kan niet lager zijn 0", + "max-cache-time-to-live": "Ongeldige tijd van cache live, kies tussen 0 en 525600", + "coap-security-mode": "Beveiligingsmodus", + "coap-security-mode-required": "CoAP-beveiligingsmodus is vereist", + "coap-security-mode-no-secure": "NIET VEILIG", + "coap-security-mode-dtls": "DTLS", + "coap-security-mode-mixed": "GEMENGD", + "coap-endpoint": "URL van CoAP-eindpunt", + "coap-endpoint-url-copied-message": "De URL van het CoAP-eindpunt is gekopieerd naar het klembord", + "copy-coap-endpoint-url": "Kopieer de URL van het CoAP-eindpunt", + "copy-coap-dtls-endpoint-url": "Kopieer de URL van het CoAP DTLS-eindpunt", + "coap-dtls-base-url": "DTLS-basis-URL", + "coap-dtls-base-url-required": "DTLS-basis-URL is vereist", + "coap-dtls-endpoint": "URL van CoAP DTLS-eindpunt", + "coap-dtls-endpoint-url-copied-message": "De URL van het CoAP DTLS-eindpunt is gekopieerd naar het klembord", + "unassign-integration-title": "Weet je zeker dat je de toewijzing van de integratie '{{integrationName}}' ongedaan wilt maken?", + "unassign-integration-from-edge-text": "Na de bevestiging wordt de toewijzing van de integratie ongedaan gemaakt en is deze niet toegankelijk voor de edge.", + "unassign-integrations-from-edge-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 integration} andere {# integrations} } wilt opheffen?", + "unassign-integrations-from-edge-text": "Na de bevestiging worden alle geselecteerde integraties ongedaan gemaakt en zijn ze niet toegankelijk voor de edge.", + "unassign-integrations": "Toewijzing van integraties ongedaan maken", + "edge-placeholder-hint": "U kunt tijdelijke aanduiding ${{ATTRIBUTE_KEY}} gebruiken om het integratieveld te vervangen door de kenmerkwaarde van een specifieke Edge-entiteit. 'Edge A' heeft bijvoorbeeld het kenmerk 'baseUrl' dat gelijk is aan 'http://localhost:9999'. U kunt $ {{baseUrl}} instellen als een van de integratievelden, en het wordt vervangen door 'http://localhost:9999' tijdens de toewijzing van deze integratie aan 'Edge A'. Bovendien, als 'Edge A' attribuut 'baseUrl' wordt bijgewerkt, wordt de integratie met de nieuwe bijgewerkte waarde automatisch ingericht voor 'Edge A'.", + "status": { + "status": "Status", + "active": "Actief", + "disabled": "Invalide", + "failed": "Mislukt", + "pending": "In behandeling" + }, + "daily-activity": "Dagelijkse activiteit", + "enable-debug-mode": "Foutopsporingsmodus inschakelen", + "disable-debug-mode": "Schakel de foutopsporingsmodus uit", + "advanced-settings": "Geavanceerde instellingen", + "basic-settings": "Basisinstellingen", + "existing-uplink-converter": "Selecteer een bestaande uplink-gegevensconverter", + "new-uplink-converter": "Maak een nieuwe uplink-gegevensconverter", + "existing-downlink-converter": "Selecteer een bestaande downlink-gegevensconverter", + "new-downlink-converter": "Maak een nieuwe downlink-gegevensconverter", + "connection": "Verbinding", + "connected": "Verbonden", + "not-connected": "Niet verbonden", + "environment": "Milieu", + "environment-required": "Omgeving is vereist.", + "region-cn": "China", + "region-us": "Verenigde Staten", + "region-eu": "Europa", + "region-in": "India", + "topic-name": "Naam van het onderwerp", + "topic-name-required": "Onderwerpnaam is verplicht", + "sub-name": "Naam van het abonnement", + "sub-name-required": "De naam van het abonnement is vereist", + "downlink-connection-string": "Downlink-verbindingsreeks", + "downlink-connection-string-required": "Downlink-verbindingsreeks is vereist", + "downlink-topic-name": "Naam van downlink-onderwerp", + "downlink-topic-name-required": "De naam van het downlink-onderwerp is vereist" + }, + "item": { + "selected": "Geselecteerd" + }, + "js-func": { + "no-return-error": "Functie moet waarde teruggeven.", + "return-type-mismatch": "Functie moet waarde van het type '{{type}}' teruggeven.", + "tidy": "Ordelijk", + "mini": "Mini" + }, + "key-val": { + "key": "Sleutel", + "value": "Waarde", + "remove-entry": "Invoer verwijderen", + "add-entry": "Invoer toevoegen", + "no-data": "Geen inzendingen" + }, + "layout": { + "layout": "Indeling", + "manage": "Lay-outs beheren", + "settings": "Lay-out instellingen", + "color": "Kleur", + "main": "Voornaamste", + "right": "Rechts", + "left": "Links", + "select": "Doellay-out selecteren", + "percentage-width": "Percentage breedte (%)", + "fixed-width": "Vaste breedte (px)", + "left-width": "Linkerkolom (%)", + "right-width": "Rechterkolom (%)", + "pick-fixed-side": "Vaste zijde:", + "layout-fixed-width": "Vaste breedte (px)", + "value-min-error": "Waarde moet meer zijn dan {{min}}{{unit}}", + "value-max-error": "De waarde moet lager zijn dan {{max}}{{unit}}", + "layout-fixed-width-required": "Vaste breedte is vereist", + "right-width-percentage-required": "Het juiste percentage is vereist", + "left-width-percentage-required": "Linker percentage is vereist", + "divider": "Scheidingslijn", + "right-side": "Indeling rechterkant", + "left-side": "Lay-out aan de linkerkant" + }, + "legend": { + "direction": "Richting van de legende", + "position": "Legende positie", + "sort-legend": "Datakeys sorteren in legende", + "show-max": "Maximale waarde weergeven", + "show-min": "Minimale waarde weergeven", + "show-avg": "Gemiddelde waarde weergeven", + "show-total": "Totale waarde weergeven", + "show-latest": "Toon laatste waarde", + "settings": "Legende-instellingen", + "min": "Min", + "max": ".max", + "avg": "Avg", + "total": "totaal", + "latest": "laatst", + "comparison-time-ago": { + "previousInterval": "(vorig interval)", + "customInterval": "(aangepast interval)", + "days": "(dag geleden)", + "weeks": "(week geleden)", + "months": "(maand geleden)", + "years": "(jaar geleden)" + } + }, + "login": { + "login": "Inloggen", + "request-password-reset": "Verzoek om wachtwoordreset", + "reset-password": "Wachtwoord opnieuw instellen", + "create-password": "Wachtwoord maken", + "two-factor-authentication": "Twee-factor-authenticatie", + "passwords-mismatch-error": "Ingevoerde wachtwoorden moeten hetzelfde zijn.", + "password-again": "Wachtwoord opnieuw ingeven", + "sign-in": "Gelieve in te loggen", + "username": "Gebruikersnaam (e-mail)", + "remember-me": "Onthoud mij", + "forgot-password": "Wachtwoord vergeten?", + "password-reset": "Wachtwoord opnieuw instellen", + "expired-password-reset-message": "Uw inloggegevens zijn verlopen. Gelieve een nieuwe wachtwoord aan te maken.", + "new-password": "Nieuw wachtwoord", + "new-password-again": "Bevestig nieuw wachtwoord", + "password-link-sent-message": "Reset-link is verzonden", + "email": "E-mail", + "no-account": "Heb je nog geen account?", + "create-account": "Maak een account aan", + "login-with": "Log in met {{name}}", + "or": "of", + "error": "Fout bij inloggen", + "verify-your-identity": "Verifieer uw identiteit", + "select-way-to-verify": "Selecteer een manier om te verifiëren", + "resend-code": "Code opnieuw verzenden", + "resend-code-wait": "Code opnieuw verzenden in { time, plural, =1 {1 second} andere {# seconds} }", + "try-another-way": "Probeer een andere manier", + "totp-auth-description": "Voer de beveiligingscode van je authenticator-app in.", + "totp-auth-placeholder": "Code", + "sms-auth-description": "Er is een beveiligingscode naar je telefoon gestuurd om {{contact}}.", + "sms-auth-placeholder": "SMS-code", + "email-auth-description": "Er is een beveiligingscode verzonden naar uw e-mailadres op {{contact}}.", + "email-auth-placeholder": "E-mail code", + "backup-code-auth-description": "Voer een van uw back-upcodes in.", + "backup-code-auth-placeholder": "Back-up code" + }, + "signup": { + "firstname": "Voornaam", + "lastname": "Achternaam", + "email": "E-mail", + "signup": "Inschrijven", + "create-password": "Maak een wachtwoord aan", + "repeat-password": "Herhaal je wachtwoord", + "have-account": "Heb je al een account?", + "signin": "Aanmelden", + "no-captcha-message": "U moet bevestigen dat u geen robot bent", + "password-length-message": "Uw wachtwoord moet minimaal 6 tekens lang zijn", + "email-verification": "E-mail verificatie", + "email-verification-message": "Er is een e-mail met verificatiegegevens verzonden naar het opgegeven e-mailadres.
Volg de instructies in de e-mail om uw aanmeldingsprocedure te voltooien.
Let op: als je de e-mail al een tijdje niet hebt gezien, controleer dan je map 'spam' of probeer de e-mail opnieuw te verzenden door op de knop 'Opnieuw verzenden' te klikken.", + "account-activation-title": "Account activeren", + "account-activated": "Account succesvol geactiveerd!", + "account-activated-text": "Gefeliciteerd!
Uw account is geactiveerd.", + "resend": "Verzenden", + "inactive-user-exists-title": "Inactieve gebruiker bestaat al", + "inactive-user-exists-text": "Er is al een geregistreerde gebruiker met een niet-geverifieerd e-mailadres.
Klik op de knop 'Opnieuw verzenden' als u de verificatie-e-mail opnieuw wilt verzenden.", + "activating-account": "Account activeren...", + "activating-account-text": "Uw account wordt momenteel geactiveerd. Een ogenblik geduld...", + "accept-privacy-policy": "Accepteer het privacybeleid", + "accept": "Accepteren", + "privacy-policy": "Privacybeleid", + "accept-privacy-policy-message": "U moet ons privacybeleid accepteren", + "recaptcha-title": "reCAPTCHA", + "terms-of-use": "Gebruiksvoorwaarden", + "accept-terms-of-use-message": "U moet onze Gebruiksvoorwaarden accepteren" + }, + "notification": { + "action-button": "Actieknop", + "action-type": "Soort actie", + "active": "Actief", + "add-notification-recipients-group": "Groep voor ontvangers van meldingen toevoegen", + "add-notification-template": "Meldingssjabloon toevoegen", + "add-recipient": "Ontvanger toevoegen", + "add-recipients": "Geadresseerden toevoegen", + "add-rule": "Regel toevoegen", + "add-stage": "Fase toevoegen", + "add-template": "Sjabloon toevoegen", + "after": "Na", + "alarm-assignment-trigger-settings": "Triggerinstellingen voor alarmtoewijzing", + "alarm-comment-trigger-settings": "Instellingen voor triggers voor alarmreacties", + "alarm-trigger-settings": "Instellingen alarmtrigger", + "all": "Alle", + "api-feature-hint": "Als het veld leeg is, wordt de trigger toegepast op alle api-functies", + "api-usage-trigger-settings": "Instellingen voor API-gebruikstrigger", + "new-platform-version-trigger-settings": "Triggerinstellingen voor nieuwe platformversie", + "at-least-one-should-be-selected": "Er moet er ten minste één worden geselecteerd", + "basic-settings": "Basisinstellingen", + "button-text": "Tekst van de knop", + "button-text-required": "Knoptekst is vereist", + "button-text-max-length": "De tekst van de knop moet kleiner zijn dan of gelijk zijn aan {{ length }} tekens", + "compose": "Samenstellen", + "conversation": "Gesprek", + "conversation-required": "Gesprek is vereist", + "copy-notification-template": "Meldingssjabloon kopiëren", + "copy-rule": "Regel kopiëren", + "copy-template": "Kopieer sjabloon", + "create-new": "Nieuwe maken", + "created": "Geschapen", + "delete-notification-text": "Opgelet, na de bevestiging wordt de melding onherstelbaar.", + "delete-notification-title": "Weet je zeker dat je de melding wilt verwijderen?", + "delete-notifications-text": "Opgelet, na de bevestiging worden meldingen onherstelbaar.", + "delete-notifications-title": "Weet u zeker dat u { count, plural, =1 {1 notification} andere {# notifications} } wilt verwijderen?", + "delete-recipient-text": "Let op, na de bevestiging wordt de ontvanger onherstelbaar.", + "delete-recipient-title": "Weet u zeker dat u de '{{recipientName}}' van de ontvanger wilt verwijderen?", + "delete-recipients-text": "Opgelet, na de bevestiging worden ontvangers onherstelbaar.", + "delete-recipients-title": "Weet u zeker dat u { count, plural, =1 {1 recipient} andere {# recipients} } wilt verwijderen?", + "delete-request-text": "Opgelet, na het bevestigingsverzoek wordt het onherstelbaar.", + "delete-request-title": "Weet je zeker dat je een verzoek wilt verwijderen?", + "delete-requests-text": "Opgelet, na de bevestiging worden verzoeken onherstelbaar.", + "delete-requests-title": "Weet u zeker dat u { count, plural, =1 {1 request} andere {# requests} } wilt verwijderen?", + "delete-rule-text": "Opgelet, nadat de bevestigingsregel onherstelbaar wordt.", + "delete-rule-title": "Weet u zeker dat u rule '{{ruleName}}' wilt verwijderen?", + "delete-rules-text": "Opgelet, na de bevestiging worden de regels onherstelbaar.", + "delete-rules-title": "Weet u zeker dat u { count, plural, =1 {1 rule} andere {# rules} } wilt verwijderen?", + "delete-template-text": "Opgelet, nadat de bevestigingssjabloon onherstelbaar wordt.", + "delete-template-title": "Weet u zeker dat u sjabloon '{{templateName}}' wilt verwijderen?", + "delete-templates-text": "Opgelet, nadat de bevestigingssjablonen onherstelbaar zijn geworden.", + "delete-templates-title": "Weet u zeker dat u { count, plural, =1 {1 template} andere {# templates} } wilt verwijderen?", + "deleted": "Verwijderd", + "delivery-method": { + "delivery-method": "Wijze van levering", + "email": "E-mail", + "email-preview": "Voorbeeld van e-mailmelding", + "slack": "Los", + "slack-preview": "Voorbeeld van Slack-melding", + "sms": "SMS", + "sms-preview": "Voorbeeld van sms-melding", + "web": "Web", + "web-preview": "Voorbeeld van webmelding" + }, + "delivery-method-not-configure-click": "De leveringsmethode is niet geconfigureerd. Klik om in te stellen.", + "delivery-method-not-configure-contact": "De leveringsmethode is niet geconfigureerd. Neem contact op met uw systeembeheerder.", + "delivery-methods": "Levering methodes", + "description": "Omschrijving: __________", + "device-activity-trigger-settings": "Triggerinstellingen voor actieve devices", + "device-list-rule-hint": "Als het veld leeg is, wordt de trigger toegepast op alle devices", + "device-profiles-list-rule-hint": "Als het veld leeg is, wordt de trigger toegepast op alle device profielen", + "disabled": "Uitgeschakeld", + "edit-notification-recipients-group": "Groep geadresseerden van meldingen bewerken", + "edit-notification-template": "Meldingssjabloon bewerken", + "edit-rule": "Regel bewerken", + "edit-template": "Sjabloon bewerken", + "enabled": "Ingeschakeld", + "entities-limit-trigger-settings": "Entiteiten beperken triggerinstellingen", + "entity-action-trigger-settings": "Instellingen voor triggers voor entiteitsacties", + "entity-type": "Type entiteit", + "escalation-chain": "Escalatie keten", + "failed-send": "Fouten verzenden", + "fails": "{ count, plural, =1 {1 fail} andere {# fails} }", + "filter": "Filter", + "first-recipient": "Eerste ontvanger", + "inactive": "Inactief", + "inbox": "Postvak IN", + "notification-inbox": "Meldingen / Postvak IN", + "input-field-support-templatization": "Ondersteuning voor invoervelden sjabloonisatie.", + "input-fields-support-templatization": "Invoervelden ondersteunen sjabloonisatie.", + "integration-action-trigger-settings": "Activeringsinstellingen voor integratiegebeurtenissen", + "integration-list-rule-hint": "Als het veld leeg is, wordt de trigger toegepast op alle integraties", + "link": "Verbinden", + "link-required": "Link is verplicht", + "link-type": { + "dashboard": "Dashboard openen", + "link": "URL-link openen" + }, + "management": "Beheer van meldingen", + "mark-all-as-read": "Alles markeren als gelezen", + "mark-as-read": "Markeren als gelezen", + "message": "Bericht", + "message-required": "Bericht is vereist", + "message-max-length": "Het bericht moet kleiner zijn dan of gelijk zijn aan {{ length }} tekens", + "name": "Naam", + "name-required": "Naam is verplicht", + "new-notification": "Nieuwe melding", + "no-inbox-notification": "Geen melding gevonden", + "no-notification-request": "Geen meldingsverzoek", + "no-notification-templates": "Geen meldingssjablonen gevonden", + "no-notifications-yet": "Nog geen meldingen", + "no-recipients-notification": "Geen melding van ontvangers", + "no-rule": "Geen rule geconfigureerd", + "no-rules-notification": "Geen melding van regels", + "no-severity-found": "Geen ernst gevonden", + "no-severity-matching": "'{{severity}}' niet gevonden.", + "no-template-matching": "Er zijn geen '{{template}}' gevonden die overeenkomen met de bron.", + "not-found-slack-recipient": "Slack-ontvanger niet gevonden", + "notification": "Bekendmaking", + "notification-center": "Meldingscentrum", + "notify": "aankondigen", + "notify-again": "Opnieuw melden", + "notify-alarm-action": { + "acknowledged": "Alarm bevestigd", + "assigned": "Alarm toegewezen", + "cleared": "Alarm gewist", + "created": "Alarm gemaakt", + "severity-changed": "Alarmernst gewijzigd", + "unassigned": "Alarm niet toegewezen" + }, + "notify-on": "Melden op", + "notify-on-comment-update": "Bericht over commentaarupdate", + "notify-on-required": "Melden op is vereist", + "notify-on-unassign": "Melden bij toewijzing ongedaan maken", + "notify-only-integrations-errors": "Alleen melden bij fout", + "notify-only-user-comments": "Alleen opmerkingen van gebruikers op de hoogte stellen", + "only-rule-chain-lifecycle-failures": "Alleen fouten in de levenscyclus van de rule chain", + "only-rule-node-lifecycle-failures": "Alleen fouten in de levenscyclus van rule nodes", + "platform-users": "Gebruikers van het platform", + "recipient": "Ontvanger", + "recipient-group": "Groep ontvangers", + "recipient-type": { + "affected-tenant-administrators": "Betrokken tenantbeheerders", + "affected-user": "Betrokken gebruiker", + "all-users": "Alle gebruikers", + "customer-users": "Klant-gebruikers", + "system-administrators": "Systeembeheerders", + "tenant-administrators": "Tenant beheerders", + "user-filters": "Gebruiker filter", + "user-group-list": "Lijst met gebruikersgroepen", + "user-list": "Lijst met gebruikers", + "user-role": "Rol van de gebruiker", + "users-entity-owner": "Gebruikers van de entiteitseigenaar" + }, + "recipients": "Ontvangers", + "notification-recipients": "Meldingen / Ontvangers", + "recipients-count": "{ count, plural, =1 {1 recipient} andere {# recipients} }", + "recipients-required": "Ontvangers zijn verplicht", + "refresh-allow-delivery-method": "Vernieuwen Bezorgmethode toestaan", + "request-search": "Zoekopdracht aanvragen", + "request-status": { + "processing": "Verwerking", + "scheduled": "Gepland", + "sent": "Verzonden" + }, + "review": "Recensie", + "rule": "Regel", + "rule-chain-list-rule-hint": "Als het veld leeg is, wordt de trigger toegepast op alle rule chains", + "rule-engine-events-trigger-settings": "Events in de rule engine activeren instellingen", + "rule-engine-filter": "Rule engine filter", + "rule-name": "Naam van rule", + "rule-name-required": "Naam is verplicht", + "rule-node-filter": "Filter voor rule nodes", + "rules": "Reglement", + "notification-rules": "Meldingen / Regels", + "scheduler-later": "Plannen voor later", + "search-notification": "Meldingen zoeken", + "search-recipients": "Ontvangers zoeken", + "search-rules": "Zoekregels", + "search-templates": "Sjablonen zoeken", + "see-documentation": "Zie documentatie", + "selected-notifications": "{ count, plural, =1 {1 notification} andere {# notifications} } geselecteerd", + "selected-recipients": "{ count, plural, =1 {1 recipient} andere {# recipients} } geselecteerd", + "selected-requests": "{ count, plural, =1 {1 request} andere {# requests} } geselecteerd", + "selected-rules": "{ count, plural, =1 {1 rule} andere {# rules} } geselecteerd", + "selected-template": "{ count, plural, =1 {1 template} andere {# templates} } geselecteerd", + "send-notification": "Notificatie versturen", + "sent": "Verzonden", + "notification-sent": "Notificaties / Verzonden", + "set-entity-from-notification": "Entiteit instellen van melding naar dashboardstatus", + "slack-chanel-type": "Type Slack-kanaal", + "slack-chanel-types": { + "direct": "Direct bericht", + "private-channel": "Privé-kanaal", + "public-channel": "Publieke zender" + }, + "start-from-scratch": "Begin vanaf nul", + "status": "Status", + "stop-escalation-alarm-status-become": "Stop de escalatie van de alarmstatus wordt:", + "subject": "Onderwerp", + "subject-required": "Onderwerp is verplicht", + "template": "Sjabloon", + "template-name": "Naam van sjabloon", + "template-required": "Sjabloon is vereist", + "template-type": { + "alarm": "Alarm", + "alarm-assignment": "Alarm toewijzing", + "alarm-comment": "Alarm commentaar", + "api-usage-limit": "Limiet voor API-gebruik", + "device-activity": "Activiteit van het device", + "entities-limit": "Limieten voor entiteiten", + "entity-action": "Actie van entiteit", + "general": "Algemeen", + "integration-lifecycle-event": "Levens cyclus event van integratie", + "rule-engine-lifecycle-event": "Levens cyclus event van rule engine", + "rule-node": "Regel knooppunt", + "new-platform-version": "Nieuwe platformversie" + }, + "templates": "Sjablonen", + "notification-templates": "Meldingen / Sjablonen", + "tenant-profiles-list-rule-hint": "Als het veld leeg is, wordt de trigger toegepast op alle tenantprofielen", + "tenants-list-rule-hint": "Als het veld leeg is, wordt de trigger toegepast op alle tenants", + "threshold": "Drempel", + "time": "Tijd", + "track-rule-node-events": "Regelknooppuntgebeurtenissen bijhouden", + "trigger": { + "alarm": "Alarm", + "alarm-assignment": "Alarm toewijzing", + "alarm-comment": "Alarm commentaar", + "api-usage-limit": "Limiet voor API-gebruik", + "device-activity": "Activiteit van het device", + "entities-limit": "Limieten voor entiteiten", + "entity-action": "Actie van entiteit", + "integration-lifecycle-event": "Levens cyclus event van integratie", + "rule-engine-lifecycle-event": "Levens cyclus event van rule engine", + "new-platform-version": "Nieuwe platformversie", + "trigger": "Trigger", + "trigger-required": "Trigger is vereist" + }, + "type": "Type", + "unread": "Ongelezen", + "updated": "Bijgewerkt", + "use-template": "Sjabloon gebruiken", + "view-all": "Alles weergeven", + "view-notification-recipients-group": "Groep geadresseerden van meldingen weergeven", + "view-notification-template": "Meldingssjabloon weergeven", + "view-rule": "Bekijk rule", + "warning": "Waarschuwing" + }, + "ota-update": { + "add": "Pakket toevoegen", + "assign-firmware": "Toegewezen firmware", + "assign-firmware-required": "Toegewezen firmware is vereist", + "assign-software": "Toegewezen software", + "assign-software-required": "Toegewezen software is vereist", + "auto-generate-checksum": "Automatisch controlesom genereren", + "cant-applied-group-all": "Kan niet worden aangevraagd voor groep Alle", + "checksum": "Checksum", + "checksum-hint": "Als de checksum leeg is, wordt deze automatisch gegenereerd", + "checksum-algorithm": "Checksum-algoritme", + "checksum-copied-message": "De controlesom van het pakket is gekopieerd naar het klembord", + "change-firmware": "Wijziging van de firmware kan leiden tot een update van { count, plural, =1 {1 device} andere {# devices} }.", + "change-software": "Wijziging van de software kan leiden tot een update van { count, plural, =1 {1 device} andere {# devices} }.", + "chose-compatible-device-profile": "Het geüploade pakket is alleen beschikbaar voor devices met het gekozen profiel.", + "chose-firmware-distributed-device": "Kies firmware die naar de devices wordt gedistribueerd", + "chose-software-distributed-device": "Kies software die naar de devices wordt gedistribueerd", + "content-type": "Inhoudstype", + "copy-checksum": "Controlesom kopiëren", + "copy-direct-url": "Directe URL kopiëren", + "copyId": "Kopieer pakket-ID", + "copied": "Gekopieerd!", + "delete": "Pakket verwijderen", + "delete-ota-update-text": "Opgelet, na de bevestiging wordt de OTA-update onherstelbaar.", + "delete-ota-update-title": "Weet je zeker dat je de OTA-update '{{title}}' wilt verwijderen?", + "delete-ota-updates-text": "Opgelet, na de bevestiging worden alle geselecteerde OTA-updates verwijderd.", + "delete-ota-updates-title": "Weet u zeker dat u { count, plural, =1 {1 OTA update} andere {# OTA updates} } wilt verwijderen?", + "description": "Omschrijving: __________", + "direct-url": "Directe URL", + "direct-url-copied-message": "De directe URL van het pakket is gekopieerd naar het klembord", + "direct-url-required": "Directe URL is vereist", + "download": "Pakket downloaden", + "drop-file": "Zet een pakketbestand neer of klik om een bestand te selecteren om te uploaden.", + "drop-package-file-or": "Sleep een pakketbestand of", + "file-name": "Bestandsnaam", + "file-size": "Bestandsgrootte", + "file-size-bytes": "Bestandsgrootte in bytes", + "idCopiedMessage": "Pakket-ID is gekopieerd naar klembord", + "no-firmware-matching": "Er zijn geen compatibele OTA-updatepakketten gevonden die overeenkomen met '{{entity}}'.", + "no-firmware-text": "Er zijn geen compatibele OTA-updatepakketten voor firmware ingericht.", + "no-packages-text": "Geen pakketten gevonden", + "no-software-matching": "Er zijn geen compatibele Software OTA Update-pakketten gevonden die overeenkomen met '{{entity}}'.", + "no-software-text": "Er zijn geen compatibele OTA-updatepakketten voor software geleverd.", + "ota-update": "OTA-update", + "ota-update-details": "Details van OTA-update", + "ota-updates": "OTA-updates", + "package-type": "Soort verpakking", + "packages-repository": "Pakketten repository", + "search": "Pakketten zoeken", + "selected-package": "{ count, plural, =1 {1 package} andere {# packages} } geselecteerd", + "title": "Titel", + "title-required": "Titel is vereist.", + "title-max-length": "Titel moet kleiner zijn dan 256 tekens", + "types": { + "firmware": "Firmware", + "software": "Software" + }, + "upload-binary-file": "Binair bestand uploaden", + "use-external-url": "Externe URL gebruiken", + "version": "Versie", + "version-required": "Versie is vereist.", + "version-tag": "Versie Tag", + "version-tag-hint": "De aangepaste tag moet overeenkomen met de pakketversie die door uw device wordt gerapporteerd.", + "version-max-length": "Versie moet kleiner zijn dan 256 tekens", + "warning-after-save-no-edit": "Zodra het pakket is geüpload, kunt u de titel, versie, device profiel en pakkettype niet meer wijzigen." + }, + "position": { + "top": "Boven", + "bottom": "Bodem", + "left": "Links", + "right": "Rechts" + }, + "profile": { + "profile": "Profiel", + "last-login-time": "Laatste keer inloggen", + "change-password": "Wachtwoord wijzigen", + "current-password": "Huidig wachtwoord", + "copy-jwt-token": "JWT-token kopiëren", + "jwt-token": "JWT-token", + "token-valid-till": "Token is geldig tot", + "tokenCopiedSuccessMessage": "JWT-token is gekopieerd naar klembord", + "tokenCopiedWarnMessage": "JWT-token is verlopen! Vernieuw de pagina." + }, + "profiles": { + "profiles": "Profielen" + }, + "security": { + "security": "Veiligheid", + "general-settings": "Algemene beveiligingsinstellingen", + "2fa": { + "2fa": "Twee-factor-authenticatie", + "2fa-description": "Tweefactorauthenticatie beschermt uw account tegen ongeoorloofde toegang. Het enige wat je hoeft te doen is een beveiligingscode in te voeren wanneer je inlogt.", + "authenticate-with": "U kunt zich authenticeren met:", + "disable-2fa-provider-text": "Als u {{name}} uitschakelt, wordt uw account minder veilig", + "disable-2fa-provider-title": "Weet u zeker dat u {{name}} wilt uitschakelen?", + "get-new-code": "Nieuwe code ophalen", + "main-2fa-method": "Gebruik als belangrijkste tweefactorauthenticatiemethode", + "dialog": { + "activation-step-description-email": "De volgende keer dat u inlogt, wordt u gevraagd de beveiligingscode in te voeren die naar uw e-mailadres wordt verzonden.", + "activation-step-description-sms": "De volgende keer dat u inlogt, wordt u gevraagd de beveiligingscode in te voeren die naar het telefoonnummer wordt verzonden.", + "activation-step-description-totp": "De volgende keer dat u inlogt, moet u een tweefactorauthenticatiecode opgeven.", + "activation-step-label": "Activering", + "backup-code-description": "Print de codes uit, zodat je ze bij de hand hebt wanneer je ze moet gebruiken om in te loggen op je account. U kunt elke back-upcode één keer gebruiken.", + "backup-code-warn": "Zodra u deze pagina verlaat, kunnen deze codes niet meer worden weergegeven. Bewaar ze veilig met behulp van de onderstaande opties.", + "download-txt": "Downloaden (txt)", + "email-step-description": "Voer een e-mailadres in dat u als authenticator wilt gebruiken.", + "email-step-label": "E-mail", + "enable-email-title": "E-mailauthenticator inschakelen", + "enable-sms-title": "SMS-authenticator inschakelen", + "enable-totp-title": "Authenticator-app inschakelen", + "enter-verification-code": "Vul hier de 6-cijferige code in", + "get-backup-code-title": "Back-upcode ophalen", + "next": "Volgend", + "scan-qr-code": "Scan deze QR-code met je verificatie-app", + "send-code": "Verstuur code", + "sms-step-description": "Voer een telefoonnummer in dat u als authenticator wilt gebruiken.", + "sms-step-label": "Telefoonnummer", + "success": "Succes!", + "totp-step-description-install": "U kunt apps zoals Google Authenticator, Authy of Duo installeren.", + "totp-step-description-open": "Open de authenticator-app op je mobiele telefoon.", + "totp-step-label": "Download de app", + "verification-code": "6-cijferige code", + "verification-code-invalid": "Ongeldige indeling van de verificatiecode", + "verification-code-incorrect": "Verificatiecode is onjuist", + "verification-code-many-request": "Te veel verzoeken om verificatiecode te controleren", + "verification-step-description": "Voer een 6-cijferige code in die we zojuist naar {{address}} hebben gestuurd", + "verification-step-label": "Verificatie" + }, + "provider": { + "email": "E-mail", + "email-description": "Gebruik een beveiligingscode die naar uw e-mailadres is verzonden om u te verifiëren.", + "email-hint": "Authenticatiecodes worden per e-mail verzonden naar {{ info }}", + "sms": "SMS", + "sms-description": "Gebruik je telefoon om je te authenticeren. We sturen je een beveiligingscode via sms wanneer je inlogt.", + "sms-hint": "Authenticatiecodes worden per sms verzonden naar {{ info }}", + "totp": "Authenticator-app", + "totp-description": "Gebruik apps zoals Google Authenticator, Authy of Duo op je telefoon om te verifiëren. Het genereert een beveiligingscode om in te loggen.", + "totp-hint": "De Authenticator-app is ingesteld voor uw account", + "backup_code": "Back-up code", + "backup-code-description": "Met deze afdrukbare eenmalige toegangscodes kunt u zich aanmelden wanneer u uw telefoon niet bij de hand hebt, bijvoorbeeld wanneer u op reis bent.", + "backup-code-hint": "{{ info }} codes voor eenmalig gebruik zijn op dit moment actief" + } + }, + "password-requirement": { + "at-least": "Minstens:", + "character": "{ count, plural, =1 {1 character} andere {# characters} }", + "digit": "{ count, plural, =1 {1 digit} andere {# digits} }", + "incorrect-password-try-again": "Onjuist wachtwoord. Probeer het opnieuw", + "lowercase-letter": "{ count, plural, =1 {1 lowercase letter} andere {# lowercase letters} }", + "new-passwords-not-match": "Nieuw wachtwoord komt niet overeen", + "password-should-not-contain-spaces": "Uw wachtwoord mag geen spaties bevatten", + "password-not-meet-requirements": "Wachtwoord voldeed niet aan de vereisten", + "password-requirements": "Vereisten voor wachtwoorden", + "password-should-difference": "Het nieuwe wachtwoord moet anders zijn dan het huidige", + "special-character": "{ count, plural, =1 {1 special character} andere {# special characters} }", + "uppercase-letter": "{ count, plural, =1 {1 uppercase letter} andere {# uppercase letters} }" + } + }, + "relation": { + "relations": "Betrekkingen", + "direction": "Richting", + "search-direction": { + "FROM": "Van", + "TO": "Aan" + }, + "direction-type": { + "FROM": "Van", + "TO": "Aan" + }, + "from-relations": "Uitgaande relaties", + "to-relations": "Inkomende relaties", + "selected-relations": "{ count, plural, =1 {1 relation} andere {# relations} } geselecteerd", + "type": "Type", + "to-entity-type": "Naar entiteitstype", + "to-entity-name": "Naar entiteitsnaam", + "from-entity-type": "Van entiteitstype", + "from-entity-name": "Van entiteitsnaam", + "to-entity": "Naar entiteit", + "from-entity": "Van entiteit", + "delete": "Relatie verwijderen", + "relation-type": "Relatie type", + "relation-type-required": "Relatietype is vereist.", + "relation-type-max-length": "Relatietype moet kleiner zijn dan 256 tekens", + "any-relation-type": "Elk type", + "add": "Relatie toevoegen", + "edit": "Relatie bewerken", + "view": "Bekijk relatie", + "delete-to-relation-title": "Weet u zeker dat u de relatie met de entiteit '{{entityName}}' wilt verwijderen?", + "delete-to-relation-text": "Let op, na de bevestiging is de entiteit '{{entityName}}' niet meer gerelateerd aan de huidige entiteit.", + "delete-to-relations-title": "Weet u zeker dat u { count, plural, =1 {1 relation} andere {# relations} } wilt verwijderen?", + "delete-to-relations-text": "Opgelet, na de bevestiging worden alle geselecteerde relaties verwijderd en worden de bijbehorende entiteiten losgekoppeld van de huidige entiteit.", + "delete-from-relation-title": "Weet u zeker dat u de relatie uit de entiteit '{{entityName}}' wilt verwijderen?", + "delete-from-relation-text": "Opgelet, na de bevestiging zal de huidige entiteit niet meer gerelateerd zijn aan de entiteit '{{entityName}}'.", + "delete-from-relations-title": "Weet u zeker dat u { count, plural, =1 {1 relation} andere {# relations} } wilt verwijderen?", + "delete-from-relations-text": "Opgelet, na de bevestiging worden alle geselecteerde relaties verwijderd en wordt de huidige entiteit losgekoppeld van de corresponderende entiteiten.", + "remove-relation-filter": "Relatiefilter verwijderen", + "add-relation-filter": "Relatiefilter toevoegen", + "any-relation": "Elke relatie", + "relation-filters": "Relatie filters", + "additional-info": "Aanvullende informatie (JSON)", + "invalid-additional-info": "Kan aanvullende informatie json niet parseren.", + "no-relations-text": "Geen relaties gevonden" + }, + "resource": { + "add": "Bron toevoegen", + "copyId": "Resource-ID kopiëren", + "delete": "Bron verwijderen", + "delete-resource-text": "Opgelet, na de bevestiging wordt de bron onherstelbaar.", + "delete-resource-title": "Weet u zeker dat u de bron '{{resourceTitle}}' wilt verwijderen?", + "delete-resources-action-title": "Verwijder { count, plural, =1 {1 resource} andere {# resources} }", + "delete-resources-text": "Houd er rekening mee dat de geselecteerde bronnen, zelfs als ze in device profielen worden gebruikt, worden verwijderd.", + "delete-resources-title": "Weet u zeker dat u { count, plural, =1 {1 resource} andere {# resources} } wilt verwijderen?", + "download": "Bron downloaden", + "drop-file": "Zet een bronbestand neer of klik om een bestand te selecteren om te uploaden.", + "drop-resource-file-or": "Sleep een bronbestand of", + "empty": "Bron is leeg", + "file-name": "Bestandsnaam", + "idCopiedMessage": "Bron-id is gekopieerd naar klembord", + "no-resource-matching": "Er zijn geen '{{widgetsBundle}}' gevonden die overeenkomen met de bron.", + "no-resource-text": "Geen bronnen gevonden", + "open-widgets-bundle": "Widgets-bundel openen", + "resource": "Hulpbron", + "resource-library-details": "Details van de bron", + "resource-type": "Type bron", + "resources-library": "Bibliotheek met bronnen", + "search": "Bronnen zoeken", + "selected-resources": "{ count, plural, =1 {1 resource} andere {# resources} } geselecteerd", + "system": "Systeem", + "title": "Titel", + "title-required": "Titel is vereist.", + "title-max-length": "Titel moet kleiner zijn dan 256 tekens" + }, + "rulechain": { + "rulechain": "Rule chains", + "rulechain-events": "Events in de rule chain", + "rulechains": "Rule chains", + "root": "Bron", + "delete": "Rule chain verwijderen", + "name": "Naam", + "name-required": "Naam is verplicht.", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "description": "Omschrijving: __________", + "add": "Rule chain toevoegen", + "set-root": "Bron rule chain aanmaken", + "set-root-rulechain-title": "Weet u zeker dat u de rule chain '{{ruleChainName}}' als bron wilt maken?", + "set-root-rulechain-text": "Na de bevestiging wordt de rule chain de bron en worden alle inkomende transportberichten afgehandeld.", + "delete-rulechain-title": "Weet u zeker dat u de rule chain '{{ruleChainName}}' wilt verwijderen?", + "delete-rulechain-text": "Opgelet, na de bevestiging worden de rule chain en alle gerelateerde gegevens onherstelbaar.", + "delete-rulechains-title": "Weet u zeker dat u { count, plural, =1 {1 rule chain} andere {# rule chains} } wilt verwijderen?", + "delete-rulechains-action-title": "Verwijder { count, plural, =1 {1 rule chain} andere {# rule chains} }", + "delete-rulechains-text": "Opgelet, na de bevestiging worden alle geselecteerde rule chains verwijderd en worden alle gerelateerde gegevens onherstelbaar.", + "add-rulechain-text": "Nieuwe rule chain toevoegen", + "no-rulechains-text": "Geen rule chains gevonden", + "rulechain-details": "Details van de rule chain", + "details": "Details", + "events": "Events", + "system": "Systeem", + "import": "Rule chain importeren", + "export": "Rule chain exporteren", + "export-failed-error": "Rule chain kan niet worden geëxporteerd: {{error}}", + "create-new-rulechain": "Nieuwe rule chain maken", + "rulechain-file": "Rule chain bestand", + "invalid-rulechain-file-error": "Rule chain kan niet worden geïmporteerd: Ongeldige gegevensstructuur van de rule chain.", + "copyId": "Rule chain-id kopiëren", + "idCopiedMessage": "Rule chain-id is gekopieerd naar klembord", + "select-rulechain": "Rule chain selecteren", + "no-rulechains-matching": "Er zijn geen rule chains gevonden die overeenkomen met '{{entity}}'.", + "rulechain-required": "Rule chain is vereist", + "management": "Beheer van rule chains", + "debug-mode": "Foutopsporingsmodus", + "search": "Rule chains zoeken", + "selected-rulechains": "{ count, plural, =1 {1 rule chain} andere {# rule chains} } geselecteerd", + "open-rulechain": "Rule chain openen", + "edge-template-root": "Sjabloon Wortel", + "assign-to-edge": "Toewijzen aan Edge", + "edge-rulechain": "Edge rule chain", + "unassign-rulechain-from-edge-text": "Na de bevestiging wordt de toewijzing van de rule chain ongedaan gemaakt en is deze niet toegankelijk voor de edge.", + "unassign-rulechains-from-edge-title": "Weet u zeker dat u de toewijzing van { count, plural, =1 {1 rulechain} andere {# rulechains} } wilt opheffen?", + "unassign-rulechains-from-edge-text": "Na de bevestiging worden alle geselecteerde rule chains ongedaan gemaakt en zijn ze niet toegankelijk via de edge.", + "assign-rulechain-to-edge-title": "Regel Chain(s) toewijzen aan Edge", + "assign-rulechain-to-edge-text": "Selecteer de rule chains die u aan de edge wilt toewijzen", + "set-edge-template-root-rulechain": "Rule chain maken als hoofdmap van de randsjabloon", + "set-edge-tscheduler-eventemplate-root-rulechain": "Rule chain maken als hoofdmap van de randsjabloon", + "set-edge-template-root-rulechain-title": "Weet u zeker dat u de rule chain '{{ruleChainName}}' randsjabloon root wilt maken?", + "set-edge-template-root-rulechain-text": "Na de bevestiging wordt de rule chain de hoofdstructuur van de randsjabloon en wordt deze de hoofdregelketen voor een nieuw aangemaakte edges.", + "invalid-rulechain-type-error": "Kan rule chain niet importeren: Ongeldig type rule chain. Verwacht type is {{expectedRuleChainType}}.", + "set-auto-assign-to-edge": "Rule chain toewijzen aan edge(en) bij het maken", + "set-auto-assign-to-edge-title": "Weet u zeker dat u de rule chain '{{ruleChainName}}' wilt toewijzen aan edge(en) bij het maken?", + "set-auto-assign-to-edge-text": "Na de bevestiging wordt de rule chain automatisch toegewezen aan edge(en) bij het aanmaken.", + "unset-auto-assign-to-edge": "Wijs geen rule chain toe aan edge(en) bij het maken", + "unset-auto-assign-to-edge-title": "Weet u zeker dat u de rule chain '{{ruleChainName}}' niet wilt toewijzen aan edge(en) bij het maken?", + "unset-auto-assign-to-edge-text": "Na de bevestiging wordt de rule chain niet langer automatisch toegewezen aan edge(en) bij het aanmaken.", + "unassign-rulechain-title": "Weet u zeker dat u de toewijzing van de rule chain '{{ruleChainName}}' wilt opheffen?", + "unassign-rulechains": "Toewijzing van rule chains ongedaan maken" + }, + "rulenode": { + "rule-node-events": "Events met rule nodes", + "details": "Details", + "events": "Events", + "search": "Rule nodes zoeken", + "open-node-library": "Knooppuntbibliotheek openen", + "add": "Rule node toevoegen", + "name": "Naam", + "name-required": "Naam is verplicht.", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "type": "Type", + "description": "Omschrijving: __________", + "delete": "Rule node verwijderen", + "select-all-objects": "Selecteer alle rule nodes en verbindingen", + "deselect-all-objects": "Deselecteer alle rule nodes en verbindingen", + "delete-selected-objects": "Geselecteerde rule nodes en verbindingen verwijderen", + "delete-selected": "Selectie verwijderen", + "create-nested-rulechain": "Geneste rule chain maken", + "select-all": "Alles selecteren", + "copy-selected": "Geselecteerde tekst kopiëren", + "deselect-all": "Alles deselecteren", + "rulenode-details": "Details van rule nodes", + "debug-mode": "Foutopsporingsmodus", + "singleton-mode": "Singleton-modus", + "configuration": "Configuratie", + "link": "Verbinden", + "link-details": "Details van rule nodes links", + "add-link": "Link toevoegen", + "link-label": "Label koppelen", + "link-label-required": "Linklabel is vereist.", + "custom-link-label": "Aangepast linklabel", + "custom-link-label-required": "Aangepast linklabel is vereist.", + "link-labels": "Labels koppelen", + "link-labels-required": "Labels koppelen is vereist.", + "no-link-labels-found": "Geen linklabels gevonden", + "no-link-label-matching": "'{{label}}' niet gevonden.", + "create-new-link-label": "Maak een nieuwe aan!", + "type-filter": "Filter", + "type-filter-details": "Inkomende berichten filteren met geconfigureerde voorwaarden", + "type-enrichment": "Verrijking", + "type-enrichment-details": "Aanvullende informatie toevoegen aan de metagegevens van berichten", + "type-transformation": "Transformatie", + "type-transformation-details": "De payload en metagegevens van berichten wijzigen", + "type-action": "Actie", + "type-action-details": "Speciale actie uitvoeren", + "type-analytics": "Analytics", + "type-analytics-details": "Analyse uitvoeren van gestreamde of persistente gegevens", + "type-external": "Extern", + "type-external-details": "Werkt samen met extern systeem", + "type-rule-chain": "Rule chain", + "type-rule-chain-details": "Inkomende berichten worden doorgestuurd naar een opgegeven rule chain", + "type-flow": "Vloeien", + "type-flow-details": "Organiseert de berichtenstroom", + "type-input": "Invoer", + "type-input-details": "Logische invoer van rule chain, stuurt inkomende berichten door naar het volgende gerelateerde rule node", + "type-unknown": "Onbekend", + "type-unknown-details": "Onopgelost rule node", + "directive-is-not-loaded": "Gedefinieerde configuratierichtlijn '{{directiveName}}' is niet beschikbaar.", + "ui-resources-load-error": "Het laden van de bronnen van de configuratie-gebruikersinterface is mislukt.", + "invalid-target-rulechain": "Kan doelregelketen niet oplossen!", + "test-script-function": "Test script functie", + "script-lang-java-script": "Java-schrift", + "script-lang-tbel": "TBEL", + "message": "Bericht", + "message-type": "Soort bericht", + "select-message-type": "Selecteer berichttype", + "message-type-required": "Berichttype is vereist", + "metadata": "Metagegevens", + "metadata-required": "Metagegevensvermeldingen mogen niet leeg zijn.", + "output": "Uitvoer", + "test": "Test", + "help": "Help", + "reset-debug-mode": "Foutopsporingsmodus resetten in alle rule nodes" + }, + "role": { + "role": "Rol", + "roles": "Rollen", + "management": "Rollen beheer", + "view-roles": "Rollen weergeven", + "no-roles-matching": "Er zijn geen rollen gevonden die overeenkomen met '{{entity}}'.", + "role-list": "Lijst met rollen", + "role-list-required": "Rollenlijst is verplicht", + "add": "Rol toevoegen", + "view": "Bekijk rol", + "search": "Rollen zoeken", + "selected-roles": "{ count, plural, =1 {1 role} andere {# roles} } geselecteerd", + "no-roles-text": "Geen rollen gevonden", + "role-details": "Details van de rol", + "add-role-text": "Nieuwe rol toevoegen", + "delete": "Rol verwijderen", + "delete-roles": "Rollen verwijderen", + "delete-role-title": "Weet je zeker dat je de rol '{{roleName}}' wilt verwijderen?", + "delete-role-text": "Opgelet, na de bevestiging worden de rol en alle gerelateerde gegevens onherstelbaar.", + "delete-roles-title": "Weet u zeker dat u { count, plural, =1 {1 role} andere {# roles} } wilt verwijderen?", + "delete-roles-action-title": "Verwijder { count, plural, =1 {1 role} andere {# roles} }", + "delete-roles-text": "Opgelet, na de bevestiging worden alle geselecteerde rollen verwijderd en worden alle gerelateerde gegevens onherstelbaar.", + "role-type": "Soort rol", + "role-type-required": "Roltype is vereist.", + "select-role-type": "Roltype selecteren", + "enter-role-type": "Roltype invoeren", + "any-role": "Elke rol", + "no-role-types-matching": "Er zijn geen roltypen gevonden die overeenkomen met '{{entitySubtype}}'.", + "role-type-list-empty": "Geen roltypen geselecteerd.", + "role-types": "Soorten rollen", + "created-time": "Gecreëerde tijd", + "name": "Naam", + "name-required": "Naam is verplicht.", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "description": "Omschrijving: __________", + "events": "Events", + "details": "Details", + "copyId": "Rol-ID kopiëren", + "idCopiedMessage": "Rol-ID is gekopieerd naar het klembord", + "permissions": "Machtigingen", + "role-required": "Vereiste rol", + "roles-required": "Vereiste rollen", + "display-type": { + "GENERIC": "Generiek", + "GROUP": "Groep" + } + }, + "group-permission": { + "user-group-roles": "Rollen voor gebruikersgroepen", + "entity-group-permissions": "Machtigingen voor entiteitsgroepen", + "role-type": "Soort rol", + "role-name": "Naam van de rol", + "group-type": "Soort groep", + "group-name": "Naam van de groep", + "group-owner": "Eigenaar van de groep", + "user-group-name": "Naam van de gebruikersgroep", + "user-group-owner": "Eigenaar van gebruikersgroep", + "edit": "Machtigingen bewerken", + "delete": "Machtigingen verwijderen", + "selected-group-permissions": "{ count, plural, =1 {1 group permission} andere {# group permissions} } geselecteerd", + "delete-group-permission-title": "Weet je zeker dat je de groepsrechten '{{roleName}}' wilt verwijderen?", + "delete-group-permission-text": "Opgelet, na de bevestiging worden de groepstoestemming en alle gerelateerde gegevens onherstelbaar.", + "delete-group-permission": "Groepsmachtiging verwijderen", + "delete-group-permissions-title": "Weet u zeker dat u { count, plural, =1 {1 group permission} andere {# group permission} } wilt verwijderen?", + "delete-group-permissions-text": "Opgelet, na de bevestiging worden alle geselecteerde groepsmachtigingen verwijderd en verliezen de bijbehorende gebruikers de toegang tot gespecificeerde bronnen.", + "delete-group-permissions": "Groepsmachtigingen verwijderen", + "add-group-permission": "Groepsmachtiging toevoegen", + "edit-group-permission": "Groepsmachtiging bewerken", + "entity-group": "Entiteitsgroep", + "user-group": "Gebruikersgroep", + "no-owners-matching": "Er zijn geen eigenaren gevonden die overeenkomen met '{{owner}}'.", + "target-owner-required": "Eigenaar van entiteitsgroep is vereist.", + "target-user-group-owner-required": "Eigenaar van gebruikersgroep is vereist.", + "no-group-permissions-text": "Geen groepsmachtigingen gevonden" + }, + "permission": { + "permissions-required": "Er moet ten minste één machtigingsvermelding worden opgegeven.", + "remove-permission": "Machtigingsinvoer verwijderen", + "add-permission": "Machtigingsinvoer toevoegen", + "other": "Anders __________", + "resource": { + "resource": "Hulpbron", + "select-resource": "Bron selecteren", + "resource-required": "Resource is vereist", + "no-resources-matching": "Er zijn geen bronnen gevonden die overeenkomen met '{{resource}}'.", + "display-type": { + "ALL": "Alle", + "PROFILE": "Profiel", + "ADMIN_SETTINGS": "Admin-instellingen", + "ALARM": "Alarm", + "DEVICE": "Device", + "DEVICE_PROFILE": "Device profiel", + "ASSET": "Asset", + "CUSTOMER": "Klant", + "DASHBOARD": "Dashboard", + "ENTITY_VIEW": "Entiteit Weergave", + "EDGE": "Edge", + "TENANT": "Tenant", + "TENANT_PROFILE": "Profiel van de tenant", + "RULE_CHAIN": "Rule chain", + "USER": "Gebruiker", + "WIDGETS_BUNDLE": "Widgets Bundel", + "WIDGET_TYPE": "Widget Type", + "CONVERTER": "Conversieprogramma", + "INTEGRATION": "Integratie", + "SCHEDULER_EVENT": "Scheduler Evenement", + "BLOB_ENTITY": "Blob-entiteit", + "CUSTOMER_GROUP": "Klantengroep", + "DEVICE_GROUP": "Device Groep", + "ASSET_GROUP": "Activagroep", + "USER_GROUP": "Gebruikersgroep", + "ENTITY_VIEW_GROUP": "Groep Entiteitsweergave", + "DASHBOARD_GROUP": "Dashboard Groep", + "ROLE": "Rol", + "GROUP_PERMISSION": "Toestemming voor groepen", + "WHITE_LABELING": "White labelling", + "AUDIT_LOG": "Controle logboek", + "API_USAGE_STATE": "Status API-gebruik", + "TB_RESOURCE": "Hulpbron", + "EDGE_GROUP": "Edge-groep", + "OTA_PACKAGE": "Ota-pakket", + "QUEUE": "Rij", + "VERSION_CONTROL": "Versiebeheer", + "ASSET_PROFILE": "Asset Profiel", + "NOTIFICATION": "Bekendmaking" + } + }, + "operation": { + "operation": "Operatie", + "operations": "Operaties", + "operations-required": "Er moet ten minste één bewerking worden opgegeven.", + "enter-operation": "Operatie invoeren", + "no-operations-matching": "Er zijn geen bewerkingen gevonden die overeenkomen met '{{operation}}'.", + "display-type": { + "ALL": "Alle", + "CREATE": "Nieuw", + "READ": "Lezen", + "WRITE": "Schrijven", + "DELETE": "Verwijderen", + "ASSIGN_TO_CUSTOMER": "Toewijzen aan klant", + "UNASSIGN_FROM_CUSTOMER": "Toewijzing van klant ongedaan maken", + "RPC_CALL": "RPC-oproep", + "READ_CREDENTIALS": "Inloggegevens lezen", + "WRITE_CREDENTIALS": "Referenties schrijven", + "READ_ATTRIBUTES": "Attributen lezen", + "WRITE_ATTRIBUTES": "Attributen schrijven", + "READ_TELEMETRY": "Telemetrie lezen", + "WRITE_TELEMETRY": "Telemetrie schrijven", + "CLAIM_DEVICES": "Devices claimen", + "IMPERSONATE": "Imiteren", + "CHANGE_OWNER": "Eigenaar wijzigen", + "ADD_TO_GROUP": "Voeg toe aan groep", + "REMOVE_FROM_GROUP": "Verwijderen uit groep", + "SHARE_GROUP": "Groep delen", + "ASSIGN_TO_TENANT": "Toewijzen aan tenant" + } + } + }, + "scheduler": { + "scheduler": "Scheduler", + "scheduler-event": "Scheduler-event", + "select-scheduler-event": "Scheduler event selecteren", + "no-scheduler-events-matching": "Er zijn geen scheduler events gevonden die overeenkomen met '{{entity}}'.", + "scheduler-event-required": "Scheduler-event is vereist", + "management": "Beheer van de planning", + "scheduler-events": "Scheduler-events", + "add-scheduler-event": "Scheduler-event toevoegen", + "search-scheduler-events": "Scheduler-events zoeken", + "created-time": "Gecreëerde tijd", + "name": "Naam", + "name-required": "Naam is verplicht", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "type": "Type", + "created_customer": "Gemaakt door de klant", + "edit-scheduler-event": "Scheduler-event bewerken", + "view-scheduler-event": "Scheduler event weergeven", + "delete-scheduler-event": "Scheduler-event verwijderen", + "no-scheduler-events": "Geen planner-gebeurtenissen gevonden", + "selected-scheduler-events": "{ count, plural, =1 {1 scheduler event} andere {# scheduler events} } geselecteerd", + "delete-scheduler-event-title": "Weet u zeker dat u de '{{schedulerEventName}}' van de planningsgebeurtenis wilt verwijderen?", + "delete-scheduler-event-text": "Opgelet, na de bevestiging worden de event van de planner en alle gerelateerde gegevens onherstelbaar.", + "delete-scheduler-events-title": "Weet u zeker dat u { count, plural, =1 {1 scheduler event} andere {# scheduler events} } wilt verwijderen?", + "delete-scheduler-events-text": "Opgelet, na de bevestiging worden alle geselecteerde scheduler events verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "create": "Scheduler-event maken", + "edit": "Scheduler-event bewerken", + "view": "Scheduler event weergeven", + "configuration": "Configuratie", + "schedule": "Rooster", + "start-time": "Begintijd", + "repeat": "Herhalen", + "repeats": "Herhaalt", + "daily": "Dagelijks", + "every-n-days": "Elke N dagen", + "every-n-days-text": "Elke { days, plural, =1 {day} andere {# days} }", + "weekly": "Wekelijks", + "every-n-weeks": "Elke N weken", + "every-n-weeks-text": "Elke { weeks, plural, =1 {week} andere {# weeks} }", + "monthly": "Maandelijks", + "yearly": "Jaarlijks", + "timer": "Op basis van een timer", + "repeats-required": "Herhalingen zijn vereist.", + "repeat-on": "Herhaal op", + "repeat-every": "Herhaal elke", + "repeat-every-n-days": "Herhaal dit elke N dagen", + "repeat-days-required": "Het aantal dagen om te herhalen is vereist.", + "invalid-repeat-days-value": "Het aantal te herhalen dagen moet een positief geheel getal zijn.", + "repeat-every-n-weeks": "Herhaal elke N weken", + "repeat-weeks-required": "Aantal weken om te herhalen is vereist.", + "invalid-repeat-weeks-value": "Het aantal te herhalen weken moet een positief geheel getal zijn.", + "ends-on": "Eindigt op", + "sunday-label": "S", + "monday-label": "M", + "tuesday-label": "T", + "wednesday-label": "W", + "thursday-label": "T", + "friday-label": "F", + "saturday-label": "S", + "repeat-on-sunday": "Herhaling op zondag", + "repeat-on-monday": "Herhaal op maandag", + "repeat-on-tuesday": "Herhaal op dinsdag", + "repeat-on-wednesday": "Herhaal op woensdag", + "repeat-on-thursday": "Herhaal op donderdag", + "repeat-on-friday": "Herhaal op vrijdag", + "repeat-on-saturday": "Herhaling op zaterdag", + "event-type": "Type event", + "select-event-type": "Selecteer evenementtype", + "event-type-required": "Gebeurtenistype is vereist.", + "event-type-max-length": "Het gebeurtenistype moet kleiner zijn dan 256 tekens.", + "list-mode": "Lijst weergave", + "calendar-mode": "Kalenderweergave", + "calendar-view-type": "Type kalenderweergave", + "month": "Maand", + "week": "Week", + "day": "Dag", + "agenda-week": "Agenda Week", + "agenda-day": "Dag van de agenda", + "list-year": "Lijst Jaar", + "list-month": "Lijst Maand", + "list-week": "Lijst Week", + "list-day": "Lijst Dag", + "today": "Vandaag", + "navigate-before": "Navigeer voor", + "navigate-next": "Navigeer volgende", + "starting-from": "Vanaf", + "until": "totdat", + "on": "op", + "sunday": "Zondag", + "monday": "Maandag", + "tuesday": "Dinsdag", + "wednesday": "Woensdag", + "thursday": "Donderdag", + "friday": "Vrijdag", + "saturday": "Zaterdag", + "originator": "Opdrachtgever", + "single-entity": "Eén entiteit", + "group-of-entities": "Groep van entiteiten", + "entities-group-owner": "Eigenaar van entiteitengroep", + "single-device": "Eén device", + "group-of-devices": "Groep Devices", + "devices-group-owner": "Eigenaar van de Devicesgroep", + "message-body": "Hoofdtekst van bericht", + "target": "Doel", + "rpc-method": "Methode", + "rpc-method-required": "Methode is vereist", + "rpc-method-white-space": "Witruimte is niet toegestaan.", + "rpc-params": "Params", + "select-dashboard-state": "Dashboardstatus selecteren", + "hours": "Uren", + "minutes": "Notulen", + "seconds": "Seconden", + "time-interval-required": "Tijdsinterval is vereist", + "time-unit-required": "Tijdseenheid is vereist", + "every-hour": "elke { count, plural, =1 {hour} andere {# hours} }", + "every-minute": "elke { count, plural, =1 {minute} andere {# minutes} }", + "every-second": "elke { count, plural, =1 {second} andere {# seconds} }", + "invalid-time": "Ongeldige tijd" + }, + "report": { + "report-config": "Configuratie van rapporten", + "email-config": "E-mail configuratie", + "dashboard-state-param": "Parameterwaarde dashboardstatus", + "base-url": "Basis-URL", + "base-url-required": "Basis-URL is vereist.", + "use-dashboard-timewindow": "Dashboard tijdvenster gebruiken", + "timewindow": "Tijdvenster", + "name-pattern": "Patroon van rapportnaam", + "name-pattern-required": "Rapportnaam patroon is vereist", + "type": "Soort rapport", + "use-current-user-credentials": "Huidige gebruikersreferenties gebruiken", + "customer-user-credentials": "Gebruikersgegevens van de klant", + "customer-user-credentials-required": "Gebruikersgegevens van de klant zijn vereist", + "generate-test-report": "Testrapport genereren", + "send-email": "Stuur een e-mail", + "from": "Van", + "from-required": "Van is vereist.", + "to": "Aan", + "to-required": "Naar is vereist.", + "cc": "CC", + "bcc": "Bcc", + "subject": "Onderwerp", + "subject-required": "Onderwerp is verplicht.", + "body": "Body", + "body-required": "Body is vereist." + }, + "blob-entity": { + "blob-entity": "Blob-entiteit", + "select-blob-entity": "Blob-entiteit selecteren", + "no-blob-entities-matching": "Er zijn geen blob-entiteiten gevonden die overeenkomen met '{{entity}}'.", + "blob-entity-required": "Blob-entiteit is vereist", + "files": "Archief", + "search": "Bestanden zoeken", + "clear-search": "Zoekopdracht wissen", + "no-blob-entities-prompt": "Geen bestanden gevonden", + "report": "Rapport", + "created-time": "Gecreëerde tijd", + "name": "Naam", + "type": "Type", + "created_customer": "Gemaakt door de klant", + "selected-blob-entities": "{ count, plural, =1 {1 file} andere {# files} } geselecteerd", + "download-blob-entity": "Bestand downloaden", + "delete-blob-entity": "Bestand verwijderen", + "delete-blob-entity-title": "Weet u zeker dat u bestand '{{blobEntityName}}' wilt verwijderen?", + "delete-blob-entity-text": "Opgelet, na de bevestiging worden de gegevens van het bestand onherstelbaar.", + "delete-blob-entities-title": "Weet u zeker dat u { count, plural, =1 {1 file} andere {# files} } wilt verwijderen?", + "delete-blob-entities-text": "Opgelet, na de bevestiging worden alle geselecteerde bestanden verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld." + }, + "timezone": { + "timezone": "Tijdzone", + "select-timezone": "Selecteer tijdzone", + "no-timezones-matching": "Er zijn geen tijdzones gevonden die overeenkomen met '{{timezone}}'.", + "timezone-required": "Tijdzone is vereist.", + "browser-time": "Browser Tijd" + }, + "queue": { + "queue-name": "Rij", + "no-queues-found": "Geen queues gevonden.", + "no-queues-matching": "Er zijn geen queues gevonden die overeenkomen met '{{queue}}'.", + "select-name": "Selecteer de naam van de queue", + "name": "Naam", + "name-required": "Queue naam is verplicht!", + "name-unique": "De naam van de queue is niet uniek!", + "name-pattern": "De naam van de queue bevat een ander teken dan ASCII-alfanumerieke tekens, '.', '_' en '-'!", + "queue-required": "Queue is verplicht!", + "topic-required": "Wachtrijonderwerp is vereist!", + "poll-interval-required": "Poll-interval is vereist!", + "poll-interval-min-value": "De waarde van het pollinterval mag niet kleiner zijn dan 1", + "partitions-required": "Partities is vereist!", + "partitions-min-value": "De waarde van partities mag niet kleiner zijn dan 1", + "pack-processing-timeout-required": "Time-out voor verwerking is vereist", + "pack-processing-timeout-min-value": "De time-outwaarde voor verwerking mag niet kleiner zijn dan 1", + "batch-size-required": "Batchgrootte is vereist!", + "batch-size-min-value": "De waarde van de batchgrootte mag niet kleiner zijn dan 1", + "retries-required": "Opnieuw proberen is vereist!", + "retries-min-value": "De waarde voor nieuwe pogingen mag niet negatief zijn", + "failure-percentage-required": "Error percentage is vereist!", + "failure-percentage-min-value": "De waarde van het error percentage mag niet kleiner zijn dan 0", + "failure-percentage-max-value": "De waarde van het error percentage mag niet hoger zijn dan 100", + "pause-between-retries-required": "Pauze tussen nieuwe pogingen is vereist!", + "pause-between-retries-min-value": "De waarde van de pauze tussen nieuwe pogingen mag niet kleiner zijn dan 1", + "max-pause-between-retries-required": "Maximale pauze tussen nieuwe pogingen is vereist!", + "max-pause-between-retries-min-value": "De maximale pauze tussen de waarde voor nieuwe pogingen mag niet minder zijn dan 1", + "submit-strategy-type-required": "Strategietype indienen is vereist!", + "processing-strategy-type-required": "Het type verwerkingsstrategie is vereist!", + "queues": "Queues", + "selected-queues": "{ count, plural, =1 {1 queue} andere {# queues} } geselecteerd", + "delete-queue-title": "Weet je zeker dat je de queue '{{queueName}}' wilt verwijderen?", + "delete-queues-title": "Weet u zeker dat u { count, plural, =1 {1 queue} andere {# queues} } wilt verwijderen?", + "delete-queue-text": "Opgelet, na de bevestiging worden de queue en alle gerelateerde gegevens onherstelbaar.", + "delete-queues-text": "Na de bevestiging worden alle geselecteerde queues verwijderd en zijn ze niet meer toegankelijk.", + "search": "Queue zoeken", + "add": "Queue toevoegen", + "details": "Details van de queue", + "topic": "Onderwerp", + "submit-settings": "Instellingen verzenden", + "submit-strategy": "Soort strategie *", + "grouping-parameter": "Parameter groeperen", + "processing-settings": "Verwerkingsinstellingen opnieuw proberen", + "processing-strategy": "Soort verwerking *", + "retries-settings": "Instellingen voor nieuwe pogingen", + "polling-settings": "Polling-instellingen", + "batch-processing": "Batchverwerking", + "poll-interval": "Poll-interval", + "partitions": "Partities", + "immediate-processing": "Onmiddellijke verwerking", + "consumer-per-partition": "Stuur een berichtenquête voor elke consument", + "consumer-per-partition-hint": "Schakel afzonderlijke verbruiker(s) in voor elke partitie", + "processing-timeout": "Verwerking binnen, ms", + "batch-size": "Grootte van de partij", + "retries": "Aantal nieuwe pogingen (0 – onbeperkt)", + "failure-percentage": "Percentage mislukte berichten voor het overslaan van nieuwe pogingen", + "pause-between-retries": "Probeer het opnieuw binnen, sec", + "max-pause-between-retries": "Extra nieuwe poging binnen, sec", + "delete": "Queue verwijderen", + "copyId": "Queue-ID kopiëren", + "idCopiedMessage": "Queue-ID is gekopieerd naar klembord", + "description": "Omschrijving: __________", + "description-hint": "Deze tekst wordt weergegeven in de wachtrijbeschrijving in plaats van de geselecteerde strategie", + "alt-description": "Strategie indienen: {{submitStrategy}}, verwerkingsstrategie: {{processingStrategy}}", + "strategies": { + "sequential-by-originator-label": "Opeenvolgend door opsteller", + "sequential-by-originator-hint": "Het nieuwe bericht voor bijvoorbeeld device A wordt pas verzonden als het vorige bericht voor device A is bevestigd", + "sequential-by-tenant-label": "Sequentieel per tenant", + "sequential-by-tenant-hint": "Nieuw bericht voor bijvoorbeeld tenant A wordt pas verzonden als het vorige bericht voor tenant A is bevestigd", + "sequential-label": "Sequentieel", + "sequential-hint": "Nieuw bericht wordt pas verzonden als het vorige bericht is bevestigd", + "burst-label": "Barsten", + "burst-hint": "Alle berichten worden verzonden naar de rule chains in de volgorde waarin ze binnenkomen", + "batch-label": "Batch", + "batch-hint": "De nieuwe batch wordt pas ingediend als de vorige batch is bevestigd", + "skip-all-failures-label": "Sla alle storingen over", + "skip-all-failures-hint": "Negeer alle fouten", + "skip-all-failures-and-timeouts-label": "Sla alle storingen en time-outs over", + "skip-all-failures-and-timeouts-hint": "Negeer alle storingen en time-outs", + "retry-all-label": "Probeer alles opnieuw", + "retry-all-hint": "Probeer alle berichten uit het verwerkingspakket opnieuw uit te voeren", + "retry-failed-label": "Opnieuw proberen mislukt", + "retry-failed-hint": "Probeer alle mislukte berichten opnieuw uit het verwerkingspakket", + "retry-timeout-label": "Time-out opnieuw proberen", + "retry-timeout-hint": "Probeer alle time-outberichten opnieuw uit het verwerkingspakket", + "retry-failed-and-timeout-label": "Opnieuw proberen mislukt en time-out", + "retry-failed-and-timeout-hint": "Probeer alle mislukte en getimede berichten opnieuw uit het verwerkingspakket" + } + }, + "server-error": { + "general": "Algemene serverfout", + "authentication": "Authenticatie fout", + "jwt-token-expired": "JWT-token is verlopen", + "tenant-trial-expired": "Proefperiode tenant verlopen", + "credentials-expired": "Inloggegevens verlopen", + "permission-denied": "Toestemming geweigerd", + "invalid-arguments": "Ongeldige argumenten", + "bad-request-params": "Ongeldige aanvraagparameters", + "item-not-found": "Object niet gevonden", + "too-many-requests": "Te veel aanvragen", + "too-many-updates": "Te veel updates" + }, + "tenant": { + "tenant": "Tenant", + "tenants": "Tenants", + "management": "Beheer van tenants", + "add": "Tenant toevoegen", + "admins": "Beheerders", + "manage-tenant-admins": "Tenant beheerders beheren", + "delete": "Tenant verwijderen", + "add-tenant-text": "Nieuwe tenant toevoegen", + "no-tenants-text": "Geen tenants gevonden", + "tenant-details": "Gegevens tenant", + "title-max-length": "Titel moet kleiner zijn dan 256 tekens", + "delete-tenant-title": "Weet u zeker dat u de tenant '{{tenantTitle}}' wilt verwijderen?", + "delete-tenant-text": "Let op, na de bevestiging worden de tenant en alle gerelateerde gegevens onherstelbaar.", + "delete-tenants-title": "Weet u zeker dat u { count, plural, =1 {1 tenant} andere {# tenants} } wilt verwijderen?", + "delete-tenants-action-title": "Verwijder { count, plural, =1 {1 tenant} andere {# tenants} }", + "delete-tenants-text": "Let op, na de bevestiging worden alle geselecteerde tenants verwijderd en worden alle gerelateerde gegevens onherstelbaar.", + "title": "Titel", + "title-required": "Titel is vereist.", + "description": "Omschrijving: __________", + "details": "Details", + "events": "Events", + "copyId": "Tenant-id kopiëren", + "idCopiedMessage": "Tenant-id is gekopieerd naar klembord", + "select-tenant": "Selecteer tenant", + "no-tenants-matching": "Er zijn geen tenants gevonden die overeenkomen met '{{entity}}'.", + "tenant-required": "Tenant is verplicht", + "allow-white-labeling": "White Labeling toestaan", + "allow-customer-white-labeling": "White labeling van klanten toestaan", + "search": "Tenants zoeken", + "selected-tenants": "{ count, plural, =1 {1 tenant} andere {# tenants} } geselecteerd", + "isolated-tb-rule-engine": "Verwerking in geïsoleerde ThingsBoard Rule Engine-container", + "isolated-tb-rule-engine-details": "Vereist afzonderlijke microservice(s) per geïsoleerde tenant" + }, + "tenant-profile": { + "tenant-profile": "Profiel van de tenant", + "tenant-profiles": "Profielen van tenants", + "add": "Huurdersprofiel toevoegen", + "add-profile": "Profiel toevoegen", + "edit": "Huurdersprofiel bewerken", + "tenant-profile-details": "Details van tenantsprofiel", + "no-tenant-profiles-text": "Geen tenantsprofielen gevonden", + "name-max-length": "Naam moet kleiner zijn dan 256 tekens", + "search": "Tentant profielen zoeken", + "selected-tenant-profiles": "{ count, plural, =1 {1 tenant profile} andere {# tenant profiles} } geselecteerd", + "no-tenant-profiles-matching": "Er zijn geen tenantprofielen gevonden die overeenkomen met '{{entity}}'.", + "tenant-profile-required": "Huurdersprofiel is vereist", + "idCopiedMessage": "De profiel-id van de tenant is gekopieerd naar het klembord", + "set-default": "Tenantprofiel standaard instellen", + "delete": "Tenantprofiel verwijderen", + "copyId": "Tenantprofiel-id kopiëren", + "name": "Naam", + "name-required": "Naam is verplicht.", + "data": "Profiel gegevens", + "profile-configuration": "Profiel configuratie", + "description": "Omschrijving: __________", + "default": "Verstek", + "delete-tenant-profile-title": "Weet u zeker dat u het tenantsprofiel '{{tenantProfileName}}' wilt verwijderen?", + "delete-tenant-profile-text": "Let op, na de bevestiging wordt het tenantsprofiel en alle gerelateerde gegevens onherstelbaar.", + "delete-tenant-profiles-title": "Weet u zeker dat u { count, plural, =1 {1 tenant profile} andere {# tenant profiles} } wilt verwijderen?", + "delete-tenant-profiles-text": "Opgelet, na de bevestiging worden alle geselecteerde tenantsprofielen verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "set-default-tenant-profile-title": "Weet u zeker dat u het tenantsprofiel standaard '{{tenantProfileName}}' wilt maken?", + "set-default-tenant-profile-text": "Na de bevestiging wordt het tenantsprofiel als standaard gemarkeerd en wordt het gebruikt voor nieuwe tenants waarvoor geen profiel is opgegeven.", + "no-tenant-profiles-found": "Er zijn geen tenantsprofielen gevonden.", + "create-new-tenant-profile": "Maak een nieuwe aan!", + "create-tenant-profile": "Nieuw tenantsprofiel maken", + "import": "Tenantprofiel importeren", + "export": "Tenantprofiel exporteren", + "export-failed-error": "Kan tenantprofiel niet exporteren: {{error}}", + "tenant-profile-file": "Bestand met tenantsprofiel", + "invalid-tenant-profile-file-error": "Kan tenantprofiel niet importeren: Ongeldige gegevensstructuur van tenantprofiel.", + "advanced-settings": "Geavanceerde instellingen", + "entities": "Entiteiten", + "rule-engine": "Rule engine", + "time-to-live": "Tijd om te leven", + "alarms-and-notifications": "Alarmen en meldingen", + "ota-files-in-bytes": "OTA-bestanden in bytes", + "ws-title": "WS", + "unlimited": "(0 - onbeperkt)", + "maximum-devices": "Maximaal aantal Devices", + "maximum-devices-required": "Het maximale aantal devices is vereist.", + "maximum-devices-range": "Het maximale aantal devices mag niet negatief zijn", + "maximum-assets": "Maximaal aantal asset", + "maximum-assets-required": "Het maximale aantal asset is vereist.", + "maximum-assets-range": "Het maximumaantal items mag niet negatief zijn", + "maximum-customers": "Maximaal aantal klanten", + "maximum-customers-required": "Het maximale aantal klanten is vereist.", + "maximum-customers-range": "Het maximale aantal klanten mag niet negatief zijn", + "maximum-users": "Maximaal aantal gebruikers", + "maximum-users-required": "Het maximale aantal gebruikers is vereist.", + "maximum-users-range": "Het maximumaantal gebruikers mag niet negatief zijn", + "maximum-dashboards": "Dashboards maximaal aantal", + "maximum-dashboards-required": "Het maximale aantal dashboards is vereist.", + "maximum-dashboards-range": "Het maximumaantal dashboards mag niet negatief zijn", + "maximum-rule-chains": "Maximaal aantal rule chains", + "maximum-rule-chains-required": "Het maximale aantal rule chains is vereist.", + "maximum-rule-chains-range": "Het maximale aantal rule chains mag niet negatief zijn", + "maximum-integrations": "Integraties maximaal aantal", + "maximum-integrations-required": "Integraties maximaal aantal is vereist.", + "maximum-integrations-range": "Het maximale aantal integraties mag niet negatief zijn", + "maximum-converters": "Converters maximaal aantal", + "maximum-converters-required": "Het maximale aantal converters is vereist.", + "maximum-converters-range": "Het maximale aantal converters mag niet negatief zijn", + "maximum-scheduler-events": "Maximaal aantal scheduler events", + "maximum-scheduler-events-required": "Het maximale aantal scheduler events is vereist.", + "maximum-scheduler-events-range": "Het maximale aantal scheduler events mag niet negatief zijn", + "maximum-resources-sum-data-size": "Totale grootte van bronbestanden", + "maximum-resources-sum-data-size-required": "De somgrootte van bronbestanden is vereist.", + "maximum-resources-sum-data-size-range": "De somgrootte van resourcebestanden mag niet negatief zijn", + "maximum-ota-packages-sum-data-size": "Totale grootte van OTA-pakketbestanden", + "maximum-ota-package-sum-data-size-required": "De somgrootte van OTA-pakketbestanden is vereist.", + "maximum-ota-package-sum-data-size-range": "De somgrootte van OTA-pakketbestanden mag niet negatief zijn", + "rest-requests-for-tenant": "REST-aanvragen voor tenant", + "transport-tenant-telemetry-msg-rate-limit": "Telemetrieberichten van tenants vervoeren", + "transport-tenant-telemetry-data-points-rate-limit": "Telemetrie gegevenspunten voor transporttenants", + "transport-device-msg-rate-limit": "Berichten over transportmiddelen", + "transport-device-telemetry-msg-rate-limit": "Telemetrieberichten van transport devices", + "transport-device-telemetry-data-points-rate-limit": "Telemetrie gegevenspunten voor transport devices", + "tenant-entity-export-rate-limit": "Aanmaken van entiteitsversies", + "tenant-entity-import-rate-limit": "Laden van entiteitsversie", + "tenant-notification-request-rate-limit": "Verzoeken om kennisgeving", + "tenant-notification-requests-per-rule-rate-limit": "Notificatieverzoeken per notificatieregel", + "max-transport-messages": "Maximaal aantal transportberichten", + "max-transport-messages-required": "Transportberichten maximaal aantal is vereist.", + "max-transport-messages-range": "Het maximale aantal transportberichten mag niet negatief zijn", + "max-transport-data-points": "Maximaal aantal transportdatapunten", + "max-transport-data-points-required": "Er is een maximaal aantal transportdatapunten vereist.", + "max-transport-data-points-range": "Het maximale aantal transport gegevenspunten mag niet negatief zijn", + "max-r-e-executions": "Maximaal aantal uitvoeringen van rule engine", + "max-r-e-executions-required": "Het maximale aantal uitvoeringen van de rule engine is vereist.", + "max-r-e-executions-range": "Het maximale aantal uitvoeringen van de rule engine mag niet negatief zijn", + "max-j-s-executions": "Maximaal aantal JavaScript-uitvoeringen", + "max-j-s-executions-required": "Het maximale aantal JavaScript-uitvoeringen is vereist.", + "max-j-s-executions-range": "Het maximale aantal JavaScript-uitvoeringen mag niet negatief zijn", + "max-d-p-storage-days": "Maximaal aantal bewaardagen datapunten", + "max-d-p-storage-days-required": "Het maximale aantal opslagdagen voor datapunten is vereist.", + "max-d-p-storage-days-range": "Het maximale aantal opslagdagen voor gegevenspunten kan niet negatief zijn", + "default-storage-ttl-days": "Opslag TTL-dagen standaard", + "default-storage-ttl-days-required": "Standaard zijn TTL-dagen voor opslag vereist.", + "default-storage-ttl-days-range": "Opslag TTL-dagen kunnen standaard niet negatief zijn", + "alarms-ttl-days": "Alarmen TTL-dagen", + "alarms-ttl-days-required": "Alarmen TTL-dagen vereist", + "alarms-ttl-days-days-range": "Alarmen TTL-dagen kunnen niet negatief zijn", + "rpc-ttl-days": "RPC TTL-dagen", + "rpc-ttl-days-required": "RPC TTL-dagen vereist", + "rpc-ttl-days-days-range": "RPC TTL-dagen kunnen niet negatief zijn", + "max-rule-node-executions-per-message": "Maximaal aantal uitvoeringen van rule node per bericht", + "max-rule-node-executions-per-message-required": "MRule node per bericht voert het maximale aantal uit dat wordt uitgevoerd.", + "max-rule-node-executions-per-message-range": "Rule node per bericht dat wordt uitgevoerd, het maximale aantal kan niet negatief zijn", + "max-emails": "Maximaal aantal verzonden e-mails", + "max-emails-required": "Het maximale aantal verzonden e-mails is vereist.", + "max-emails-range": "Het maximale aantal verzonden e-mails mag niet negatief zijn", + "max-sms": "Maximaal aantal sms-berichten", + "max-sms-required": "Het maximale aantal sms-berichten is vereist.", + "max-sms-range": "Het maximale aantal verzonden sms'jes mag niet negatief zijn", + "max-created-alarms": "Maximaal aantal alarmen gemaakt", + "max-created-alarms-required": "Het maximale aantal alarmen is vereist.", + "max-created-alarms-range": "Alarmen gemaakt maximaal aantal negatief zijn", + "no-queue": "Geen queue geconfigureerd", + "add-queue": "Queue toevoegen", + "queues-with-count": "Queues ({{count}})", + "tenant-rest-limits": "REST-aanvragen voor tenant", + "customer-rest-limits": "REST-aanvragen voor klant", + "incorrect-pattern-for-rate-limits": "Het formaat bestaat uit door komma's gescheiden paren van capaciteit en punt (in seconden) met een dubbele punt ertussen, bijvoorbeeld 100:1,2000:60", + "too-small-value-zero": "De waarde moet groter zijn dan 0", + "too-small-value-one": "De waarde moet groter zijn dan 1", + "queue-size-is-limited-by-system-configuration": "De grootte van de queue wordt ook beperkt door de systeemconfiguratie.", + "cassandra-tenant-limits-configuration": "Cassandra-query voor tenant", + "ws-limit-max-sessions-per-tenant": "Sessies per tenant maximaal aantal", + "ws-limit-max-sessions-per-customer": "Maximaal aantal sessies per klant", + "ws-limit-max-sessions-per-regular-user": "Sessies per reguliere gebruiker maximaal aantal", + "ws-limit-max-sessions-per-public-user": "Maximaal aantal sessies per openbare gebruiker", + "ws-limit-queue-per-session": "Maximale grootte van berichtenwachtrij per sessie", + "ws-limit-max-subscriptions-per-tenant": "Maximaal aantal abonnementen per tenant", + "ws-limit-max-subscriptions-per-customer": "Abonnementen per klant maximum aantal", + "ws-limit-max-subscriptions-per-regular-user": "Abonnementen per gewone gebruiker maximum aantal", + "ws-limit-max-subscriptions-per-public-user": "Abonnementen per openbare gebruiker maximum aantal", + "ws-limit-updates-per-session": "WS-updates per sessie", + "rate-limits": { + "add-limit": "Limiet toevoegen", + "advanced-settings": "Geavanceerde instellingen", + "edit-limit": "Limiet bewerken", + "but-less-than": "maar minder dan", + "edit-transport-tenant-msg-title": "Snelheidslimieten voor berichten van transporttenants bewerken", + "edit-transport-tenant-telemetry-msg-title": "Snelheidslimieten voor telemetrie berichten van transporttenants bewerken", + "edit-transport-tenant-telemetry-data-points-title": "Snelheidslimieten voor telemetrie gegevenspunten van transporttenants bewerken", + "edit-transport-device-msg-title": "Snelheidslimieten voor berichten van transport devices bewerken", + "edit-transport-device-telemetry-msg-title": "Snelheidslimieten voor telemetrie berichten van transport devices bewerken", + "edit-transport-device-telemetry-data-points-title": "Snelheidslimieten voor telemetriegegevenspunten van transport devices bewerken", + "edit-tenant-rest-limits-title": "REST-aanvragen voor tarieflimieten voor tenants bewerken", + "edit-customer-rest-limits-title": "REST-aanvragen voor snelheidslimieten voor klanten bewerken", + "edit-ws-limit-updates-per-session-title": "Snelheidslimieten voor WS-updates per sessie bewerken", + "edit-cassandra-tenant-limits-configuration-title": "Cassandra-query bewerken voor tarieflimieten voor tenants", + "edit-tenant-entity-export-rate-limit-title": "Limieten voor het maken van entiteitsversies bewerken", + "edit-tenant-entity-import-rate-limit-title": "Limieten voor de laadsnelheid van entiteitsversies bewerken", + "edit-tenant-notification-request-rate-limit-title": "Snelheidslimieten voor meldingsverzoeken bewerken", + "edit-tenant-notification-requests-per-rule-rate-limit-title": "Snelheidslimieten voor meldingsverzoeken per meldingsregel bewerken", + "messages-per": "berichten per", + "not-set": "Niet ingesteld", + "number-of-messages": "Aantal berichten", + "number-of-messages-required": "Het aantal berichten is vereist.", + "number-of-messages-min": "Minimale waarde is 1.", + "preview": "Voorbeeld", + "per-seconds": "Per seconde", + "per-seconds-required": "Tijdtarief is vereist.", + "per-seconds-min": "Minimale waarde is 1.", + "rate-limits": "Limieten voor tarieven", + "remove-limit": "Limiet verwijderen", + "transport-tenant-msg": "Berichten van tenants vervoeren", + "transport-tenant-telemetry-msg": "Telemetrieberichten van tenants vervoeren", + "transport-tenant-telemetry-data-points": "Telemetriege gevenspunten voor transport tenants", + "transport-device-msg": "Berichten over transportmiddelen", + "transport-device-telemetry-msg": "Telemetrieberichten van transport devices", + "transport-device-telemetry-data-points": "Telemetriegegevenspunten voor transport devices", + "sec": "seconde" + } + }, + "timeinterval": { + "seconds-interval": "{ seconds, plural, =1 {1 second} andere {# seconds} }", + "minutes-interval": "{ minutes, plural, =1 {1 minute} andere {# minutes} }", + "hours-interval": "{ hours, plural, =1 {1 hour} andere {# hours} }", + "days-interval": "{ days, plural, =1 {1 day} andere {# days} }", + "days": "Dagen", + "hours": "Uren", + "minutes": "Notulen", + "seconds": "Seconden", + "advanced": "Geavanceerd", + "predefined": { + "yesterday": "Gisteren", + "day-before-yesterday": "Eergisteren", + "this-day-last-week": "Deze dag vorige week", + "previous-week": "Vorige week (zo - za)", + "previous-week-iso": "Vorige week (ma - zo)", + "previous-month": "Vorige maand", + "previous-quarter": "Vorig kwartaal", + "previous-half-year": "Vorig halfjaar", + "previous-year": "Vorig jaar", + "current-hour": "Huidig uur", + "current-day": "Huidige dag", + "current-day-so-far": "Huidige dag tot nu toe", + "current-week": "Huidige week (zo - za)", + "current-week-iso": "Huidige week (ma - zo)", + "current-week-so-far": "Huidige week tot nu toe (zo - za)", + "current-week-iso-so-far": "Huidige week tot nu toe (ma - zo)", + "current-month": "Huidige maand", + "current-month-so-far": "Huidige maand tot nu toe", + "current-quarter": "Huidig kwartaal", + "current-quarter-so-far": "Huidig kwartaal tot nu toe", + "current-half-year": "Huidig halfjaar", + "current-half-year-so-far": "Huidig halfjaar tot nu toe", + "current-year": "Huidig jaar", + "current-year-so-far": "Huidig jaar tot nu toe" + } + }, + "timeunit": { + "milliseconds": "Milliseconden", + "seconds": "Seconden", + "minutes": "Notulen", + "hours": "Uren", + "days": "Dagen" + }, + "timewindow": { + "years": "{ years, plural, =1 { year } andere {# years } }", + "months": "{ months, plural, =1 { month } andere {# months } }", + "weeks": "{ weeks, plural, =1 { week } andere {# weeks } }", + "days": "{ days, plural, =1 { day } andere {# days } }", + "hours": "{ hours, plural, =0 { hour } =1 {1 hour } andere {# hours } }", + "hr": "{{ hr }} uur", + "minutes": "{ minutes, plural, =0 { minute } =1 {1 minute } andere {# minutes } }", + "min": "{{ min }} min", + "seconds": "{ seconds, plural, =0 { second } =1 {1 second } andere {# seconds } }", + "sec": "{{ sec }} sec", + "short": { + "days": "{ days, plural, =1 {1 day } andere {# days } }", + "hours": "{ hours, plural, =1 {1 hour } andere {# hours } }", + "minutes": "{{minutes}} min", + "seconds": "{{seconds}} sec" + }, + "realtime": "Realtime", + "history": "Geschiedenis", + "last-prefix": "laatste", + "period": "van {{ startTime }} tot {{ endTime }}", + "edit": "Tijdvenster bewerken", + "date-range": "Periode", + "for-all-time": "Permanent", + "last": "Laatste", + "time-period": "Periode", + "hide": "Verbergen", + "interval": "Interval", + "just-now": "Daarnet", + "ago": "geleden" + }, + "user": { + "all": "Alle", + "all-users": "Alle gebruikers", + "groups": "Groepen", + "user": "Gebruiker", + "users": "Gebruikers", + "management": "Gebruikersbeheer", + "customer-users": "Gebruikers van klanten", + "tenant-admins": "Tenant Admins", + "sys-admin": "Systeembeheerder", + "tenant-admin": "Tenant beheerder", + "customer": "Klant", + "anonymous": "Anoniem", + "add": "Gebruiker toevoegen", + "delete": "Gebruiker verwijderen", + "add-user-text": "Nieuwe gebruiker toevoegen", + "no-users-text": "Geen gebruikers gevonden", + "user-details": "Gegevens van de gebruiker", + "delete-users": "Gebruikers verwijderen", + "delete-user-title": "Weet u zeker dat u de '{{userEmail}}' van de gebruiker wilt verwijderen?", + "delete-user-text": "Opgelet, na de bevestiging worden de gebruiker en alle gerelateerde gegevens onherstelbaar.", + "delete-users-title": "Weet u zeker dat u { count, plural, =1 {1 user} andere {# users} } wilt verwijderen?", + "delete-users-action-title": "Verwijder { count, plural, =1 {1 user} andere {# users} }", + "delete-users-text": "Opgelet, na de bevestiging worden alle geselecteerde gebruikers verwijderd en kunnen alle gerelateerde gegevens niet meer worden hersteld.", + "activation-email-sent-message": "Activeringsmail is succesvol verzonden!", + "resend-activation": "Activering opnieuw verzenden", + "email": "E-mail", + "email-required": "E-mail is vereist.", + "invalid-email-format": "Ongeldig e-mailformaat.", + "first-name": "Voornaam", + "last-name": "Achternaam", + "description": "Omschrijving: __________", + "default-dashboard": "Standaard dashboard", + "always-fullscreen": "Altijd volledig scherm", + "select-user": "Selecteer gebruiker", + "no-users-matching": "Er zijn geen gebruikers gevonden die overeenkomen met '{{entity}}'.", + "user-required": "Gebruiker is vereist", + "activation-method": "Activeringsmethode", + "display-activation-link": "Activeringslink weergeven", + "send-activation-mail": "Activeringsmail versturen", + "activation-link": "Activeringslink voor gebruiker", + "activation-link-text": "Om de gebruiker te activeren gebruikt u de volgende activation link:", + "copy-activation-link": "Activeringslink kopiëren", + "activation-link-copied-message": "De activeringslink van de gebruiker is gekopieerd naar het klembord", + "details": "Details", + "login-as-tenant-admin": "Aanmelden als tenantbeheerder", + "login-as-customer-user": "Inloggen als klantgebruiker", + "select-group-to-add": "Selecteer doelgroep om geselecteerde gebruikers toe te voegen", + "select-group-to-move": "Selecteer de doelgroep om geselecteerde gebruikers te verplaatsen", + "remove-users-from-group": "Weet je zeker dat je { count, plural, =1 {1 user} andere {# users} } uit groep '{{entityGroup}}' wilt verwijderen?", + "group": "Groep gebruikers", + "list-of-groups": "{ count, plural, =1 {One user group} andere {List of # user groups} }", + "group-name-starts-with": "Gebruikersgroepen waarvan de naam begint met '{{prefix}}'", + "search": "Gebruikers zoeken", + "selected-users": "{ count, plural, =1 {1 user} andere {# users} } geselecteerd", + "disable-account": "Gebruikersaccount uitschakelen", + "enable-account": "Gebruikersaccount inschakelen", + "enable-account-message": "Gebruikersaccount is succesvol ingeschakeld!", + "disable-account-message": "Gebruikersaccount is met succes uitgeschakeld!", + "copyId": "Kopieer gebruikers-ID", + "idCopiedMessage": "Gebruikers-ID is gekopieerd naar klembord", + "user-list": "Lijst met gebruikers", + "user-list-required": "Gebruikerslijst is vereist" + }, + "value": { + "type": "Soort waarde", + "string": "Snaar", + "string-value": "Tekenreeks waarde", + "string-value-required": "Tekenreekswaarde is vereist", + "integer": "Geheel getal", + "integer-value": "Gehele waarde", + "integer-value-required": "Geheel getal is vereist", + "invalid-integer-value": "Ongeldige waarde van een geheel getal", + "double": "Dubbel", + "double-value": "Dubbele waarde", + "double-value-required": "Dubbele waarde is vereist", + "boolean": "Booleaans", + "boolean-value": "Booleaanse waarde", + "false": "Vals", + "true": "Waar", + "long": "Lang", + "json": "JSON", + "json-value": "JSON-waarde", + "json-value-invalid": "JSON-waarde heeft een ongeldige indeling", + "json-value-required": "JSON-waarde is vereist." + }, + "version-control": { + "version-control": "Versiebeheer", + "management": "Beheer van versiebeheer", + "search": "Versies zoeken", + "branch": "Tak", + "default": "Verstek", + "select-branch": "Selecteer filiaal", + "branch-required": "Filiaal is vereist", + "create-entity-version": "Entiteitsversie maken", + "version-name": "Versienaam", + "version-name-required": "Versienaam is vereist", + "author": "Auteur", + "export-relations": "Exportrelaties", + "export-attributes": "Attributen exporteren", + "export-credentials": "Inloggegevens exporteren", + "export-group-entities": "Groepsentiteiten exporteren", + "export-roles": "Rollen exporteren", + "entity-versions": "Versies van entiteiten", + "versions": "Versies", + "created-time": "Gecreëerde tijd", + "version-id": "Versie-ID", + "no-entity-versions-text": "Geen entiteitsversies gevonden", + "no-versions-text": "Geen versies gevonden", + "copy-full-version-id": "Kopieer de volledige versie-id", + "create-version": "Versie maken", + "creating-version": "Versie maken... Een ogenblik geduld", + "nothing-to-commit": "Geen wijzigingen om vast te leggen", + "restore-version": "Versie herstellen", + "restore-entity-from-version": "Entiteit herstellen vanaf versie '{{versionName}}'", + "restoring-entity-version": "Entiteitsversie herstellen... Een ogenblik geduld", + "load-relations": "Relaties met belasting", + "load-attributes": "Attributen laden", + "load-credentials": "Inloggegevens laden", + "load-group-entities": "Groepsentiteiten laden", + "load-roles": "Rollen laden", + "compare-with-current": "Vergelijk met de huidige", + "diff-entity-with-version": "Verschil met entiteitsversie '{{versionName}}'", + "previous-difference": "Vorig verschil", + "next-difference": "Volgende Verschil", + "current": "Actueel", + "differences": "{ count, plural, =1 {1 difference} andere {# differences} }", + "create-entities-version": "Versie van entiteiten maken", + "default-sync-strategy": "Standaard synchronisatiestrategie", + "sync-strategy-merge": "Fuseren", + "sync-strategy-overwrite": "Overschrijven", + "entities-to-export": "Te exporteren entiteiten", + "entities-to-restore": "Entiteiten die moeten worden hersteld", + "sync-strategy": "Synchronisatie strategie", + "all-entities": "Alle entiteiten", + "no-entities-to-export-prompt": "Geef entiteiten op die u wilt exporteren", + "no-entities-to-restore-prompt": "Geef entiteiten op die u wilt herstellen", + "add-entity-type": "Entiteitstype toevoegen", + "remove-all": "Alles verwijderen", + "version-create-result": "{ added, plural, =0 {No entities} =1 {1 entity} andere {# entities} } toegevoegd.
{ modified, plural, =0 {No entities} =1 {1 entity} andere {# entities} } gewijzigd.
{ removed, plural, =0 {No entities} =1 {1 entity} andere {# entities} } verwijderd.", + "remove-other-entities": "Andere entiteiten verwijderen", + "find-existing-entity-by-name": "Bestaande entiteit zoeken op naam", + "restore-entities-from-version": "Entiteiten herstellen vanaf versie '{{versionName}}'", + "restoring-entities-from-version": "Entiteiten herstellen... Een ogenblik geduld", + "no-entities-restored": "Geen entiteiten hersteld", + "created": "{{created}} gemaakt", + "updated": "{{updated}} geüpdatet", + "deleted": "{{deleted}} geschrapt", + "groups-created": "{ created, plural, =1 {1 group} andere {# groups} } gemaakt", + "groups-updated": "{ updated, plural, =1 {1 group} andere {# groups} } bijgewerkt", + "groups-deleted": "{ deleted, plural, =1 {1 group} andere {# groups} } verwijderd", + "remove-other-entities-confirm-text": "Opgelet! Hiermee worden alle huidige entiteiten
die niet aanwezig zijn in de versie die u wilt herstellen, permanent verwijderd.

Typ andere entiteiten verwijderen om te bevestigen.", + "auto-commit-to-branch": "Automatisch vastleggen op {{ branch }} filiaal", + "default-create-entity-version-name": "{{entityName}} update", + "sync-strategy-merge-hint": "Hiermee maakt of actualiseert u geselecteerde entiteiten in de opslagplaats. Alle andere opslagplaatsentiteiten worden niet gewijzigd.", + "sync-strategy-overwrite-hint": "Hiermee maakt of actualiseert u geselecteerde entiteiten in de opslagplaats. Alle andere opslagplaatsentiteiten worden verwijderd.", + "device-credentials-conflict": "Kan het device niet laden met externe id {{entityId}}
omdat dezelfde referenties al aanwezig zijn in de database voor een ander device.
Overweeg om de instelling voor laadreferenties in het herstelformulier uit te schakelen.", + "missing-referenced-entity": "Het laden van de {{sourceEntityTypeName}} met externe id {{sourceEntityId}}
omdat het verwijst naar ontbrekende {{targetEntityTypeName}} met id {{targetEntityId}}.", + "add-entity-groups": "Entiteitsgroepen toevoegen", + "entity-groups": "Entiteitsgroepen", + "integration-routing-key-conflict": "Kan de integratie met externe id niet laden {{entityId}}
vanwege dezelfde integratiesleutel is al aanwezig in de database voor een andere integratie.
Overweeg om de instelling voor het automatisch genereren van integratiesleutels in het herstelformulier in te schakelen.", + "auto-generate-integration-key": "Integratiesleutel automatisch genereren", + "runtime-failed": "Mislukt: {{message}}", + "auto-commit-settings-read-only-hint": "De functie voor automatisch vastleggen werkt niet met de ingeschakelde niet editeerbaar optie in de instellingen van de opslagplaats." + }, + "widget": { + "widget-library": "Widgets Bibliotheek", + "widget-bundle": "Widgets Bundel", + "all-bundles": "Alle bundels", + "select-widgets-bundle": "Selecteer widgetsbundel", + "management": "Beheer van widgets", + "editor": "Widget-editor", + "widget-type-not-found": "Probleem met het laden van de configuratie van de widget.
Waarschijnlijk geassocieerd\n Widgettype is verwijderd.", + "widget-type-load-error": "Widget is niet geladen vanwege de volgende fouten:", + "remove": "Widget verwijderen", + "edit": "Widget bewerken", + "remove-widget-title": "Weet je zeker dat je de widget '{{widgetTitle}}' wilt verwijderen?", + "remove-widget-text": "Na de bevestiging worden de widget en alle gerelateerde gegevens onherstelbaar.", + "timeseries": "Timeseries", + "search-data": "Zoekgegevens", + "no-data-found": "Geen gegevens gevonden", + "latest": "Meest recente waarden", + "rpc": "Controle widget", + "alarm": "Alarm widget", + "static": "Statische widget", + "select-widget-type": "Selecteer widgettype", + "missing-widget-title-error": "De titel van de widget moet worden opgegeven!", + "widget-saved": "Widget opgeslagen", + "unable-to-save-widget-error": "Kan widget niet opslaan! Widget heeft fouten!", + "save": "Widget opslaan", + "saveAs": "Widget opslaan als", + "save-widget-type-as": "Widgettype opslaan als", + "save-widget-type-as-text": "Voer een nieuwe widgettitel in en/of selecteer de bundel met doelwidgets", + "toggle-fullscreen": "Volledig scherm in- en uitschakelen", + "run": "Widget uitvoeren", + "title": "Titel van de widget", + "title-required": "De titel van de widget is vereist.", + "type": "Type widget", + "resources": "Weg", + "resource-url": "JavaScript/CSS-URL", + "resource-is-module": "Is-module", + "remove-resource": "Bron verwijderen", + "add-resource": "Bron toevoegen", + "html": ".HTML", + "tidy": "Ordelijk", + "css": ".CSS", + "settings-schema": "Schema Instellingen", + "datakey-settings-schema": "Schema voor instellingen voor gegevenssleutels", + "latest-datakey-settings-schema": "Schema met meest recente instellingen voor gegevenssleutels", + "widget-settings": "Widget instellingen", + "description": "Omschrijving: __________", + "image-preview": "Voorbeeld van afbeelding", + "settings-form-selector": "Formulierkiezer voor instellingen", + "data-key-settings-form-selector": "Formulierkiezer voor instellingen voor gegevenssleutels", + "latest-data-key-settings-form-selector": "Formulierkiezer voor de meest recente gegevenssleutelinstellingen", + "javascript": "Javascript", + "js": ".JS", + "remove-widget-type-title": "Weet je zeker dat je het widgettype '{{widgetName}}' wilt verwijderen?", + "remove-widget-type-text": "Na de bevestiging worden het type widget en alle gerelateerde gegevens onherstelbaar.", + "remove-widget-type": "Widgettype verwijderen", + "add-widget-type": "Nieuw widgettype toevoegen", + "widget-type-load-failed-error": "Kan widgettype niet laden!", + "widget-template-load-failed-error": "Kan widgetsjabloon niet laden!", + "add": "Widget toevoegen", + "undo": "Wijzigingen in widgets ongedaan maken", + "export": "Widget exporteren", + "export-data": "Widgetgegevens exporteren", + "export-to-csv": "Exporteer gegevens naar CSV...", + "export-to-excel": "Gegevens exporteren naar XLS...", + "export-to-excel-xlsx": "Gegevens exporteren naar XLSX...", + "no-data": "Geen gegevens om weer te geven op widget", + "data-overflow": "Widget geeft {{count}} van {{total}} entiteiten weer", + "alarm-data-overflow": "Widget geeft alarmen weer voor {{allowedEntities}} (maximaal toegestane) entiteiten van {{totalEntities}} entiteiten", + "search": "Widget zoeken", + "filter": "Type widgetfilter", + "loading-widgets": "Widgets worden geladen...", + "widget-template-error": "Ongeldige HTML-sjabloon voor widgets." + }, + "widget-action": { + "header-button": "Knop koptekst widget", + "open-dashboard-state": "Navigeer naar de nieuwe dashboardstatus", + "update-dashboard-state": "Huidige dashboardstatus bijwerken", + "open-dashboard": "Navigeer naar ander dashboard", + "custom": "Aangepaste actie", + "custom-pretty": "Aangepaste actie (met HTML-sjabloon)", + "custom-pretty-error-title": "Fout in aangepast dialoogvenster", + "custom-pretty-template-error": "Ongeldige sjabloon voor een aangepast dialoogvenster.", + "custom-pretty-controller-error": "Er is een fout opgetreden bij het evalueren van de aangepaste dialoogvensterfunctie.", + "mobile-action": "Mobiele actie", + "target-dashboard-state": "Status van doeldashboard", + "target-dashboard-state-required": "De status van het doeldashboard is vereist", + "set-entity-from-widget": "Entiteit instellen vanuit widget", + "target-dashboard": "Dashboard voor doelen", + "open-right-layout": "Dashboardlay-out rechts openen (mobiele weergave)", + "state-display-type": "Optie voor weergave van de status van het dashboard", + "open-normal": "Normaal", + "open-in-separate-dialog": "Openen in apart dialoogvenster", + "open-in-popover": "Openen in popover", + "dialog-title": "Titel van het dialoogvenster", + "dialog-hide-dashboard-toolbar": "Dashboardwerkbalk verbergen in dialoogvenster", + "dialog-width": "Dialoogvensterbreedte in procenten ten opzichte van viewportbreedte", + "dialog-height": "Dialoogvensterhoogte in procenten ten opzichte van viewporthoogte", + "dialog-size-range-error": "De procentuele waarde van de dialooggrootte moet tussen 1 en 100 liggen.", + "popover-preferred-placement": "Voorkeursplaatsing van de popover", + "popover-placement-top": "Boven", + "popover-placement-topLeft": "Linksboven", + "popover-placement-topRight": "Rechtsboven", + "popover-placement-right": "Rechts", + "popover-placement-rightTop": "Rechtsboven", + "popover-placement-rightBottom": "Rechtsonder", + "popover-placement-bottom": "Bodem", + "popover-placement-bottomLeft": "Linksonder", + "popover-placement-bottomRight": "Rechtsonder", + "popover-placement-left": "Links", + "popover-placement-leftTop": "Links boven", + "popover-placement-leftBottom": "Links onder", + "popover-hide-on-click-outside": "Popover verbergen bij klikken aan de buitenkant", + "popover-hide-dashboard-toolbar": "Dashboardwerkbalk verbergen in pop-over", + "popover-width": "Popover-breedte in browsereenheden (bijv. 100px, 25vw)", + "popover-height": "Popover-hoogte in browsereenheden (bijv. 100px, 25vh)", + "popover-style": "Popover-stijl", + "open-new-browser-tab": "Openen in een nieuw browsertabblad", + "mobile": { + "action-type": "Mobiel actietype", + "action-type-required": "Mobiel actietype is vereist", + "take-picture-from-gallery": "Maak een foto uit de galerij", + "take-photo": "Maak een foto", + "map-direction": "Routebeschrijving openen", + "map-location": "Locatie op de kaart openen", + "scan-qr-code": "QR-code scannen", + "make-phone-call": "Telefoneren", + "get-location": "Telefoonlocatie ophalen", + "take-screenshot": "Screenshot maken" + } + }, + "widgets-bundle": { + "current": "Huidige bundel", + "widgets-bundles": "Widgets Bundels", + "add": "Widgets-bundel toevoegen", + "delete": "Widgetsbundel verwijderen", + "title": "Titel", + "title-required": "Titel is vereist.", + "title-max-length": "Titel moet kleiner zijn dan 256 tekens", + "description": "Omschrijving: __________", + "image-preview": "Voorbeeld van afbeelding", + "add-widgets-bundle-text": "Nieuwe widgetsbundel toevoegen", + "no-widgets-bundles-text": "Geen widgetbundels gevonden", + "empty": "Widgets-bundel is leeg", + "details": "Details", + "widgets-bundle-details": "Details van de widgetsbundel", + "delete-widgets-bundle-title": "Weet je zeker dat je de widgets bundel '{{widgetsBundleTitle}}' wilt verwijderen?", + "delete-widgets-bundle-text": "Opgelet, na de bevestiging worden de widgetbundel en alle gerelateerde gegevens onherstelbaar.", + "delete-widgets-bundles-title": "Weet u zeker dat u { count, plural, =1 {1 widgets bundle} andere {# widgets bundles} } wilt verwijderen?", + "delete-widgets-bundles-action-title": "Verwijder { count, plural, =1 {1 widgets bundle} andere {# widgets bundles} }", + "delete-widgets-bundles-text": "Opgelet, na de bevestiging worden alle geselecteerde widgetbundels verwijderd en worden alle gerelateerde gegevens onherstelbaar.", + "no-widgets-bundles-matching": "Er zijn geen widgetbundels gevonden die overeenkomen met '{{widgetsBundle}}'.", + "widgets-bundle-required": "Widgets-bundel is vereist.", + "system": "Systeem", + "import": "Widgets importeren bundel", + "export": "Widgets exporteren bundel", + "export-failed-error": "Kan widgetbundel niet exporteren: {{error}}", + "create-new-widgets-bundle": "Nieuwe widgetsbundel maken", + "widgets-bundle-file": "Widgets bundel bestand", + "invalid-widgets-bundle-file-error": "Kan widgetbundel niet importeren: Ongeldige widgetbundel gegevensstructuur.", + "search": "Widgetbundels zoeken", + "selected-widgets-bundles": "{ count, plural, =1 {1 widgets bundle} andere {# widgets bundles} } geselecteerd", + "open-widgets-bundle": "Widgets-bundel openen", + "loading-widgets-bundles": "Widgets bundels worden geladen..." + }, + "widget-config": { + "data": "Gegevens", + "settings": "Instellingen", + "advanced": "Geavanceerd", + "title": "Titel", + "title-tooltip": "Titel Tooltip", + "general-settings": "Algemene instellingen", + "display-title": "Titel van widget weergeven", + "drop-shadow": "Schaduw verwijderen", + "enable-fullscreen": "Volledig scherm inschakelen", + "enable-data-export": "Gegevensexport inschakelen", + "background-color": "Achtergrondkleur", + "text-color": "Tekstkleur", + "padding": "Spacties", + "margin": "Marge", + "widget-style": "Widget stijl", + "widget-css": "Widget CSS", + "title-style": "Titel stijl", + "mobile-mode-settings": "Mobiele modus", + "order": "Bevelen", + "height": "Hoogte", + "mobile-hide": "Widget verbergen in mobiele modus", + "desktop-hide": "Widget verbergen in desktopmodus", + "units": "Speciaal symbool om naast waarde weer te geven", + "decimals": "Aantal cijfers na drijvende komma", + "timewindow": "Tijdvenster", + "use-dashboard-timewindow": "Dashboardtijdvenster gebruiken", + "display-timewindow": "Tijdvenster weergeven", + "legend": "Legende", + "display-legend": "Legende weergeven", + "datasources": "Gegevensbronnen", + "maximum-datasources": "Maximaal { count, plural, =1 {1 datasource is allowed.} andere {# datasources are allowed} }", + "timeseries-key-error": "Er moet ten minste één tijdreeksgegevenssleutel worden opgegeven", + "datasource-type": "Type", + "datasource-parameters": "Parameters", + "remove-datasource": "Gegevensbron verwijderen", + "add-datasource": "Gegevensbron toevoegen", + "target-device": "Doelapparaat", + "alarm-source": "Alarmbron", + "actions": "Acties", + "action": "Actie", + "add-action": "Actie toevoegen", + "search-actions": "Zoekacties", + "no-actions-text": "Geen acties gevonden", + "action-source": "Bron van actie", + "action-source-required": "Actiebron is vereist.", + "action-name": "Naam", + "action-name-required": "De naam van de actie is vereist.", + "action-name-not-unique": "Er bestaat al een andere actie met dezelfde naam.
De naam van de actie moet uniek zijn binnen dezelfde actiebron.", + "action-icon": "Pictogram", + "show-hide-action-using-function": "Actie tonen/verbergen met behulp van functie", + "action-type": "Type", + "action-type-required": "Actietype is vereist.", + "edit-action": "Actie bewerken", + "delete-action": "Actie verwijderen", + "delete-action-title": "Widgetactie verwijderen", + "delete-action-text": "Weet je zeker dat je de actie voor het verwijderen van widgets met de naam '{{actionName}}' wilt?", + "title-icon": "Titel icoon", + "display-icon": "Titelpictogram weergeven", + "icon-color": "Kleur van het pictogram", + "icon-size": "Grootte van het pictogram", + "advanced-settings": "Geavanceerde instellingen", + "data-settings": "Gegevensinstellingen", + "no-data-display-message": "Alternatief bericht 'Geen gegevens om weer te geven'", + "data-page-size": "Maximum aantal entiteiten per gegevensbron", + "settings-component-not-found": "Instellingen formuliercomponent niet gevonden voor selector '{{selector}}'" + }, + "widget-type": { + "import": "Type widget importeren", + "export": "Widgettype exporteren", + "export-failed-error": "Kan widgettype niet exporteren: {{error}}", + "create-new-widget-type": "Nieuw widgettype maken", + "widget-type-file": "Bestand van het type widget", + "invalid-widget-type-file-error": "Kan widgettype niet importeren: Ongeldige gegevensstructuur van het widgettype." + }, + "self-registration": { + "self-registration": "Zelf registratie", + "self-registration-url": "URL voor zelfregistratie", + "captcha-version": "reCAPTCHA-versie", + "captcha-action": "naam van de actie van het reCAPTCHA-logboek", + "captcha-site-key": "reCAPTCHA-sitesleutel", + "captcha-secret-key": "reCAPTCHA geheime sleutel", + "notification-email": "E-mail met melding", + "privacy-policy-text": "Tekst van het privacybeleid", + "terms-of-use-text": "Tekst van de gebruiksvoorwaarden", + "text-message-page": "Sms voor aanmeldingspagina", + "enable-mobile-self-registration": "Zelfregistratie inschakelen vanuit de mobiele applicatie", + "mobile-self-registration-title": "Instellingen voor zelfregistratie van mobiele applicaties", + "mobile-package": "Applicatie pakket", + "mobile-package-placeholder": "Vb.: my.example.app", + "mobile-package-hint": "Voor Android: uw eigen unieke applicatie-ID. Voor iOS: ID van productbundel.", + "mobile-package-required": "Aanvraagpakket is vereist", + "mobile-app-secret": "Geheim van de toepassing", + "invalid-mobile-app-secret": "Het geheim van de toepassing mag alleen alfanumerieke tekens bevatten en moet tussen de 16 en 2048 tekens lang zijn.", + "copy-mobile-app-secret": "Toepassingsgeheim kopiëren", + "mobile-app-scheme": "URL-schema van toepassing", + "mobile-app-scheme-placeholder": "Vb.: maatwerk", + "mobile-app-scheme-required": "Het URL-schema van de aanvraag is vereist", + "mobile-app-host": "Hostnaam van applicatie-URL", + "mobile-app-host-placeholder": "Bijv.: mijn.app.host", + "mobile-app-host-required": "Hostnaam van toepassings-URL is vereist", + "show-privacy-policy": "Toon Privacybeleid", + "show-terms-of-use": "Toon Gebruiksvoorwaarden", + "domain-settings": "Domein instellingen", + "general-settings": "Algemene instellingen" + }, + "solution-template": { + "solution-template": "Oplossing sjabloon", + "solution-templates": "Sjablonen voor oplossingen", + "management": "Oplossingssjablonen beheren", + "details": "Details", + "install": "Installeren", + "level": "Niveau", + "install-title": "Oplossingssjabloon succesvol geïnstalleerd", + "install-failed-title": "Installatie van oplossingssjabloon mislukt", + "instructions": "Aanwijzingen", + "goto-main-dashboard": "Ga naar het hoofddashboard", + "delete": "Verwijderen", + "delete-solution-title": "Weet u zeker dat u de oplossing '{{solutionTitle}}' wilt verwijderen?", + "delete-solution-text": "Opgelet, na de bevestiging worden de oplossing en alle gerelateerde gegevens onherstelbaar.", + "installing": "Oplossingssjabloon installeren..." + }, + "markdown": { + "edit": "Bewerken", + "preview": "Voorbeeld", + "copy-code": "Klik om te kopiëren", + "copied": "Gekopieerd!" + }, + "white-labeling": { + "white-labeling": "White labelling", + "white-labeling-general": "Algemene White Labeling", + "login-white-labeling": "Inloggen White Labeling", + "general": "Algemeen", + "login": "Inloggen", + "preview": "Voorbeeld", + "app-title": "Titel van de toepassing", + "favicon": "Website icoon", + "favicon-description": "*.ico, *.gif of *.png afbeelding met een maximale grootte {{kbSize}} KBytes.", + "favicon-size-error": "De afbeelding van de website is te groot. De maximaal toegestane afbeeldingsgrootte van de website {{kbSize}} KBytes.", + "favicon-type-error": "Ongeldige bestandsindeling voor websiteafbeeldingen. Alleen ICO-, GIF- of PNG-afbeeldingen worden geaccepteerd.", + "drop-favicon-image": "Zet een afbeelding van een websitepictogram neer of klik om een bestand te selecteren om te uploaden.", + "drop-favicon-image-or": "Sleep een afbeelding van een websitepictogram of", + "no-favicon-image": "Geen pictogram geselecteerd", + "logo": "Logo", + "logo-description": "Elke afbeelding met een maximale grootte {{kbSize}} KBytes.", + "logo-size-error": "De afbeelding van het logo is te groot. De maximaal toegestane afbeeldingsgrootte van het logo {{kbSize}} KBytes.", + "logo-type-error": "Ongeldig bestandsformaat voor logo's. Alleen afbeeldingen worden geaccepteerd.", + "drop-logo-image": "Zet een logo-afbeelding neer of klik om een bestand te selecteren om te uploaden.", + "drop-logo-image-or": "Een logo-afbeelding slepen en neerzetten of", + "no-logo-image": "Geen logo geselecteerd", + "logo-height": "Hoogte logo, px", + "primary-palette": "Primair palet", + "accent-palette": "Accent palet", + "customize-palette": "Aanpassen", + "advanced-css": "Geavanceerde CSS", + "edit-palette": "Palet bewerken", + "save-palette": "Palet opslaan", + "primary-background": "Primaire achtergrond", + "secondary-background": "Secundaire achtergrond", + "hue1": "TINT 1", + "hue2": "HUE 2", + "hue3": "HUE 3", + "page-background-color": "Achtergrondkleur van de pagina", + "dark-foreground": "Donkere voorgrond", + "domain-name": "Domeinnaam", + "base-url": "Basis-URL", + "base-url-required": "Basis-URL is vereist.", + "prohibit-different-url": "Verbieden om de hostnaam te gebruiken in de headers van de clientaanvraag", + "prohibit-different-url-hint": "Deze instelling moet zijn ingeschakeld voor productieomgevingen. Kan beveiligingsproblemen veroorzaken wanneer deze is uitgeschakeld", + "help-link-base-url": "Help-links basis-url", + "ui-help-base-url": "Help-basis-URL van de gebruikersinterface", + "enable-help-links": "Helpkoppelingen inschakelen", + "error-verification-url": "Een domeinnaam mag geen symbolen '/' en ':' bevatten. Voorbeeld: thingsboard.io", + "show-platform-name-version": "Platformnaam en -versie weergeven", + "platform-name": "Naam van het platform", + "platform-version": "Platform versie", + "version-mask": "{{name}} v.{{version}}", + "position": { + "label": "Platformnaam en versiepositie", + "under-logo": "Onder het logo", + "bottom": "Onderaan het inlogformulier" + } + }, + "widgets": { + "chart": { + "common-settings": "Algemene instellingen", + "enable-stacking-mode": "Stapelmodus inschakelen", + "line-shadow-size": "Grootte van de lijnschaduw", + "display-smooth-lines": "Vloeiende (gebogen) lijnen weergeven", + "default-bar-width": "Standaardbalkbreedte voor niet-geaggregeerde gegevens (milliseconden)", + "bar-alignment": "Staaf uitlijning", + "bar-alignment-left": "Links", + "bar-alignment-right": "Rechts", + "bar-alignment-center": "Middelpunt", + "default-font-size": "Standaard lettergrootte", + "default-font-color": "Standaard tekstkleur", + "thresholds-line-width": "Standaardregeldikte voor alle drempels", + "tooltip-settings": "Tooltip-instellingen", + "show-tooltip": "Tooltip weergeven", + "hover-individual-points": "Beweeg de muisaanwijzer over individuele punten", + "show-cumulative-values": "Cumulatieve waarden weergeven in stapelmodus", + "hide-zero-false-values": "Nul/onwaar-waarden verbergen in knopinfo", + "tooltip-value-format-function": "Functie voor het opmaken van knoppuntwaarden", + "grid-settings": "Raster instellingen", + "show-vertical-lines": "Verticale lijnen weergeven", + "show-horizontal-lines": "Horizontale lijnen weergeven", + "grid-outline-border-width": "Rasteromtrek/randbreedte (px)", + "primary-color": "Primaire kleur", + "background-color": "Achtergrondkleur", + "ticks-color": "De kleur van de teken", + "xaxis-settings": "Instellingen van de X-as", + "axis-title": "Titel van de as", + "xaxis-tick-labels-settings": "Instellingen voor labels voor tikken op de X-as", + "show-tick-labels": "Labels voor asvinkjes weergeven", + "yaxis-settings": "Y-as instellingen", + "min-scale-value": "Minimumwaarde op de weegschaal", + "max-scale-value": "Maximale waarde op de weegschaal", + "yaxis-tick-labels-settings": "Instellingen voor labels voor Y-as tikken", + "tick-step-size": "Stapgrootte tussen teken", + "number-of-decimals": "Het aantal decimalen dat moet worden weergegeven", + "ticks-formatter-function": "Teken formatter-functie", + "comparison-settings": "Vergelijkingsinstellingen", + "enable-comparison": "Vergelijking inschakelen", + "time-for-comparison": "Vergelijkingsperiode", + "time-for-comparison-previous-interval": "Vorig interval (standaard)", + "time-for-comparison-days": "Dag geleden", + "time-for-comparison-weeks": "Week geleden", + "time-for-comparison-months": "Maand geleden", + "time-for-comparison-years": "Jaar geleden", + "time-for-comparison-custom-interval": "Aangepast interval", + "custom-interval-value": "Aangepaste intervalwaarde (ms)", + "comparison-x-axis-settings": "Vergelijking X-asinstellingen", + "axis-position": "Positie van de as", + "axis-position-top": "Top (standaard)", + "axis-position-bottom": "Bodem", + "custom-legend-settings": "Aangepaste legende-instellingen", + "enable-custom-legend": "Aangepaste legende inschakelen (hiermee kunt u attribuut-/tijdreekswaarden gebruiken in sleutellabels)", + "key-name": "Naam van de sleutel", + "key-name-required": "Sleutelnaam is vereist", + "key-type": "Type sleutel", + "key-type-attribute": "Attribuut", + "key-type-timeseries": "Timeseries", + "label-keys-list": "Toetsenlijst voor labels", + "no-label-keys": "Geen sleutels geconfigureerd", + "add-label-key": "Nieuwe sleutel toevoegen", + "line-width": "Lijndikte", + "color": "Kleur", + "data-is-hidden-by-default": "Gegevens zijn standaard verborgen", + "disable-data-hiding": "Schakel het verbergen van gegevens uit", + "remove-from-legend": "Datakey verwijderen uit legende", + "exclude-from-stacking": "Uitsluiten van stapelen (beschikbaar in de modus \"Stapelen\")", + "line-settings": "Lijn instellingen", + "show-line": "Toon lijn", + "fill-line": "Lijn vullen", + "fill-line-opacity": "Dekking vullen", + "points-settings": "Punten instellingen", + "show-points": "Toon punten", + "points-line-width": "Lijndikte van punten", + "points-radius": "Straal van punten", + "point-shape": "Puntvorm", + "point-shape-circle": "Cirkel", + "point-shape-cross": "Kruis", + "point-shape-diamond": "Diamant", + "point-shape-square": "Vierkant", + "point-shape-triangle": "Driehoek", + "point-shape-custom": "Aangepaste functie", + "point-shape-draw-function": "Tekenfunctie voor puntvorm", + "show-separate-axis": "Afzonderlijke as weergeven", + "axis-position-left": "Links a-x positie", + "axis-position-right": "Rechts a-x positie", + "thresholds": "Drempels", + "no-thresholds": "Geen drempels geconfigureerd", + "add-threshold": "Nieuwe drempel toevoegen", + "show-values-for-comparison": "Historische waarden weergeven ter vergelijking", + "comparison-values-label": "Label met historische waarden", + "threshold-settings": "Drempelwaarde instellingen", + "use-as-threshold": "Sleutelwaarde gebruiken als drempelwaarde", + "threshold-line-width": "Lijnbreedte drempel", + "threshold-color": "Drempel kleur", + "common-pie-settings": "Algemene taartinstellingen", + "radius": "Radius", + "inner-radius": "Binnen radius", + "tilt": "Kantelen", + "stroke-settings": "Lijn instellingen", + "width-pixels": "Breedte (pixels)", + "show-labels": "Labels weergeven", + "animation-settings": "Animatie-instellingen", + "animated-pie": "Pie animatie inschakelen (experimenteel)", + "border-settings": "Randinstellingen", + "border-width": "Breedte van de edge", + "border-color": "Kleur van de edge", + "legend-settings": "Legende-instellingen", + "display-legend": "Legende weergeven", + "labels-font-color": "Letterkleur van labels" + }, + "dashboard-state": { + "dashboard-state-settings": "Instellingen voor de status van het dashboard", + "dashboard-state": "Status-id van dashboard", + "autofill-state-layout": "Standaard lay-outhoogte voor automatisch aanvullen", + "default-margin": "Standaard widgets marge", + "default-background-color": "Standaard achtergrondkleur", + "sync-parent-state-params": "Statusparameters synchroniseren met het bovenliggende dashboard" + }, + "date-range-navigator": { + "date-range-picker-settings": "Instellingen voor het kiezen van het datumbereik", + "hide-date-range-picker": "Datumbereik kiezer verbergen", + "picker-one-panel": "Datumbereik kiezer één paneel", + "picker-auto-confirm": "Datumbereik kiezer automatisch bevestigen", + "picker-show-template": "Datumbereik kiezer toon sjabloon", + "first-day-of-week": "Eerste dag van de week", + "interval-settings": "Interval-instellingen", + "hide-interval": "Interval verbergen", + "initial-interval": "Initieel interval", + "interval-hour": "Uur", + "interval-day": "Dag", + "interval-week": "Week", + "interval-two-weeks": "2 weken", + "interval-month": "Maand", + "interval-three-months": "3 maanden", + "interval-six-months": "6 maanden", + "step-settings": "Stap instellingen", + "hide-step-size": "Stapgrootte verbergen", + "initial-step-size": "Grootte van de eerste stap", + "hide-labels": "Labels verbergen", + "use-session-storage": "Sessieopslag gebruiken", + "localizationMap": { + "Sun": "Zon", + "Mon": "Ma", + "Tue": "Di", + "Wed": "Woe", + "Thu": "Do", + "Fri": "Vr", + "Sat": "Zaterdag", + "Jan": "Jan", + "Feb": "Februari", + "Mar": "Mar", + "Apr": "Apr", + "May": "Mei", + "Jun": "Jun", + "Jul": "Jul", + "Aug": "Aug", + "Sep": "Sep", + "Oct": "Oct", + "Nov": "Nov", + "Dec": "Dec", + "January": "Januari", + "February": "Februari", + "March": "Maart", + "April": "April", + "June": "Juni", + "July": "Juli", + "August": "Augustus", + "September": "September", + "October": "Oktober", + "November": "November", + "December": "December", + "Custom Date Range": "Aangepast datumbereik", + "Date Range Template": "Datumbereik sjabloon", + "Today": "Vandaag", + "Yesterday": "Gisteren", + "This Week": "Deze week", + "Last Week": "Vorige week", + "This Month": "Deze maand", + "Last Month": "Afgelopen maand", + "Year": "Jaar", + "This Year": "Dit jaar", + "Last Year": "Vorig jaar", + "Date picker": "Datumkiezer", + "Hour": "Uur", + "Day": "Dag", + "Week": "Week", + "2 weeks": "2 weken", + "Month": "Maand", + "3 months": "3 maanden", + "6 months": "6 maanden", + "Custom interval": "Aangepast interval", + "Interval": "Interval", + "Step size": "Stap grootte", + "Ok": "OK" + } + }, + "entities-hierarchy": { + "hierarchy-data-settings": "Instellingen voor hiërarchische gegevens", + "relations-query-function": "Queryfunctie voor knooppuntrelaties", + "has-children-function": "Knoop heeft een kinderfunctie", + "node-state-settings": "Instellingen voor knooppuntstatus", + "node-opened-function": "Standaard functie voor het openen van rule nodes", + "node-disabled-function": "Knooppuntuitgeschakelde functie", + "display-settings": "Weergave-instellingen", + "node-icon-function": "Knooppuntpictogram functie", + "node-text-function": "Knooppunttekstfunctie", + "sort-settings": "Sorteer instellingen", + "nodes-sort-function": "Sorteerfunctie voor rule nodes" + }, + "edge": { + "display-default-title": "Standaardtitel weergeven" + }, + "gateway": { + "general-settings": "Algemene instellingen", + "widget-title": "Titel van de widget", + "default-archive-file-name": "Standaard bestandsnaam voor archief", + "device-type-for-new-gateway": "Device type voor nieuwe gateway", + "messages-settings": "Instellingen voor Berichten", + "save-config-success-message": "Sms-bericht over succesvol opgeslagen gatewayconfiguratie", + "device-name-exists-message": "Sms-bericht wanneer het device met de ingevoerde naam al bestaat", + "gateway-title": "Gateway-formulier", + "read-only": "Alleen-lezen", + "events-title": "Titel van het formulier voor gateway events", + "events-filter": "Events filter", + "event-key-contains": "Events sleutel bevat..." + }, + "gauge": { + "default-color": "Standaard kleur", + "radial-gauge-settings": "Instellingen radiale meter", + "ticks-settings": "Vink instellingen aan", + "min-value": "Minimumwaarde", + "max-value": "Maximale waarde", + "start-ticks-angle": "Start tikt hoek", + "ticks-angle": "De hoek van teken", + "major-ticks-count": "Aantal belangrijke teken", + "major-ticks-color": "De belangrijkste kleur van teken", + "minor-ticks-count": "Kleine vinkjes tellen", + "minor-ticks-color": "Kleine vinkjes kleur", + "tick-numbers-font": "Tick nummers lettertype", + "unit-title-settings": "Instellingen voor eenheidstitels", + "show-unit-title": "Titel van eenheid weergeven", + "unit-title": "Titel van de eenheid", + "title-font": "Lettertype van titeltekst", + "units-settings": "Instellingen van de eenheden", + "units-font": "Eenheden tekstlettertype", + "value-box-settings": "Instellingen voor het vak Waarde", + "show-value-box": "Vak Waarde weergeven", + "value-int": "Cijfers tellen mee voor het gehele deel van de waarde", + "value-font": "Waarde tekstlettertype", + "value-box-rect-stroke-color": "Voordeelvak rechthoekige lijnkleur", + "value-box-rect-stroke-color-end": "Voordeelvak rechthoekige lijnkleur - eindverloop", + "value-box-background-color": "Achtergrondkleur van het waardevak", + "value-box-shadow-color": "Waarde vak schaduw kleur", + "plate-settings": "Plaat instellingen", + "show-plate-border": "Plaatrand weergeven", + "plate-color": "Kleur van de plaat", + "needle-settings": "Naald instellingen", + "needle-circle-size": "De grootte van de naaldcirkel", + "needle-color": "Kleur van de naald", + "needle-color-end": "Naaldkleur - eindverloop", + "needle-color-shadow-up": "Bovenste helft van de kleur van de naaldschaduw", + "needle-color-shadow-down": "Kleur slagschaduw naald", + "highlights-settings": "Instellingen voor markeringen", + "highlights-width": "Breedte van hoogtepunten", + "highlights": "Hoogtepunten", + "highlight-from": "Van", + "highlight-to": "Aan", + "highlight-color": "Kleur", + "no-highlights": "Geen markeringen geconfigureerd", + "add-highlight": "Markering toevoegen", + "animation-settings": "Animatie-instellingen", + "enable-animation": "Animatie inschakelen", + "animation-duration": "Duur van de animatie", + "animation-rule": "Animatie regel", + "animation-linear": "Lineair", + "animation-quad": "Quad", + "animation-quint": "Quint", + "animation-cycle": "Cyclus", + "animation-bounce": "Stuiteren", + "animation-elastic": "Elastisch", + "animation-dequad": "Splitsen", + "animation-dequint": "Afscheid nemen", + "animation-decycle": "Uitzetten", + "animation-debounce": "Debouncen", + "animation-delastic": "Delastisch", + "linear-gauge-settings": "Lineaire meetinstellingen", + "bar-stroke-width": "Lijnbreedte van de staaf", + "bar-stroke-color": "Kleur balklijn", + "bar-background-color": "Achtergrondkleur van de meterbalk", + "bar-background-color-end": "Achtergrondkleur van de balk - eindverloop", + "progress-bar-color": "Kleur voortgangsbalk", + "progress-bar-color-end": "Kleur voortgangsbalk - eindverloop", + "major-ticks-names": "Belangrijke namen van teken", + "show-stroke-ticks": "Toon teken beroerte", + "major-ticks-font": "Het belangrijkste teken lettertype", + "border-color": "Kleur van de edge", + "border-width": "Breedte van de edge", + "needle-circle-color": "De cirkelkleur van de naald", + "animation-target": "Animatie doel", + "animation-target-needle": "Naald", + "animation-target-plate": "Bord", + "common-settings": "Gemeenschappelijke meterinstellingen", + "gauge-type": "Type meter", + "gauge-type-arc": "Boog", + "gauge-type-donut": "Donut", + "gauge-type-horizontal-bar": "Rekstok", + "gauge-type-vertical-bar": "Verticale balk", + "donut-start-angle": "Hoek om mee te beginnen", + "bar-settings": "Meetbalk-instellingen", + "relative-bar-width": "Relatieve staafbreedte", + "neon-glow-brightness": "Neon glow effect helderheid, (0-100), 0 - effect uitschakelen", + "stripes-thickness": "Dikte van de strepen, 0 - geen strepen", + "rounded-line-cap": "Afgeronde lijndop weergeven", + "bar-color-settings": "Kleurinstellingen voor de balk", + "use-precise-level-color-values": "Gebruik nauwkeurige kleurniveaus", + "bar-colors": "Balkkleuren, van onder naar boven", + "color": "Kleur", + "no-bar-colors": "Geen balkkleuren geconfigureerd", + "add-bar-color": "Staafkleur toevoegen", + "from": "Van", + "to": "Aan", + "fixed-level-colors": "Staafkleuren met behulp van grenswaarden", + "gauge-title-settings": "Titelinstellingen meten", + "show-gauge-title": "Metertitel weergeven", + "gauge-title": "Titel van de meter", + "gauge-title-font": "Lettertype van de metertitel", + "unit-title-and-timestamp-settings": "Instellingen voor titel en tijdstempel van de eenheid", + "show-timestamp": "Tijdstempel van de waarde weergeven", + "timestamp-format": "Indeling tijdstempel", + "label-font": "Lettertype van label dat onder waarde wordt weergegeven", + "value-settings": "Waarde-instellingen", + "show-value": "Waardetekst weergeven", + "min-max-settings": "Instellingen voor minimale/maximale labels", + "show-min-max": "Min- en max-waarden weergeven", + "min-max-font": "Lettertype van minimum- en maximumlabels", + "show-ticks": "Toon teken", + "tick-width": "Tikbreedte", + "tick-color": "Vink kleur aan", + "tick-values": "Vink waarden aan", + "no-tick-values": "Geen vinkjes geconfigureerd", + "add-tick-value": "Tick waarde toevoegen" + }, + "gpio": { + "pin": "Speld", + "label": "Etiket", + "row": "Rijen", + "column": "Kolom", + "color": "Kleur", + "panel-settings": "Paneel instellingen", + "background-color": "Achtergrondkleur", + "gpio-switches": "GPIO-schakelaars", + "no-gpio-switches": "Geen GPIO-schakelaars geconfigureerd", + "add-gpio-switch": "GPIO-schakelaar toevoegen", + "gpio-status-request": "GPIO-statusaanvraag", + "method-name": "Naam van de methode", + "method-body": "Methode lichaam", + "gpio-status-change-request": "Aanvraag voor wijziging van GPIO-status", + "parse-gpio-status-function": "GPIO-statusfunctie parseren", + "gpio-leds": "GPIO-leds", + "no-gpio-leds": "Geen GPIO-leds geconfigureerd", + "add-gpio-led": "GPIO-led toevoegen" + }, + "html-card": { + "html": ".HTML", + "css": ".CSS" + }, + "input-widgets": { + "attribute-not-allowed": "Attribuutparameter kan niet worden gebruikt in deze widget", + "blocked-location": "Geolocatie is geblokkeerd in uw browser", + "claim-device": "Device claimen", + "claim-failed": "Kan het device niet claimen!", + "claim-not-found": "Device niet gevonden!", + "claim-successful": "Device is succesvol geclaimd!", + "date": "Datum", + "device-name": "Naam van het device", + "device-name-required": "Device naam is vereist", + "discard-changes": "Wijzigingen negeren", + "entity-attribute-required": "Entiteitskenmerk is vereist", + "entity-coordinate-required": "Beide velden, lengte- en breedtegraad, zijn verplicht", + "entity-timeseries-required": "Timeseries van entiteiten zijn vereist", + "get-location": "Huidige locatie ophalen", + "invalid-date": "Ongeldige datum", + "latitude": "Breedtegraad", + "longitude": "Lengtegraad", + "min-value-error": "Minimale waarde is {{value}}", + "max-value-error": "Maximale waarde is {{value}}", + "not-allowed-entity": "Geselecteerde entiteit kan geen gedeelde attributen hebben", + "no-attribute-selected": "Er is geen attribuut geselecteerd", + "no-datakey-selected": "Er is geen datakey geselecteerd", + "no-coordinate-specified": "Datakey voor lengte- en breedtegraad is niet opgegeven", + "no-entity-selected": "Geen entiteit geselecteerd", + "no-image": "Geen afbeelding", + "no-support-geolocation": "Uw browser ondersteunt geen geolocatie", + "no-support-web-camera": "Uw browser ondersteunt geen camera's", + "enable-https-use-widget": "Schakel HTTPS in om deze widget te gebruiken", + "no-found-your-camera": "Kan je camera niet vinden", + "no-permission-camera": "Toestemming is geweigerd door de gebruiker / Deze site heeft geen toestemming om de camera te gebruiken", + "no-timeseries-selected": "Geen tijdreeks geselecteerd", + "secret-key": "Geheime sleutel", + "secret-key-required": "Geheime sleutel is vereist", + "switch-attribute-value": "Entiteitskenmerkwaarde wijzigen", + "switch-camera": "Wissel van camera", + "switch-timeseries-value": "Tijdreekswaarde van entiteit wijzigen", + "take-photo": "Maak een foto", + "time": "Tijd", + "timeseries-not-allowed": "Timeseries parameter kan niet worden gebruikt in deze widget", + "update-failed": "Update mislukt", + "update-successful": "Update geslaagd", + "update-attribute": "Attribuut bijwerken", + "update-timeseries": "Timeseries bijwerken", + "value": "Waarde", + "general-settings": "Algemene instellingen", + "widget-title": "Titel van de widget", + "claim-button-label": "Knoplabel claimen", + "show-secret-key-field": "Toon 'Geheime sleutel' invoerveld", + "labels-settings": "Labels instellingen", + "show-labels": "Labels weergeven", + "device-name-label": "Label voor invoerveld device naam", + "secret-key-label": "Label voor het invoerveld van de geheime sleutel", + "messages-settings": "Instellingen voor berichten", + "claim-device-success-message": "Sms-bericht van succesvolle claiming van device", + "claim-device-not-found-message": "Sms wanneer device niet gevonden", + "claim-device-failed-message": "Sms-bericht van geclaimd device", + "claim-device-name-required-message": "Foutbericht 'Device naam vereist'", + "claim-device-secret-key-required-message": "Foutmelding 'Geheime sleutel vereist'", + "relations-settings": "Instellingen voor relaties", + "relate-device-to-state-entity": "Device relateren aan de entiteit met de huidige status", + "relate-direction": "Richting relateren", + "relate-direction-from": "Van", + "relate-direction-to": "Aan", + "relation-type": "Relatie type", + "show-label": "Etiket weergeven", + "label": "Etiket", + "required": "Vereist", + "required-error-message": "Foutmelding 'Vereist'", + "show-result-message": "Resultaatbericht weergeven", + "integer-field-settings": "Instellingen voor velden met gehele getallen", + "min-value": "Min waarde", + "max-value": "Maximale waarde", + "double-field-settings": "Dubbele veldinstellingen", + "text-field-settings": "Instellingen voor tekstvelden", + "min-length": "Min lengte", + "max-length": "Maximale lengte", + "checkbox-settings": "Selectievakjes instellingen", + "true-label": "Gecontroleerd etiket", + "false-label": "Onaangevinkt etiket", + "image-input-settings": "Instellingen voor beeldinvoer", + "display-preview": "Voorbeeld weergeven", + "display-clear-button": "Knop Wissen weergeven", + "display-apply-button": "Knop Toepassen weergeven", + "display-discard-button": "Knop voor weggooien weergeven", + "datetime-field-settings": "Instellingen voor datum-/tijdvelden", + "display-time-input": "Tijdinvoer weergeven", + "latitude-key-name": "Naam van breedtegraad-sleutel", + "longitude-key-name": "Lengtegraad sleutelnaam", + "show-get-location-button": "Toon knop 'Huidige locatie ophalen'", + "use-high-accuracy": "Gebruik hoge nauwkeurigheid", + "location-fields-settings": "Instellingen voor locatievelden", + "latitude-label": "Label voor breedtegraad", + "longitude-label": "Label voor lengtegraad", + "input-fields-alignment": "Uitlijning van invoervelden", + "input-fields-alignment-column": "Kolom (standaard)", + "input-fields-alignment-row": "Rijen", + "latitude-field-required": "Breedtegraadveld vereist", + "longitude-field-required": "Lengtegraadveld vereist", + "attribute-settings": "Attribuut instellingen", + "widget-mode": "Widget-modus", + "widget-mode-update-attribute": "Attribuut bijwerken", + "widget-mode-update-timeseries": "Timeseries bijwerken", + "attribute-scope": "Bereik van attribuut", + "attribute-scope-server": "Server-attribuut", + "attribute-scope-shared": "Gedeeld attribuut", + "value-required": "Vereiste waarde", + "image-settings": "Beeldinstellingen", + "image-format": "Beeldformaat", + "image-format-jpeg": ".JPEG", + "image-format-png": ".PNG", + "image-format-webp": ".WEBP", + "image-quality": "Beeldkwaliteit die compressie met verlies gebruikt, zoals jpeg en webp", + "max-image-width": "Maximale afbeeldingsbreedte", + "max-image-height": "Maximale afbeeldingshoogte", + "action-buttons": "Actieknoppen", + "show-action-buttons": "Actieknoppen weergeven", + "update-all-values": "Werk alle waarden bij, niet alleen gewijzigd", + "save-button-label": "Label met de knop 'OPSLAAN'", + "reset-button-label": "Knoplabel 'ONGEDAAN MAKEN'", + "group-settings": "Groepsinstellingen", + "show-group-title": "Titel weergeven voor groep velden, gerelateerd aan verschillende entiteiten", + "group-title": "Titel van de groep", + "fields-alignment": "Uitlijning van velden", + "fields-alignment-row": "Rij (standaard)", + "fields-alignment-column": "Kolom", + "fields-in-row": "Aantal velden in de rij", + "option-value": "Waarde (schrijf 'null' voor de optie leeg maken)", + "option-label": "Etiket", + "hide-input-field": "Invoerveld verbergen", + "datakey-type": "Type datakey", + "datakey-type-server": "Serverkenmerk (standaard)", + "datakey-type-shared": "Gedeeld attribuut", + "datakey-type-timeseries": "Timeseries", + "datakey-value-type": "Waardetype Datakey", + "datakey-value-type-string": "Snaar", + "datakey-value-type-double": "Dubbel", + "datakey-value-type-integer": "Geheel getal", + "datakey-value-type-json": "JSON", + "datakey-value-type-boolean-checkbox": "Booleaans (selectievakje)", + "datakey-value-type-boolean-switch": "Booleaans (schakelaar)", + "datakey-value-type-date-time": "Datum en tijd", + "datakey-value-type-date": "Datum", + "datakey-value-type-time": "Tijd", + "datakey-value-type-select": "Selecteren", + "value-is-required": "Waarde is vereist", + "ability-to-edit-attribute": "Mogelijkheid om attribuut te bewerken", + "ability-to-edit-attribute-editable": "Bewerkbaar (standaard)", + "ability-to-edit-attribute-disabled": "Invalide", + "ability-to-edit-attribute-readonly": "Alleen-lezen", + "disable-on-datakey-name": "Uitschakelen bij valse waarde van een andere datakey (geef de naam van de datakey op)", + "slide-toggle-settings": "Instellingen voor schuifschakelaar", + "slide-toggle-label-position": "Schuif de positie van het label omschakelen", + "slide-toggle-label-position-after": "Na", + "slide-toggle-label-position-before": "Voor", + "select-options": "Opties selecteren", + "no-select-options": "Geen geselecteerde opties geconfigureerd", + "add-select-option": "Selectieoptie toevoegen", + "numeric-field-settings": "Instellingen voor numerieke velden", + "step-interval": "Stapinterval tussen waarden", + "error-messages": "Foutberichten", + "min-value-error-message": "Foutmelding 'Min. waarde'", + "max-value-error-message": "Foutmelding 'Maximale waarde'", + "invalid-date-error-message": "Foutmelding 'Ongeldige datum'", + "invalid-JSON-error-message": "Foutbericht 'Ongeldige JSON'", + "icon-settings": "Icoon instellingen", + "dialog-editor-settings": "Instellingen van de dialoogeditor", + "use-custom-icon": "Aangepast pictogram gebruiken", + "input-cell-icon": "Pictogram om weer te geven vóór invoercel", + "value-conversion-settings": "Instellingen voor waardeconversie", + "get-value-settings": "Waarde-instellingen ophalen", + "use-get-value-function": "De getValue-functie gebruiken", + "get-value-function": "getValue, functie", + "set-value-settings": "Waarde-instellingen instellen", + "use-set-value-function": "Gebruik de setValue-functie", + "set-value-function": "setValue-functie", + "json-invalid": "JSON-waarde heeft een ongeldige indeling", + "title": "Titel", + "cancel-button-label": "Label met de knop 'Annuleren'" + }, + "invalid-qr-code-text": "Ongeldige invoertekst voor QR-code. Invoer moet een tekenreekstype hebben", + "qr-code": { + "use-qr-code-text-function": "Gebruik de tekstfunctie van de QR-code", + "qr-code-text-pattern": "Tekstpatroon QR-code (bijv. '${entityName} | ${keyName} - wat tekst.')", + "qr-code-text-pattern-hint": "Het tekstpatroon van de QR-code gebruikt de waarde van de eerst gevonden sleutel in de entiteiten in de entiteitsalias.", + "qr-code-text-pattern-required": "Tekstpatroon QR-code is vereist.", + "qr-code-text-function": "Tekstfunctie QR-code" + }, + "label-widget": { + "label-pattern": "Patroon", + "label-pattern-hint": "Tip: bijv. 'Text <span style=\"color: #000;\">${keyName<span style=\"color: #000;\">} eenheden.' of <span style=\"color: #000;\">${#<key index><span style=\"color: #000;\">} eenheden'", + "label-pattern-required": "Patroon is vereist", + "label-position": "Positie (percentage ten opzichte van achtergrond)", + "x-pos": "X", + "y-pos": "Y", + "background-color": "Achtergrondkleur", + "font-settings": "Lettertype-instellingen", + "background-image": "Achtergrondafbeelding", + "labels": "Etiketten", + "no-labels": "Geen labels geconfigureerd", + "add-label": "Label toevoegen" + }, + "navigation": { + "title": "Titel", + "navigation-path": "Navigatie pad", + "filter-type": "Filter type", + "filter-type-all": "Alle artikelen", + "filter-type-include": "Items opnemen", + "filter-type-exclude": "Items uitsluiten", + "items": "Items", + "enter-urls-to-filter": "Voer url's in om te filteren..." + }, + "persistent-table": { + "rpc-id": "RPC-ID", + "message-type": "Soort bericht", + "method": "Methode", + "params": "Params", + "created-time": "Gecreëerde tijd", + "expiration-time": "Vervaltijd", + "retries": "Pogingen", + "status": "Status", + "filter": "Filter", + "refresh": "Opfrissen", + "add": "RPC-aanvraag toevoegen", + "details": "Details", + "delete": "Verwijderen", + "delete-request-title": "Persistent RPC-verzoek verwijderen", + "delete-request-text": "Weet je zeker dat je een verzoek wilt verwijderen?", + "details-title": "Details RPC-ID:", + "additional-info": "Aanvullende informatie", + "response": "Antwoord", + "any-status": "Elke status", + "rpc-status-list": "RPC-statuslijst", + "no-request-prompt": "Geen verzoek om weer te geven", + "send-request": "Aanvraag versturen", + "add-title": "Permanente RPC-aanvraag maken", + "method-error": "Methode is vereist.", + "timeout-error": "De minimale time-outwaarde is 5000 (5 seconden).", + "white-space-error": "Witruimte is niet toegestaan.", + "rpc-status": { + "QUEUED": "WACHTRIJ", + "SENT": "VERZONDEN", + "DELIVERED": "GELEVERD", + "SUCCESSFUL": "SUCCESVOL", + "TIMEOUT": "TIMEOUT", + "EXPIRED": "VERVALLEN", + "FAILED": "MISLUKT" + }, + "rpc-search-status-all": "ALLE", + "message-types": { + "false": "Twee richtingen", + "true": "One-way" + }, + "general-settings": "Algemene instellingen", + "enable-filter": "Filter inschakelen", + "enable-sticky-header": "Koptekst weergeven tijdens scrollen", + "enable-sticky-action": "Kolom Acties weergeven tijdens het scrollen", + "display-request-details": "Aanvraaggegevens weergeven", + "allow-send-request": "Sta het verzenden van RPC-verzoek toe", + "allow-delete-request": "Verwijderingsverzoek toestaan", + "columns-settings": "Instellingen voor kolommen", + "display-columns": "Weer te geven kolommen", + "column": "Kolom", + "no-columns-found": "Geen kolommen gevonden", + "no-columns-matching": "'{{column}}' niet gevonden." + }, + "rpc": { + "value-settings": "Waarde-instellingen", + "initial-value": "Beginwaarde", + "retrieve-value-settings": "Aan/uit-waarde-instellingen ophalen", + "retrieve-value-method": "Waarde ophalen met behulp van methode", + "retrieve-value-method-none": "Niet ophalen", + "retrieve-value-method-rpc": "RPC aanroepen om waardemethode op te halen", + "retrieve-value-method-attribute": "Abonneren op attribuut", + "retrieve-value-method-timeseries": "Schrijf je in voor tijdseries", + "attribute-value-key": "Attribuut sleutel", + "timeseries-value-key": "Tijdreeks-toets", + "get-value-method": "RPC get value methode", + "parse-value-function": "Functie voor het parseren van waarden", + "update-value-settings": "Waarde-instellingen bijwerken", + "set-value-method": "RPC-methode voor ingestelde waarden", + "convert-value-function": "Functie Waarde converteren", + "rpc-settings": "RPC-instellingen", + "request-timeout": "Time-out voor RPC-aanvraag (ms)", + "persistent-rpc-settings": "Persistente RPC-instellingen", + "request-persistent": "RPC-aanvraag persistent", + "persistent-polling-interval": "Pollinginterval (ms) om persistente RPC-opdrachtrespons te krijgen", + "common-settings": "Algemene instellingen", + "switch-title": "Titel wijzigen", + "show-on-off-labels": "Aan/uit-labels weergeven", + "slide-toggle-label": "Schuif toggle label", + "label-position": "Positie van het etiket", + "label-position-before": "Voor", + "label-position-after": "Na", + "slider-color": "Kleur schuifregelaar", + "slider-color-primary": "Primair", + "slider-color-accent": "Accent", + "slider-color-warn": "Waarschuwen", + "button-style": "Knop stijl", + "button-raised": "Verhoogde knop", + "button-primary": "Primaire kleur", + "button-background-color": "Achtergrondkleur knop", + "button-text-color": "Tekstkleur knop", + "widget-title": "Titel van de widget", + "button-label": "Knop label", + "device-attribute-scope": "Bereik van device attributen", + "server-attribute": "Server-attribuut", + "shared-attribute": "Gedeeld attribuut", + "device-attribute-parameters": "Parameters voor device attributen", + "is-one-way-command": "Is eenrichtingscommando", + "rpc-method": "RPC-methode", + "rpc-method-params": "Params van de RPC-methode", + "show-rpc-error": "Fout bij het uitvoeren van RPC-opdrachten weergeven", + "led-title": "LED-titel", + "led-color": "LED-kleur", + "check-status-settings": "Statusinstellingen controleren", + "perform-rpc-status-check": "Voer de statuscontrole van het RPC-device uit", + "retrieve-led-status-value-method": "Leidsstatuswaarde ophalen met behulp van methode", + "led-status-value-attribute": "Apparaatkenmerk met led-statuswaarde", + "led-status-value-timeseries": "Tijdreeks van het device met led-statuswaarde", + "check-status-method": "RPC-methode voor het controleren van de apparaatstatus", + "parse-led-status-value-function": "Led-statuswaardefunctie parseren", + "knob-title": "Titel van de knop", + "min-value": "Minimumwaarde", + "max-value": "Maximale waarde" + }, + "maps": { + "select-entity": "Entiteit selecteren", + "select-entity-hint": "Tip: klik na selectie op de kaart om de positie in te stellen", + "tooltips": { + "placeMarker": "Klik om de entiteit '{{entityName}}' te plaatsen", + "firstVertex": "Polygoon voor '{{entityName}}': klik om eerste punt te plaatsen", + "firstVertex-cut": "Klik om het eerste punt te plaatsen", + "continueLine": "Polygoon voor '{{entityName}}': klik om verder te tekenen", + "continueLine-cut": "Klik om door te gaan met tekenen", + "finishLine": "Klik op een bestaande markering om te voltooien", + "finishPoly": "Polygoon voor '{{entityName}}': klik op de eerste markering om te voltooien en op te slaan", + "finishPoly-cut": "Klik op de eerste markering om te voltooien en op te slaan", + "finishRect": "Polygoon voor '{{entityName}}': klik om te voltooien en op te slaan", + "startCircle": "Cirkel voor '{{entityName}}': klik om het midden van de cirkel te plaatsen", + "finishCircle": "Cirkel voor '{{entityName}}': klik om cirkel te voltooien", + "placeCircleMarker": "Klik om de cirkelmarkering te plaatsen" + }, + "actions": { + "finish": "Fins", + "cancel": "Annuleren", + "removeLastVertex": "Laatste punt verwijderen" + }, + "buttonTitles": { + "drawMarkerButton": "Entiteit plaatsen", + "drawPolyButton": "Polygoon maken", + "drawLineButton": "Polylijn maken", + "drawCircleButton": "Cirkel maken", + "drawRectButton": "Rechthoek maken", + "editButton": "Modus bewerken", + "dragButton": "Drag-drop-modus", + "cutButton": "Snijd polygoongebied", + "deleteButton": "Verwijderen", + "drawCircleMarkerButton": "Cirkelmarkering maken", + "rotateButton": "Polygoon roteren" + }, + "map-provider-settings": "Instellingen van kaartprovider", + "map-provider": "Kaart provider", + "map-provider-google": "Google kaarten", + "map-provider-openstreet": "OpenStreet-kaarten", + "map-provider-here": "HERE kaarten", + "map-provider-image": "Afbeelding kaart", + "map-provider-tencent": "Tencent kaarten", + "openstreet-provider": "OpenStreet-kaartprovider", + "openstreet-provider-mapnik": "OpenStreetMap.Mapnik (standaard)", + "openstreet-provider-hot": "OpenStreetMap.HOT", + "openstreet-provider-esri-street": "Esri.WorldStreetMap", + "openstreet-provider-esri-topo": "Esri.WorldTopoMap", + "openstreet-provider-esri-imagery": "Esri.WorldImagery", + "openstreet-provider-cartodb-positron": "CartoDB.Positron", + "openstreet-provider-cartodb-dark-matter": "CartoDB.DarkMatter", + "use-custom-provider": "Aangepaste provider gebruiken", + "custom-provider-tile-url": "Aangepaste tegel-URL van provider", + "google-maps-api-key": "API-sleutel voor Google Maps", + "default-map-type": "Standaard kaarttype", + "google-map-type-roadmap": "Stappenplan", + "google-map-type-satelite": "Satelliet", + "google-map-type-hybrid": "Hybride", + "google-map-type-terrain": "Terrein", + "map-layer": "Kaart laag", + "here-map-normal-day": "HERE.normalDay (standaard)", + "here-map-normal-night": "HIER.normalNight", + "here-map-hybrid-day": "HIER.hybridDay", + "here-map-terrain-day": "HIER.terreinDag", + "credentials": "Geloofsbrief", + "here-app-id": "HERE-app-id", + "here-app-code": "HERE-app-code", + "here-api-key": "HERE API-sleutel", + "here-use-new-version-api-3": "API-versie 3 gebruiken", + "tencent-maps-api-key": "API-sleutel voor Tencent Maps", + "tencent-map-type-roadmap": "Stappenplan", + "tencent-map-type-satelite": "Satelliet", + "tencent-map-type-hybrid": "Hybride", + "image-map-background": "De achtergrond van de afbeeldingskaart", + "image-map-background-from-entity-attribute": "Neem de achtergrond van de afbeeldingstoewijzing van het entiteitskenmerk", + "image-url-source-entity-alias": "Alias van de bronentiteit van de afbeeldings-URL", + "image-url-source-entity-attribute": "Entiteitskenmerk bronentiteit afbeeldings-URL", + "common-map-settings": "Algemene kaartinstellingen", + "x-pos-key-name": "Naam van de X-positiesleutel", + "y-pos-key-name": "Y-positie sleutelnaam", + "latitude-key-name": "Naam van breedtegraad-sleutel", + "longitude-key-name": "Lengtegraad sleutelnaam", + "default-map-zoom-level": "Standaard zoomniveau voor kaart (0 - 20)", + "default-map-center-position": "Standaard middenpositie op de kaart (0,0)", + "disable-scroll-zooming": "Scrollen uitschakelen", + "disable-double-click-zooming": "Dubbelklikken uitschakelen", + "disable-zoom-control-buttons": "Zoombedieningsknoppen uitschakelen", + "fit-map-bounds": "Pas kaartgrenzen aan om alle markeringen te bedekken", + "use-default-map-center-position": "Gebruik de standaardpositie in het midden van de kaart", + "entities-limit": "Limiet van te laden entiteiten", + "markers-settings": "Instellingen voor markeringen", + "marker-offset-x": "Markering X verschuiving ten opzichte van positie vermenigvuldigd met markeringsbreedte", + "marker-offset-y": "Markering Y-verschuiving ten opzichte van positie vermenigvuldigd met markeringshoogte", + "position-function": "Positieconversiefunctie, moet x,y-coördinaten retourneren als dubbel van 0 tot 1 elk", + "draggable-marker": "Versleepbare markering", + "label": "Etiket", + "show-label": "Etiket weergeven", + "use-label-function": "Labelfunctie gebruiken", + "label-pattern": "Label (patroonvoorbeelden: '${entityName}', '${entityName}: (Tekst ${keyName} eenheden.)' )", + "label-function": "Label functie", + "tooltip": "Tooltip", + "show-tooltip": "Tooltip weergeven", + "show-tooltip-action": "Actie voor het weergeven van de knopinfo", + "show-tooltip-action-click": "Knopinfo weergeven bij klikken (Standaard)", + "show-tooltip-action-hover": "Knopinfo weergeven bij aanwijzen", + "auto-close-tooltips": "Tooltips voor automatisch sluiten", + "use-tooltip-function": "Tooltip-functie gebruiken", + "tooltip-pattern": "Tooltip (bijv. 'Tekst ${keyName} eenheden.' of Linktekst')", + "tooltip-function": "Tooltip-functie", + "tooltip-offset-x": "Tooltip X-verschuiving ten opzichte van markeringsanker vermenigvuldigd met markeringsbreedte", + "tooltip-offset-y": "Tooltip Y-verschuiving ten opzichte van markeringsanker vermenigvuldigd met markeringshoogte", + "color": "Kleur", + "use-color-function": "Kleurfunctie gebruiken", + "color-function": "Kleur functie", + "marker-image": "Afbeelding markeren", + "use-marker-image-function": "Gebruik de functie voor markeringsafbeeldingen", + "custom-marker-image": "Aangepaste markeringsafbeelding", + "custom-marker-image-size": "Afbeeldingsgrootte aangepaste markering (px)", + "marker-image-function": "Marker image functie", + "marker-images": "Marker afbeeldingen", + "polygon-settings": "Polygoon-instellingen", + "show-polygon": "Polygoon weergeven", + "polygon-key-name": "Naam van de Polygoonsleutel", + "enable-polygon-edit": "Polygoonbewerking inschakelen", + "polygon-label": "Polygoon etiket", + "show-polygon-label": "Polygoonlabel weergeven", + "use-polygon-label-function": "Polygoonlabelfunctie gebruiken", + "polygon-label-pattern": "Polygoonlabel (patroonvoorbeelden: '${entityName}', '${entityName}: (Tekst ${keyName} eenheden.)' )", + "polygon-label-function": "Polygoon label functie", + "polygon-tooltip": "Tooltip voor polygoon", + "show-polygon-tooltip": "Polygoon knopinfo weergeven", + "auto-close-polygon-tooltips": "Tooltips voor polygoon automatisch sluiten", + "use-polygon-tooltip-function": "Polygoon-tooltipfunctie gebruiken", + "polygon-tooltip-pattern": "Tooltip (bijv. 'Tekst ${keyName} eenheden.' of Linktekst')", + "polygon-tooltip-function": "Polygoon tooltip functie", + "polygon-color": "Polygoon kleur", + "polygon-opacity": "Dekking van polygoon", + "use-polygon-color-function": "Polygoonkleurfunctie gebruiken", + "polygon-color-function": "Polygoon kleur functie", + "polygon-stroke": "Polygoon lijn", + "stroke-color": "Kleur van de lijn", + "stroke-opacity": "Dekking van de beroerte", + "stroke-weight": "Het gewicht van de slag", + "use-polygon-stroke-color-function": "Gebruik de kleurfunctie van de polygoonlijn", + "polygon-stroke-color-function": "Kleurfunctie voor polygoonlijnen", + "circle-settings": "Cirkel-instellingen", + "show-circle": "Toon cirkel", + "circle-key-name": "Naam van de cirkelsleutel", + "enable-circle-edit": "Cirkelbewerking inschakelen", + "circle-label": "Het etiket van de cirkel", + "show-circle-label": "Cirkellabel weergeven", + "use-circle-label-function": "Gebruik de cirkellabelfunctie", + "circle-label-pattern": "Cirkellabel (patroonvoorbeelden: '${entityName}', '${entityName}: (Tekst ${keyName} eenheden.)' )", + "circle-label-function": "Cirkellabel-functie", + "circle-tooltip": "Tooltip voor cirkelen", + "show-circle-tooltip": "Knopinfo cirkel weergeven", + "auto-close-circle-tooltips": "Tooltips voor automatisch sluiten van cirkels", + "use-circle-tooltip-function": "Gebruik de cirkel-tooltip-functie", + "circle-tooltip-pattern": "Tooltip (bijv. 'Tekst ${keyName} eenheden.' of Linktekst')", + "circle-tooltip-function": "Cirkel tooltip functie", + "circle-fill-color": "Vulkleur cirkel", + "circle-fill-color-opacity": "Dekking van de vulkleur van de cirkel", + "use-circle-fill-color-function": "Gebruik de functie voor het vullen van cirkels", + "circle-fill-color-function": "Cirkelvulkleurfunctie", + "circle-stroke": "De slag van de cirkel", + "use-circle-stroke-color-function": "Gebruik de kleurfunctie van de cirkelstreek", + "circle-stroke-color-function": "Cirkellijn kleurfunctie", + "markers-clustering-settings": "Instellingen voor het clusteren van markeringen", + "use-map-markers-clustering": "Clustering van kaartmarkeringen gebruiken", + "zoom-on-cluster-click": "Inzoomen bij het klikken op een cluster", + "max-cluster-zoom": "Het maximale zoomniveau wanneer een markering deel kan uitmaken van een cluster (0 - 18)", + "max-cluster-radius-pixels": "Maximale straal die een cluster in pixels bestrijkt", + "cluster-zoom-animation": "Animatie weergeven op markeringen bij het zoomen", + "show-markers-bounds-on-cluster-mouse-over": "De grenzen van markeringen weergeven wanneer u de muisaanwijzer op een cluster plaatst", + "spiderfy-max-zoom-level": "Spiderfy op het maximale zoomniveau (om alle clustermarkeringen te zien)", + "load-optimization": "Optimalisatie van de belasting", + "cluster-chunked-loading": "Gebruik chunks om markeringen toe te voegen, zodat de pagina niet vastloopt", + "cluster-markers-lazy-load": "Gebruik lazy load voor het toevoegen van markeringen", + "editor-settings": "Editor-instellingen", + "enable-snapping": "Uitlijnen op andere punten inschakelen voor nauwkeurig tekenen", + "init-draggable-mode": "Kaart initialiseren in versleepbare modus", + "hide-all-edit-buttons": "Alle bedieningsknoppen voor bewerken verbergen", + "hide-draw-buttons": "Tekenknoppen verbergen", + "hide-edit-buttons": "Bewerkingsknoppen verbergen", + "hide-remove-button": "Verwijderknop verbergen", + "route-map-settings": "Routekaartinstellingen", + "trip-animation-settings": "Instellingen voor reisanimatie", + "normalization-step": "Normalisatie gegevensstap (ms)", + "tooltip-background-color": "Achtergrondkleur tooltip", + "tooltip-font-color": "Tekstkleur van knopinfo", + "tooltip-opacity": "Tooltip dekking (0-1)", + "auto-close-tooltip": "Tooltip voor automatisch sluiten", + "rotation-angle": "Stel extra draaihoek in voor marker (graden)", + "path-settings": "Pad-instellingen", + "path-color": "De kleur van het pad", + "use-path-color-function": "Padkleurfunctie gebruiken", + "path-color-function": "Padkleurfunctie", + "path-decorator": "Pad decorateur", + "use-path-decorator": "Gebruik paddecorateur", + "decorator-symbol": "Het symbool van de decorateur", + "decorator-symbol-arrow-head": "Pijl", + "decorator-symbol-dash": "Scheutje", + "decorator-symbol-size": "Grootte decorateur symbool (px)", + "use-path-decorator-custom-color": "Gebruik de aangepaste kleur van de paddecorateur", + "decorator-custom-color": "Decorateur aangepaste kleur", + "decorator-offset": "Decorateur offset", + "end-decorator-offset": "Einddecorateur offset", + "decorator-repeat": "Decorateur herhalen", + "points-settings": "Punten instellingen", + "show-points": "Toon punten", + "point-color": "Kleur van de punt", + "point-size": "Punt grootte (px)", + "use-point-color-function": "Puntkleurfunctie gebruiken", + "point-color-function": "Puntkleurfunctie", + "use-point-as-anchor": "Punt gebruiken als anker", + "point-as-anchor-function": "Aanwijzen als ankerfunctie", + "independent-point-tooltip": "Tooltip voor onafhankelijk punt", + "clustering-markers": "Markeringen clusteren", + "use-icon-create-function": "Gebruik de kleurfunctie van markeringen", + "marker-color-function": "Marker kleur functie" + }, + "markdown": { + "use-markdown-text-function": "Markdown/HTML-waardefunctie gebruiken", + "markdown-text-function": "Markdown/HTML-waarde functie", + "markdown-text-pattern": "Markdown/HTML-patroon (markdown of HTML met variabelen, bijvoorbeeld '${entityName} of ${keyName} - wat tekst.')", + "apply-default-markdown-style": "Standaardstijl voor afprijzing toepassen", + "markdown-css": "Afprijzing/HTML CSS" + }, + "simple-card": { + "label-position": "Positie van het etiket", + "label-position-left": "Links", + "label-position-top": "Boven" + }, + "table": { + "common-table-settings": "Algemene tabelinstellingen", + "enable-search": "Zoeken inschakelen", + "enable-sticky-header": "Koptekst altijd weergeven", + "enable-sticky-action": "Kolom Acties altijd weergeven", + "hidden-cell-button-display-mode": "Weergavemodus voor verborgen celknopacties", + "show-empty-space-hidden-action": "Lege ruimte weergeven in plaats van verborgen celknopactie", + "dont-reserve-space-hidden-action": "Reserveer geen ruimte voor verborgen actieknoppen", + "display-timestamp": "Tijdstempelkolom weergeven", + "display-milliseconds": "Tijdstempel milliseconden weergeven", + "display-pagination": "Paginering weergeven", + "default-page-size": "Standaard paginaformaat", + "use-entity-label-tab-name": "Entiteitslabel gebruiken in de naam van het tabblad", + "hide-empty-lines": "Lege regels verbergen", + "row-style": "Rij stijl", + "use-row-style-function": "Rijstijlfunctie gebruiken", + "row-style-function": "Rijstijl functie", + "cell-style": "Cel stijl", + "use-cell-style-function": "Celstijlfunctie gebruiken", + "cell-style-function": "Functie voor celstijl", + "cell-content": "Celinhoud", + "use-cell-content-function": "De functie voor celinhoud gebruiken", + "cell-content-function": "Functie voor celinhoud", + "show-latest-data-column": "Kolom met meest recente gegevens weergeven", + "latest-data-column-order": "Meest recente volgorde van gegevenskolommen", + "entities-table-title": "Titel van de tabel Entiteiten", + "enable-select-column-display": "Schakel geselecteerde kolommen in om weer te geven", + "display-entity-name": "Kolom met entiteitsnaam weergeven", + "entity-name-column-title": "Kolomtitel van entiteitsnaam", + "display-entity-label": "Kolom met entiteitslabel weergeven", + "entity-label-column-title": "Kolomtitel van entiteitslabel", + "display-entity-type": "Kolom met entiteitstype weergeven", + "default-sort-order": "Standaard sorteervolgorde", + "custom-title": "Aangepaste kopteksttitel", + "column-width": "Kolombreedte (px of %)", + "default-column-visibility": "Standaard zichtbaarheid van kolommen", + "column-visibility-visible": "Zichtbaar", + "column-visibility-hidden": "Verborgen", + "column-visibility-hidden-mobile": "Verborgen in mobiele modus", + "column-selection-to-display": "Kolomselectie in 'Weer te geven kolommen'", + "column-selection-to-display-enabled": "Ingeschakeld", + "column-selection-to-display-disabled": "Invalide", + "column-export-option": "Kolom opnemen in export", + "column-export-option-always": "Altijd", + "column-export-option-only-visible": "Alleen als de kolom zichtbaar is", + "column-export-option-never": "Nooit", + "alarms-table-title": "Titel van de tabel Alarmen", + "enable-alarms-selection": "Selectie van alarmen inschakelen", + "enable-alarms-search": "Zoeken naar alarmen inschakelen", + "enable-alarm-filter": "Alarmfilter inschakelen", + "display-alarm-details": "Alarmdetails weergeven", + "allow-alarms-ack": "Alarmbevestiging toestaan", + "allow-alarms-clear": "Laat alarmen wissen", + "display-alarm-activity": "Alarmactiviteit weergeven", + "allow-alarms-assign": "Toewijzing van alarmen toestaan", + "blob-entities-table-title": "Titel van de tabel met blobentiteiten", + "display-created-time": "Aangemaakte tijdkolom weergeven", + "display-type": "Kolom Weergavetype", + "display-customer": "Klantkolom weergeven", + "no-data-display-message": "Alternatief bericht 'Geen gegevens om weer te geven'", + "force-default-blob-entity-type": "Standaard blob-entiteitstype afdwingen", + "scheduler-events-table-title": "Titel van de tabel met scheduler events", + "force-default-event-type": "Standaardgebeurtenistype afdwingen" + }, + "scheduler": { + "enabled-scheduler-event-views": "Weergaven van scheduler events ingeschakeld", + "enabled-scheduler-event-views-both": "Beide", + "enabled-scheduler-event-views-list": "Alleen lijstweergave", + "enabled-scheduler-event-views-calendar": "Alleen agendaweergave", + "display-name": "Weergavenaam", + "type-name": "Typ naam", + "display-originator-select": "Aansteller van entiteit weergeven", + "display-message-type-select": "Berichttype weergeven selecteren", + "display-metadata-table": "Tabel met metagegevens van berichten weergeven", + "configuration-html-template": "Configuratie HTML-sjabloon", + "custom-event-types": "Aangepaste gebeurtenistypen", + "no-custom-event-types": "Geen aangepaste gebeurtenistypen geconfigureerd", + "add-custom-event-type": "Aangepast gebeurtenistype toevoegen" + }, + "value-source": { + "value-source": "Waardebron", + "predefined-value": "Vooraf gedefinieerde waarde", + "entity-attribute": "Waarde ontleend aan entiteitskenmerk", + "value": "Waarde", + "source-entity-alias": "Alias van bronentiteit", + "source-entity-attribute": "Kenmerk van bronentiteit" + }, + "widget-font": { + "font-family": "Lettertype familie", + "size": "Grootte", + "relative-font-size": "Relatieve lettergrootte (procenten)", + "font-style": "Stijl", + "font-style-normal": "Normaal", + "font-style-italic": "Cursief", + "font-style-oblique": "Schuin", + "font-weight": "Gewicht", + "font-weight-normal": "Normaal", + "font-weight-bold": "Bold", + "font-weight-bolder": "Bolder", + "font-weight-lighter": "Lichter", + "color": "Kleur", + "shadow-color": "De kleur van de schaduw" + }, + "home": { + "no-data-available": "Geen gegevens beschikbaar" + }, + "system-info": { + "cpu": "CPU", + "ram": "RAM", + "disk": "Schijf", + "cpu-warning-text": "Hoog CPU-gebruik. Optimaliseer de systeemprestaties om systeemstoringen te voorkomen.", + "cpu-critical-text": "Kritisch hoog CPU-gebruik. Optimaliseer de systeemprestaties om systeemstoringen te voorkomen.", + "ram-warning-text": "Heeft bijna geen RAM-geheugen meer. Om systeemstoringen te voorkomen, optimaliseert u de systeemprestaties of vergroot u de grootte van het RAM-geheugen.", + "ram-critical-text": "Kritisch lage RAM-reserve. Om systeemstoringen te voorkomen, optimaliseert u de systeemprestaties of vergroot u de grootte van het RAM-geheugen.", + "disk-warning-text": "Weinig schijfruimte. Om gegevensverlies te voorkomen, maakt u schijfruimte vrij of breidt u deze uit.", + "disk-critical-text": "Kritisch weinig schijfruimte. Om gegevensverlies te voorkomen, maakt u schijfruimte vrij of breidt u deze uit." + }, + "cluster-info": { + "service-id": "Service-id", + "service-type": "Soort dienst", + "no-data": "Geen gegevens" + }, + "transport-messages": { + "title": "Berichten vervoeren", + "info": "Alle berichten die afkomstig zijn van Devices" + }, + "activity": { + "title": "Activiteit" + }, + "documentation": { + "title": "Documentatie", + "add-link": "Link toevoegen", + "add-link-title": "Documentatiekoppeling toevoegen", + "name": "Naam", + "name-required": "Naam is verplicht.", + "link": "Verbinden", + "link-required": "Link is vereist.", + "columns": "Kolommen" + }, + "quick-links": { + "title": "Snelkoppelingen", + "add-link": "Link toevoegen", + "add-link-title": "Snelkoppeling toevoegen", + "quick-link": "Snelkoppeling", + "quick-link-required": "Snelle koppeling is vereist.", + "no-links-matching": "Er zijn geen links gevonden die overeenkomen met '{{name}}'.", + "columns": "Kolommen" + }, + "recent-dashboards": { + "title": "Dashboards", + "last": "Laatst bekeken", + "starred": "Speelde", + "name": "Naam", + "last-viewed": "Laatst bekeken", + "no-last-viewed-dashboards": "Nog geen laatst bekeken dashboards" + }, + "configured-features": { + "title": "Geconfigureerde functies", + "info": "Status van functies waarvoor configuratie vereist is", + "white-labeling-feature": "White labelling", + "email-feature": "E-mail", + "sms-feature": "SMS", + "slack-feature": "Los", + "oauth2-feature": "OAuth 2", + "2fa-feature": "2FA", + "feature-configured": "Functie is geconfigureerd.\nKlik om in te stellen", + "feature-not-configured": "Functie is niet geconfigureerd.\nKlik om in te stellen" + }, + "version-info": { + "title": "Versie", + "contact-us": "Neem contact met ons op", + "current-version": "Huidige versie", + "current": "Actueel", + "available-version": "Beschikbare versie", + "available": "Beschikbaar", + "upgrade": "Opwaarderen", + "version-is-up-to-date": "Versie is up-to-date" + }, + "license-info": { + "title": "Licentie info", + "view-all": "Alles weergeven", + "license-portal": "Licentie portaal", + "devices-info": "{count} / { max, plural, =0 {∞} andere {#} } Devices", + "assets-info": "{count} / { max, plural, =0 {∞} andere {#} } Assets", + "dashboards-info": "{count} / { max, plural, =0 {∞} andere {#} } Dashboards", + "integrations-info": "{count} / { max, plural, =0 {∞} andere {#} } Integraties", + "community-support": "Ondersteuning van de gemeenschap", + "white-labeling": "White labelling", + "unlimited-datapoints-and-messages": "Onbeperkt aantal datapunten en berichten", + "unlimited-api-calls": "Onbeperkt aantal API-aanroepen" + }, + "usage-info": { + "title": "Gebruik", + "entities": "Entiteiten", + "api-calls": "API-aanroepen" + }, + "functions": { + "title": "Functies", + "pe-feature-tooltip": "Alleen op ThingsBoard\nProfessionele editie", + "switch-to-pe": "Overschakelen naar PE", + "alarms": "Alarmen", + "dashboards": "Dashboards", + "entities-and-relations": "Entiteiten en relaties", + "profiles": "Profielen", + "advanced-features": "Geavanceerde functies", + "notification-center": "Meldingscentrum", + "api-usage": "API-gebruik", + "customers": "Klanten", + "customers-hierarchy": "Hiërarchie van klanten", + "roles-and-permissions": "Rollen en machtigingen", + "groups": "Groepen", + "integrations": "Integraties", + "solution-templates": "Sjablonen voor oplossingen", + "scheduler": "Scheduler", + "white-labeling": "White labelling" + }, + "devices": { + "view-docs": "Documenten bekijken", + "inactive": "Inactief", + "active": "Actief", + "total": "Totaal" + }, + "alarms": { + "critical": "Kritisch", + "assigned-to-me": "Aan mij toegewezen", + "total": "Totaal" + }, + "solution-templates": { + "title": "Sjablonen voor oplossingen", + "prototype-plan": "Prototype plan", + "startup-plan": "Opstart plan" + }, + "getting-started": { + "get-started": "Start", + "finish": "Einde", + "done-welcome-title": "Welkom", + "done-welcome-text": "Je hebt het geweldig gedaan!", + "sys-admin": { + "step1": { + "title": "Tenant en tenantbeheerder maken", + "content": "

Een tenant is een persoon of een organisatie die devices en bedrijfsmiddelen bezit of produceert. De tenant kan meerdere tenantbeheerders, gebruikers, klanten, devices en assets hebben.

De tenantbeheerder kan devices, assets, klanten en dashboards maken en beheren binnen het tenantaccount.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-create-tenant": "Tenant en tenantbeheerder aanmaken" + }, + "step2": { + "title": "Functie configureren: E-mailserver", + "content": "

De configuratie van de e-mailserver is essentieel voor gebruikersactivering, wachtwoordherstel en bezorging van alarmmeldingen.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-configure-mail-server": "Hoe de e-mailserver te configureren" + }, + "step3": { + "title": "Configureer functie: SMS-provider", + "content": "

Configureer sms-providers om de klanten via sms op de hoogte te stellen van de alarmen.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-configure-sms-provider": "Hoe sms-provider te configureren" + }, + "step4": { + "title": "Configureer functie: White-labeling", + "content": "

Pas eenvoudig het logo en het kleurenschema van uw bedrijf of product aan zonder codering en zonder de service opnieuw te starten.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-configure-white-labeling": "Whitelabeling configureren" + }, + "step5": { + "title": "Configureer functie: 2FA", + "content": "

Verbeter de beveiliging van de platformaccounts met tweefactorauthenticatie.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-configure-2fa": "Hoe configureer je 2FA?" + }, + "step6": { + "title": "Functie configureren: OAuth 2", + "content": "

Vereenvoudig het inloggen voor de tenant en klantgebruikers met Single Sign-On-functionaliteit via OAuth 2.0.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-configure-oauth2": "Hoe OAuth 2 te configureren" + }, + "step7": { + "title": "Functie configureren: Slack", + "content": "

Distribueer meldingen naar de tenant en klantgebruikers via Slack volgens de meldingsregels die u instelt.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-configure-notifications": "Slack configureren" + } + }, + "tenant-admin": { + "step1": { + "title": "Device maken", + "content": "

Laten we uw eerste device via de gebruikersinterface op het platform aanmaken. Volg de documentatie over hoe u dit moet doen:

", + "how-to-create-device": "Hoe een device te maken" + }, + "step2": { + "title": "Device aansluiten", + "content-before": "

Om verbinding te maken met het device, moet u de device referenties ophalen. We raden u aan standaard automatisch gegenereerde referenties te gebruiken die toegangstoken zijn voor deze handleiding.

  • Ga naar de device tabel
  • Klik op de device rij om de apparaatgegevens te openen
  • Druk op de knop \"Toegangstoken kopiëren\"

Gebruik eenvoudige commando's om gegevens via HTTP te publiceren. Vergeet niet om $ACCESS_TOKEN te vervangen door het toegangstoken van uw device:

", + "ubuntu": { + "install-curl": "Installeer cURL voor Ubuntu:" + }, + "macos": { + "install-curl": "Installeer cURL voor MacOS:" + }, + "windows": { + "install-curl": "Vanaf Windows 10 b17063 is cURL standaard beschikbaar." + }, + "replace-access-token": "Vervang $ACCESS_TOKEN door het token van uw device:", + "content-after": "

U kunt ook andere protocollen gebruiken, zoals MQTT, CoAP, enz.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-connect-device": "Hoe het device aan te sluiten" + }, + "step3": { + "title": "Dashboard maken", + "content": "

Maak een dashboard om gegevens van entiteiten zoals assets, devices, enz. te visualiseren.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-create-dashboard": "Hoe maak je een dashboard?" + }, + "step4": { + "title": "Alarmregels configureren", + "alarm-rules": "Alarm regels", + "content": "

Laten we alarm slaan als de temperatuur 25°C bereikt. Volg de documentatie over hoe u dit moet doen:

", + "how-to-configure-alarm-rules": "Alarmregels configureren" + }, + "step5": { + "title": "Alarm maken", + "content-before": "

Om het alarm te activeren, verzendt u een nieuwe telemetriewaarde van 26°C of hoger.

", + "replace-access-token": "Vervang $ACCESS_TOKEN door het token van uw device:", + "content-after": "

Volg de documentatie over hoe u dit moet doen:

", + "how-to-create-alarm": "Hoe maak je een alarm aan?" + }, + "step6": { + "title": "Dashboard voor klanten maken en delen", + "content": "

Door dashboards voor eindgebruikers te maken, kan een klantgebruiker alleen zijn eigen devices zien en worden gegevens van een andere klant verborgen.

Volg de documentatie over hoe u dit moet doen:

", + "how-to-create-customer-and-share-dashboard": "Hoe maak je een klantdashboard en deel je het dashboard?" + } + } + } + }, + "icon": { + "icon": "Pictogram", + "select-icon": "Selecteer icoon", + "material-icons": "Materiaal iconen", + "show-all": "Toon alle iconen" + }, + "subscription": { + "entity-limit-text": "U kunt uw abonnement echter upgraden om uw limieten te verhogen.", + "upgrade-your-plan": "Abonnement upgraden", + "white-labeling-feature": "White labeling-functie", + "white-labeling-text-full": "Rebrand de webinterface van het ThingsBoard-platform in 2 minuten met uw bedrijfs- of productlogo en kleurenschema.

Verwijder \"Powered By\" in de voettekst van het dashboard.
Geen codering of herstart van de service vereist. Sta uw klanten toe om hun interface ook te whitelabelen.", + "enable-white-labeling": "Schakel nu de whitelabeling-functie in door uw abonnement te upgraden!", + "read-more": "Lees meer", + "white-labeling-video-text": "Zie onderstaande video-tutorial om te zien hoe deze functie werkt!" + }, + "subscription-error": { + "title": "Overtreding van het abonnement", + "warning-title": "Waarschuwing voor abonnement", + "upgrade-subscription-plan": "Upgrade uw abonnement", + "upgrade-subscription-plan-to-install-solution-template": "Om {{solutionTemplateName}} oplossing te installeren, moet u uw abonnement minimaal upgraden naar het {{planName}} abonnement!", + "limit-reached": { + "device-count": "Je hebt het maximale aantal devices ({{value}}) bereikt dat is toegestaan door je abonnement!", + "asset-count": "U hebt het maximale vermogen ({{value}}) bereikt dat is toegestaan door uw abonnement!" + }, + "feature-disabled": { + "white-labeling": "De White Labeling-functie is niet toegestaan door uw abonnement!" + } + }, + "phone-input": { + "phone-input-label": "Telefoonnummer", + "phone-input-required": "Telefoonnummer is verplicht", + "phone-input-validation": "Telefoonnummer is ongeldig of niet mogelijk", + "phone-input-pattern": "Ongeldig telefoonnummer. Moet in E.164-formaat zijn, bijv. {{phoneNumber}}", + "phone-input-hint": "Telefoonnummer in E.164-formaat, bijv. {{phoneNumber}}" + }, + "custom": { + "widget-action": { + "action-cell-button": "Actiecelknop", + "row-click": "Klik op rij", + "polygon-click": "Klik op polygoon", + "marker-click": "Klik op de markering", + "circle-click": "Klik op de cirkel", + "tooltip-tag-action": "Actie voor tooltip-tag", + "node-selected": "Op knooppunt geselecteerd", + "element-click": "Klik op het HTML-element op", + "pie-slice-click": "Klik op slice", + "row-double-click": "Dubbelklik op de rij" + } + }, + "paginator": { + "items-per-page": "Items per pagina:", + "first-page-label": "Eerste pagina", + "last-page-label": "Laatste pagina", + "next-page-label": "Volgende pagina", + "previous-page-label": "Vorige pagina", + "items-per-page-separator": "van" + }, + "language": { + "language": "Taal", + "locales": { + "ca_ES": "Catalaans", + "cs_CZ": "Česky", + "da_DK": "Dansk", + "de_DE": "Deutsch", + "el_GR": "Ελληνικά", + "en_US": "Engels", + "es_ES": "Español", + "fa_IR": "فارسي", + "fr_FR": "Français", + "it_IT": "Italiano", + "ja_JP": "日本語", + "ka_GE": "ქართული", + "ko_KR": "한국어", + "lv_LV": "Kanton Latviešu", + "pt_BR": "Português do Brasil", + "ro_RO": "Română", + "ru_RU": "Русский", + "sl_SI": "Slovenščina", + "tr_TR": "Türkçe", + "uk_UA": "Українська", + "zh_CN": "简体中文", + "zh_TW": "繁體中文" + } + } +} diff --git a/ui-ngx/src/assets/locale/locale.constant-ru_RU.json b/ui-ngx/src/assets/locale/locale.constant-ru_RU.json deleted file mode 100644 index 5e15a3496e..0000000000 --- a/ui-ngx/src/assets/locale/locale.constant-ru_RU.json +++ /dev/null @@ -1,1875 +0,0 @@ -{ - "access": { - "unauthorized": "Неавторизированный", - "unauthorized-access": "Несанкционированный доступ", - "unauthorized-access-text": "Вы должны войти в систему для получения доступа к этому ресурсу!", - "access-forbidden": "Доступ запрещен", - "access-forbidden-text": "У вас нет прав доступа к этому ресурсу!
Для получения доступа попробуйте войти под другим пользователем.", - "refresh-token-expired": "Сессия истекла", - "refresh-token-failed": "Не удалось обновить сессию" - }, - "action": { - "activate": "Активировать", - "suspend": "Приостановить", - "save": "Сохранить", - "saveAs": "Сохранить как", - "cancel": "Отмена", - "ok": "ОК", - "delete": "Удалить", - "add": "Добавить", - "yes": "Да", - "no": "Нет", - "update": "Обновить", - "remove": "Удалить", - "search": "Поиск", - "clear-search": "Очистить", - "assign": "Присвоить", - "unassign": "Отозвать", - "share": "Поделиться", - "make-private": "Закрыть для общего доступа", - "apply": "Применить", - "apply-changes": "Применить изменения", - "edit-mode": "Режим редактирования", - "enter-edit-mode": "Режим редактирования", - "decline-changes": "Отменить изменения", - "close": "Закрыть", - "back": "Назад", - "run": "Запуск", - "sign-in": "Войти", - "edit": "Редактировать", - "view": "Просмотреть", - "create": "Создать", - "drag": "Переместить", - "refresh": "Обновить", - "undo": "Откатить", - "copy": "Копировать", - "paste": "Вставить", - "copy-reference": "Копировать ссылку", - "paste-reference": "Вставить ссылку", - "import": "Импортировать", - "export": "Экспортировать", - "share-via": "Поделиться в {{provider}}", - "continue": "Продолжить", - "discard-changes": "Отменить изменения", - "done": "Завершено" - }, - "aggregation": { - "aggregation": "Агрегация", - "function": "Тип агрегации данных", - "limit": "Максимальное значение", - "group-interval": "Интервал группировки", - "min": "Мин", - "max": "Maкс", - "avg": "Среднее", - "sum": "Сумма", - "count": "Количество", - "none": "Без агрегации" - }, - "admin": { - "general": "Общие", - "general-settings": "Общие настройки", - "outgoing-mail": "Исходящая почта", - "outgoing-mail-settings": "Настройки исходящей почты", - "system-settings": "Системные настройки", - "test-mail-sent": "Пробное письмо успешно отправлено!", - "base-url": "Базовая URL", - "base-url-required": "Базовая URL обязательна.", - "mail-from": "Отправитель", - "mail-from-required": "Отправитель обязателен.", - "smtp-protocol": "SMTP протокол", - "smtp-host": "SMTP хост", - "smtp-host-required": "SMTP хост обязателен.", - "smtp-port": "SMTP порт", - "smtp-port-required": "SMTP порт обязателен.", - "smtp-port-invalid": "Недействительный SMTP порт.", - "timeout-msec": "Таймаут (мс)", - "timeout-required": "Таймаут обязателен.", - "timeout-invalid": "Недействительный таймаут.", - "enable-tls": "Включить TLS", - "tls-version" : "Версия TLS", - "send-test-mail": "Отправить пробное письмо", - "security-settings": "Настройки безопасности", - "password-policy": "Политика паролей", - "minimum-password-length": "Минимальная длина пароля", - "minimum-password-length-required": "Требуется минимальная длина пароля", - "minimum-password-length-range": "Минимальная длина пароля должна быть в диапазоне от 5 до 50", - "minimum-uppercase-letters": "Минимальное количество прописных букв", - "minimum-uppercase-letters-range": "Минимальное количество прописных букв не может быть отрицательным", - "minimum-lowercase-letters": "Минимальное количество строчных букв", - "minimum-lowercase-letters-range": "Минимальное количество строчных букв не может быть отрицательным", - "minimum-digits": "Минимальное количество цифр", - "minimum-digits-range": "Минимальное количество цифр не может быть отрицательным", - "minimum-special-characters": "Минимальное количество специальных символов", - "minimum-special-characters-range": "Минимальное количество специальных символов не может быть отрицательным", - "password-expiration-period-days": "Срок действия пароля в днях", - "password-expiration-period-days-range": "Срок действия пароля в днях не может быть отрицательным", - "password-reuse-frequency-days": "Частота повторного использования пароля в днях", - "password-reuse-frequency-days-range": "Частота повторного использования пароля в днях не может быть отрицательной", - "general-policy": "Общая политика", - "max-failed-login-attempts": "Максимальное количество неудачных попыток входа в систему, прежде чем учетная запись заблокирована", - "minimum-max-failed-login-attempts-range": "Максимальное количество неудачных попыток входа в систему не может быть отрицательным", - "user-lockout-notification-email": "В случае блокировки учетной записи пользователя отправьте уведомление на электронную почту", - "smpp-provider": { - "smpp-version": "SMPP версия", - "smpp-host": "SMPP хост", - "smpp-host-required": "SMPP хост обязателен.", - "smpp-port": "SMPP порт", - "smpp-port-required": "SMPP порт обязателен.", - "system-id": "ИД системи", - "system-id-required": "ИД системи обязателен.", - "password": "Пароль", - "password-required": "Пароль обязателен.", - "type-settings": "Настройки типов", - "source-settings": "Настройки источника", - "destination-settings": "Настройки назначения", - "additional-settings": "Дополнительные настройки", - "system-type": "Тип системы", - "bind-type": "Тип привязки", - "service-type": "Тип обслуживания", - "source-address": "Адрес источника", - "source-ton": "Тип номера источника", - "source-npi": "Идентификация плана нумерации источника", - "destination-ton": "Тип номера назничения", - "destination-npi": "Идентификация плана нумерации назначения", - "address-range": "Диапазон адресов", - "coding-scheme": "Схема кодирования" - } - }, - "alarm": { - "alarm": "Оповещение", - "alarms": "Оповещения", - "select-alarm": "Выбрать оповещение", - "no-alarms-matching": "Оповещения '{{entity}}' не найдены.", - "alarm-required": "Оповещение обязательно", - "alarm-status": "Статус оповещения", - "search-status": { - "ANY": "Все", - "ACTIVE": "Активные", - "CLEARED": "Сброшенные", - "ACK": "Подтвержденные", - "UNACK": "Неподтвержденные" - }, - "display-status": { - "ACTIVE_UNACK": "Активные неподтвержденные", - "ACTIVE_ACK": "Активные подтвержденные", - "CLEARED_UNACK": "Сброшенные неподтвержденные", - "CLEARED_ACK": "Сброшенные подтвержденные" - }, - "no-alarms-prompt": "Оповещения отсутствуют", - "created-time": "Время создания", - "type": "Тип", - "severity": "Уровень", - "originator": "Инициатор", - "originator-type": "Тип инициатора", - "details": "Подробности", - "status": "Статус", - "alarm-details": "Подробности об оповещении", - "start-time": "Время начала", - "end-time": "Время окончания", - "ack-time": "Время подтверждения", - "clear-time": "Время сброса", - "severity-critical": "Критический", - "severity-major": "Основной", - "severity-minor": "Второстепенный", - "severity-warning": "Предупреждение", - "severity-indeterminate": "Неопределенный", - "acknowledge": "Подтвердить", - "clear": "Сбросить", - "search": "Поиск оповещений", - "selected-alarms": "Выбрано { count, plural, =1 {1 оповещение} few {# оповещения} other {# оповещений} }", - "no-data": "Нет данных для отображения", - "polling-interval": "Интервал опроса оповещений (сек)", - "polling-interval-required": "Интервал опроса оповещений обязателен.", - "min-polling-interval-message": "Минимальный интервал опроса оповещений 1 секунда.", - "aknowledge-alarms-title": "Подтвердить { count, plural, =1 {1 оповещение} other {# оповещений} }", - "aknowledge-alarms-text": "Вы точно хотите подтвердить { count, plural, =1 {1 оповещение} other {# оповещений} }?", - "aknowledge-alarm-title": "Подтвердить оповещение", - "aknowledge-alarm-text": "Вы точно хотите подтвердить оповещение?", - "clear-alarms-title": "Сбросить { count, plural, =1 {1 оповещение} other {# оповещений} }", - "clear-alarms-text": "Вы точно хотите сбросить { count, plural, =1 {1 оповещение} other {# оповещений} }?", - "clear-alarm-title": "Сбросить оповещение", - "clear-alarm-text": "Вы точно хотите сбросить оповещение?", - "alarm-status-filter": "Фильтр оповещений", - "max-count-load": "Максимальное количество оповещений для загрузки (0 - неограниченно)", - "max-count-load-required": "Максимальное количество оповещений для загрузки обязателен.", - "max-count-load-error-min": "Минимальное значение 0.", - "fetch-size": "Размер пакета для загрузки", - "fetch-size-required": "Размер пакета для загрузки обязателен.", - "fetch-size-error-min": "Минимальное значение 10." - }, - "alias": { - "add": "Добавить псевдоним", - "edit": "Редактировать псевдоним", - "name": "Псевдоним", - "name-required": "Псевдоним обязателен", - "duplicate-alias": "Такой псевдоним уже существует.", - "filter-type-single-entity": "Отдельный объект", - "filter-type-entity-list": "Список объектов", - "filter-type-entity-name": "Название объекта", - "filter-type-state-entity": "Объект из состояния дашборда", - "filter-type-state-entity-description": "Объект, полученный из параметров состояния дашборда", - "filter-type-asset-type": "Тип актива", - "filter-type-asset-type-description": "Активы типа '{{assetTypes}}'", - "filter-type-asset-type-and-name-description": "Активы типа '{{assetTypes}}' и названием, начинающимся с '{{prefix}}'", - "filter-type-device-type": "Тип устройства", - "filter-type-device-type-description": "Устройства типа '{{deviceTypes}}'", - "filter-type-device-type-and-name-description": "Устройства типа '{{deviceTypes}}' и названием, начинающимся с '{{prefix}}'", - "filter-type-entity-view-type": "Тип Представления Объекта", - "filter-type-entity-view-type-description": "Представления Объекта типа '{{entityViewTypes}}'", - "filter-type-entity-view-type-and-name-description": "Представления Объекта типа '{{entityViewTypes}}' и названием, начинающимся с '{{prefix}}'", - "filter-type-relations-query": "Запрос по типу отношений", - "filter-type-relations-query-description": "{{entities}}, имеющие отношение типа {{relationType}} {{direction}} {{rootEntity}}", - "filter-type-asset-search-query": "Поисковый запрос по активам", - "filter-type-asset-search-query-description": "Активы типа {{assetTypes}}, имеющие отношение типа {{relationType}} {{direction}} {{rootEntity}}", - "filter-type-device-search-query": "Поисковый запрос по устройствам", - "filter-type-device-search-query-description": "Устройства типа {{deviceTypes}}, имеющие отношение типа {{relationType}} {{direction}} {{rootEntity}}", - "filter-type-entity-view-search-query": "Поисковый запрос по представлениям объектов", - "filter-type-entity-view-search-query-description": "Представления объектов типа {{entityViewTypes}}, имеющие отношение типа {{relationType}} {{direction}} {{rootEntity}}", - "entity-filter": "Фильтр объектов", - "resolve-multiple": "Принять как несколько объектов", - "filter-type": "Тип фильтра", - "filter-type-required": "Тип фильтра обязателен.", - "entity-filter-no-entity-matched": "Объекты, соответствующие фильтру, не найдены.", - "no-entity-filter-specified": "Не указан фильтр объектов", - "root-state-entity": "Использовать объект, полученный из дашборда, как корневой", - "last-level-relation": "Использовать только отношения последнего уровня", - "root-entity": "Корневой объект", - "state-entity-parameter-name": "Название объекта состояния", - "default-state-entity": "Объект состояния по умолчанию", - "default-entity-parameter-name": "По умолчанию", - "max-relation-level": "Максимальная глубина отношений", - "unlimited-level": "Неограниченная глубина", - "state-entity": "Объект состояния дашборда", - "all-entities": "Все объекты", - "any-relation": "не указано" - }, - "asset": { - "asset": "Актив", - "assets": "Активы", - "management": "Управление активами", - "view-assets": "Просмотреть активы", - "add": "Добавить актив", - "assign-to-customer": "Присвоить клиенту", - "assign-asset-to-customer": "Присвоить актив(ы) клиенту", - "assign-asset-to-customer-text": "Пожалуйста, выберите активы, которые нужно присвоить объекту", - "no-assets-text": "Активы не найдены", - "assign-to-customer-text": "Пожалуйста, выберите клиента, которому нужно присвоить актив(ы)", - "public": "Общедоступные", - "assignedToCustomer": "Присвоить клиенту", - "make-public": "Открыть общий доступ к активу", - "make-private": "Закрыть общий доступ к активу", - "unassign-from-customer": "Отозвать у клиента", - "delete": "Удалить актив", - "asset-public": "Актив общедоступный", - "asset-type": "Тип актива", - "asset-type-required": "Тип актива обязателен.", - "select-asset-type": "Выберите тип актива", - "enter-asset-type": "Введите тип актива", - "any-asset": "Любой актив", - "no-asset-types-matching": "Активы типа '{{entitySubtype}}' не найдены.", - "asset-type-list-empty": "Типы активов не выбраны.", - "asset-types": "Типы активов", - "name": "Название", - "name-required": "Название обязательно.", - "description": "Описание", - "type": "Тип", - "type-required": "Тип обязателен.", - "details": "Подробности", - "events": "События", - "add-asset-text": "Добавить новый актив", - "asset-details": "Подробности об активе", - "assign-assets": "Присвоить активы", - "assign-assets-text": "Присвоить { count, plural, =1 {1 актив} few {# актива} other {# активов} } клиенту", - "delete-assets": "Удалить активы", - "unassign-assets": "Отозвать активы", - "unassign-assets-action-title": "Отозвать { count, plural, =1 {1 актив} few {# актива} other {# активов} } у клиента", - "assign-new-asset": "Присвоить новый актив", - "delete-asset-title": "Вы точно хотите удалить '{{assetName}}'?", - "delete-asset-text": "Внимание, после подтверждения актив и все связанные с ним данные будут безвозвратно удалены.", - "delete-assets-title": "Вы точно хотите удалить { count, plural, =1 {1 актив} few {# актива} other {# активов} }", - "delete-assets-action-title": "Удалить { count, plural, =1 {1 актив} few {# актива} other {# активов} }", - "delete-assets-text": "Внимание, после подтверждения выбранные активы и все связанные с ними данные будут безвозвратно удалены.", - "make-public-asset-title": "Вы точно хотите открыть общий доступ к активу '{{assetName}}'?", - "make-public-asset-text": "Внимание, после подтверждения актив и все связанные с ним данные станут общедоступными.", - "make-private-asset-title": "Вы точно хотите закрыть общий доступ к активу '{{assetName}}'?", - "make-private-asset-text": "После подтверждения актив и все связанные с ним данные будут закрыты для общего доступа", - "unassign-asset-title": "Вы точно хотите отозвать актив '{{assetName}}'?", - "unassign-asset-text": "После подтверждения актив будут отозван, и клиент потеряет к нему доступ.", - "unassign-asset": "Отозвать актив", - "unassign-assets-title": "Вы точно хотите отозвать { count, plural, =1 {1 актив} few {# актива} other {# активов} }?", - "unassign-assets-text": "После подтверждения активы будут отозваны, и клиент потеряет к ним доступ.", - "copyId": "Копировать ИД актива", - "idCopiedMessage": "ИД актива скопировано в буфер обмена", - "select-asset": "Выбрать активы", - "no-assets-matching": "Активы, соответствующие '{{entity}}', не найдены.", - "asset-required": "Актив обязателен", - "name-starts-with": "Название актива, начинающееся с", - "import": "Импортировать активы", - "asset-file": "Файл с активами", - "label": "Метка" - }, - "attribute": { - "attributes": "Атрибуты", - "latest-telemetry": "Последняя телеметрия", - "attributes-scope": "Контекст атрибутов объекта", - "scope-latest-telemetry": "Последняя телеметрия", - "scope-client": "Клиентские атрибуты", - "scope-server": "Серверные атрибуты", - "scope-shared": "Общие атрибуты", - "add": "Добавить атрибут", - "key": "Ключ", - "last-update-time": "Последнее обновление", - "key-required": "Ключ атрибута обязателен.", - "value": "Значение", - "value-required": "Значение атрибута обязательно.", - "delete-attributes-title": "Вы уверенны, что хотите удалить { count, plural, =1 {1 атрибут} few {# атрибута} other {# атрибутов} }? ", - "delete-attributes-text": "Внимание, после подтверждения выбранные атрибуты будут удалены.", - "delete-attributes": "Удалить атрибуты", - "enter-attribute-value": "Введите значение атрибута", - "show-on-widget": "Показать на виджете", - "widget-mode": "Виджет-режим", - "next-widget": "Следующий виджет", - "prev-widget": "Предыдущий виджет", - "add-to-dashboard": "Добавить на дашборд", - "add-widget-to-dashboard": "Добавить виджет на дашборд", - "selected-attributes": "{ count, plural, =1 {Выбран} other {Выбраны} } { count, plural, =1 {1 атрибут} few {# атрибута} other {# атрибутов} }", - "selected-telemetry": "{ count, plural, =1 {Выбран} other {Выбраны} } { count, plural, =1 {1 параметр} few {# параметра} other {# параметров} } телеметрии" - }, - "audit-log": { - "audit": "Аудит", - "audit-logs": "Логи аудита", - "timestamp": "Время", - "entity-type": "Тип объекта", - "entity-name": "Название объекта", - "user": "Пользователь", - "type": "Тип", - "status": "Статус", - "details": "Подробности", - "type-added": "Добавленный", - "type-deleted": "Удаленный", - "type-updated": "Обновленный", - "type-attributes-updated": "Обновлены атрибуты", - "type-attributes-deleted": "Удалены атрибуты", - "type-rpc-call": "RPC вызов", - "type-credentials-updated": "Обновлены учетные данные", - "type-assigned-to-customer": "Присвоен клиенту", - "type-unassigned-from-customer": "Отозван у клиента", - "type-activated": "Активирован", - "type-suspended": "Приостановлен", - "type-credentials-read": "Чтение учетные данных", - "type-attributes-read": "Чтение атрибутов", - "type-relation-add-or-update": "Обновлены отношения", - "type-relation-delete": "Удалены отношения", - "type-relations-delete": "Удалены все отношения", - "type-alarm-ack": "Подтвержден", - "type-alarm-clear": "Сброшен", - "type-login": "Вход", - "type-logout": "Выход", - "type-lockout": "Заблокирован", - "status-success": "Успех", - "status-failure": "Сбой", - "audit-log-details": "Подробности аудит лога", - "no-audit-logs-prompt": "Логи не найдены", - "action-data": "Данные действия", - "failure-details": "Подробности сбоя", - "search": "Поиск аудит логов", - "clear-search": "Очистить поиск" - }, - "confirm-on-exit": { - "message": "У вас есть несохраненные изменения. Вы точно хотите покинуть эту страницу?", - "html-message": "У вас есть несохраненные изменения.
Вы точно хотите покинуть эту страницу?", - "title": "Несохраненные изменения" - }, - "contact": { - "country": "Страна", - "city": "Город", - "state": "Штат", - "postal-code": "Почтовый код", - "postal-code-invalid": "Допустимы только цифры", - "address": "Адрес", - "address2": "Адрес 2", - "phone": "Телефон", - "email": "Эл. адрес", - "no-address": "Адрес не указан" - }, - "common": { - "username": "Имя пользователя", - "password": "Пароль", - "enter-username": "Введите имя пользователя", - "enter-password": "Введите пароль", - "enter-search": "Введите условие поиска", - "created-time": "Время создания" - }, - "content-type": { - "json": "Json", - "text": "Текстовый", - "binary": "Бинарный (Base64)" - }, - "customer": { - "customer": "Клиент", - "customers": "Клиенты", - "management": "Управление клиентами", - "dashboard": "Дашборд клиента", - "dashboards": "Дашборды клиента", - "devices": "Устройства клиента", - "entity-views": "Представления объектов клиента", - "assets": "Активы клиента", - "public-dashboards": "Общедоступные дашборды", - "public-devices": "Общедоступные устройства", - "public-assets": "Общедоступные активы", - "public-entity-views": "Общедоступные представления объектов", - "add": "Добавить клиента", - "delete": "Удалить клиента", - "manage-customer-users": "Управление пользователями клиента", - "manage-customer-devices": "Управление устройствами клиента", - "manage-customer-dashboards": "Управление дашбордами клиента", - "manage-public-devices": "Управление общедоступными устройствами", - "manage-public-dashboards": "Управление общедоступными дашбордами", - "manage-customer-assets": "Управление активами клиента", - "manage-public-assets": "Управление общедоступными активами", - "add-customer-text": "Добавить нового клиента", - "no-customers-text": "Клиенты не найдены", - "customer-details": "Подробности о клиенте", - "delete-customer-title": "Вы точно хотите удалить клиента '{{customerTitle}}'?", - "delete-customer-text": "Внимание, после подтверждения клиент и все связанные с ним данные будут безвозвратно удалены.", - "delete-customers-title": "Вы точно хотите удалить { count, plural, =1 {1 клиент} few {# клиента} other {# клиентов} }?", - "delete-customers-action-title": "Удалить { count, plural, =1 {1 клиент} few {# клиента} other {# клиентов} }", - "delete-customers-text": "Внимание, после подтверждения выбранные клиенты и все связанные с ними данные будут безвозвратно удалены.", - "manage-users": "Управление пользователями", - "manage-assets": "Управление активами", - "manage-devices": "Управление устройствами", - "manage-dashboards": "Управление дашбордами", - "title": "Имя", - "title-required": "Название обязательно.", - "description": "Описание", - "details": "Подробности", - "events": "События", - "copyId": "Копировать ИД клиента", - "idCopiedMessage": "ИД клиента скопирован в буфер обмена", - "select-customer": "Выбрать клиента", - "no-customers-matching": "Клиенты, соответствующие '{{entity}}', не найдены.", - "customer-required": "Клиент обязателен", - "select-default-customer": "Выбрать клиента по умолчанию", - "default-customer": "Клиент по умолчанию", - "default-customer-required": "Клиент по умолчанию обязателен для отладки дашборда на уровне на уровне Владельца" - }, - "datetime": { - "date-from": "Дата с", - "time-from": "Время с", - "date-to": "Дата до", - "time-to": "Время до" - }, - "dashboard": { - "dashboard": "Дашборд", - "dashboards": "Дашборды", - "management": "Управление дашбордами", - "view-dashboards": "Просмотреть дашборды", - "add": "Добавить дашборд", - "assign-dashboard-to-customer": "Прикрепить дашборд(ы) к клиенту", - "assign-dashboard-to-customer-text": "Пожалуйста, выберите дашборды, которые нужно прикрепить к клиенту", - "assign-to-customer-text": "Пожалуйста, выберите клиента, к которому нужно прикрепить дашборд(ы)", - "assign-to-customer": "Прикрепить к клиенту", - "unassign-from-customer": "Отозвать у клиента", - "make-public": "Открыть дашборд для общего доступа", - "make-private": "Закрыть дашборд для общего доступа", - "manage-assigned-customers": "Управление назначенными клиентами", - "assigned-customers": "Назначенные клиенты", - "assign-to-customers": "Присвоить дашборд(ы) клиенту", - "assign-to-customers-text": "Пожалуйста, выбери клиентов, которым нужно присвоить дашборд(ы)", - "unassign-from-customers": "Отозвать дашборд(ы) у клиентов", - "unassign-from-customers-text": "Пожалуйста, выберите клиентов, у которых нужно отозвать дашборд(ы)", - "no-dashboards-text": "Дашборды не найдены", - "no-widgets": "Виджеты не сконфигурированы", - "add-widget": "Добавить новый виджет", - "title": "Название", - "select-widget-title": "Выберите виджет", - "copyId": "Копировать идентификатор дашборда", - "idCopiedMessage": "Идентификатор дашборда скопирован в буфер обмена", - "select-widget-subtitle": "Список доступных виджетов", - "delete": "Удалить дашборд", - "title-required": "Название обязательно.", - "description": "Описание", - "details": "Подробности", - "dashboard-details": "Подробности о дашборде", - "add-dashboard-text": "Добавить новый дашборд", - "assign-dashboards": "Прикрепить дашборды", - "assign-new-dashboard": "Прикрепить новый дашборд", - "assign-dashboards-text": "Прикрепить { count, plural, =1 {1 дашборд} few {# дашборда} other {# дашбордов} } к клиенту", - "unassign-dashboards-action-text": "Отозвать { count, plural, =1 {1 дашборд} few {# дашборда} other {# дашбордов} } у клиента", - "delete-dashboards": "Удалить дашборды", - "unassign-dashboards": "Отозвать дашборды", - "unassign-dashboards-action-title": "Отозвать { count, plural, =1 {1 дашборд} few {# дашборда} other {# дашбордов} } у клиента", - "delete-dashboard-title": "Вы точно хотите удалить дашборд '{{dashboardTitle}}'?", - "delete-dashboard-text": "Внимание, после подтверждения дашборд и все связанные с ним данные будут безвозвратно утеряны.", - "delete-dashboards-title": "Вы точно хотите удалить { count, plural, =1 {1 дашборд} few {# дашборда} other {# дашбордов} }?", - "delete-dashboards-action-title": "Удалить { count, plural, =1 {1 дашборд} few {# дашборда} other {# дашбордов} }", - "delete-dashboards-text": "Внимание, после подтверждения дашборды и все связанные с ними данные будут безвозвратно утеряны.", - "unassign-dashboard-title": "Вы точно хотите отозвать дашборд '{{dashboardTitle}}'?", - "unassign-dashboard-text": "После подтверждения дашборд не будет доступен клиенту.", - "unassign-dashboard": "Отозвать дашборд", - "unassign-dashboards-title": "Вы точно хотите отозвать { count, plural, =1 {1 дашборд} few {# дашборда} other {# дашбордов} }?", - "unassign-dashboards-text": "После подтверждения выбранные дашборды не будут доступны клиенту.", - "public-dashboard-title": "Теперь дашборд общедоступный", - "public-dashboard-text": "Теперь ваш дашборд {{dashboardTitle}} доступен всем по ссылке:", - "public-dashboard-notice": "Примечание: Для получения доступа к данным устройства нужно открыть общий доступ к этому устройству.", - "make-private-dashboard-title": "Вы точно хотите закрыть общий доступ к дашборду '{{dashboardTitle}}'?", - "make-private-dashboard-text": "После подтверждения дашборд будет закрыт для общего доступа.", - "make-private-dashboard": "Закрыть дашборд для общего доступа", - "socialshare-text": "'{{dashboardTitle}}' сделано ThingsBoard", - "socialshare-title": "'{{dashboardTitle}}' сделано ThingsBoard", - "select-dashboard": "Выберите дашборд", - "no-dashboards-matching": "Дашборд '{{entity}}' не найден.", - "dashboard-required": "Дашборд обязателен.", - "select-existing": "Выберите существующий дашборд", - "create-new": "Создать новый дашборд", - "new-dashboard-title": "Новое название дашборда", - "open-dashboard": "Открыть дашборд", - "set-background": "Установить фон", - "background-color": "Фоновый цвет", - "background-image": "Фоновая картинка", - "background-size-mode": "Размер фона", - "no-image": "Картинка не выбрана", - "drop-image": "Перетащите картинку или кликните для выбора файла.", - "settings": "Настройки", - "columns-count": "Количество колонок", - "columns-count-required": "Количество колонок обязательно.", - "min-columns-count-message": "Минимальное число колонок - 10.", - "max-columns-count-message": "Максимальное число колонок - 1000.", - "widgets-margins": "Величина отступа между виджетами", - "horizontal-margin": "Величина горизонтального отступа", - "horizontal-margin-required": "Величина горизонтального отступа обязательна.", - "min-horizontal-margin-message": "Минимальная величина горизонтального отступа - 0.", - "max-horizontal-margin-message": "Максимальная величина горизонтального отступа - 50.", - "vertical-margin": "Величина вертикального отступа", - "vertical-margin-required": "Величина вертикального отступа обязательна.", - "min-vertical-margin-message": "Минимальная величина вертикального отступа - 0.", - "max-vertical-margin-message": "Максимальная величина вертикального отступа - 50.", - "autofill-height": "Автозаполнение по высоте", - "mobile-layout": "Настройки мобильного режима", - "mobile-row-height": "Высота строки в мобильном режиме, px", - "mobile-row-height-required": "Высота строки в мобильном режиме обязательна.", - "min-mobile-row-height-message": "Минимальная высота строки в мобильном режиме составляет 5 px.", - "max-mobile-row-height-message": "Максимальная высота строки в мобильном режиме составляет 200 px.", - "display-title": "Показать название дашборда", - "toolbar-always-open": "Отображать панель инструментов", - "title-color": "Цвет названия", - "display-dashboards-selection": "Отображать выборку дашбордов", - "display-entities-selection": "Отображать выбору объектов", - "display-dashboard-timewindow": "Показать временное окно", - "display-dashboard-export": "Показать экспорт", - "import": "Импортировать дашборд", - "export": "Экспортировать дашборд", - "export-failed-error": "Не удалось экспортировать дашборд: {{error}}", - "create-new-dashboard": "Создать новый дашборд", - "dashboard-file": "Файл дашборда", - "invalid-dashboard-file-error": "Не удалось импортировать дашборд: неизвестная схема данных дашборда.", - "dashboard-import-missing-aliases-title": "Настроить псевдонимы импортированного дашборда", - "create-new-widget": "Создать новый виджет", - "import-widget": "Импортировать виджет", - "widget-file": "Виджет-файл", - "invalid-widget-file-error": "Не удалось импортировать виджет: неправильный формат данных.", - "widget-import-missing-aliases-title": "Настроить псевдонимы, которые использует импортированный виджет", - "open-toolbar": "Открыть панель инструментов дашборда", - "close-toolbar": "Закрыть панель инструментов", - "configuration-error": "Ошибка в настройках", - "alias-resolution-error-title": "Ошибка в настройках псевдонимов дашборда", - "invalid-aliases-config": "Не удалось найти устройство, соответствующее фильтру псевдонимов.
Пожалуйста, обратитесь к администратору для устранения неполадки.", - "select-devices": "Выберите устройства", - "assignedToCustomer": "Присвоенные клиенту", - "assignedToCustomers": "Присвоенные клиентам", - "public": "Публичный", - "public-link": "Публичная ссылка", - "copy-public-link": "Копировать публичную ссылку", - "public-link-copied-message": "Публичная ссылка на дашборд скопирована в буфер обмена.", - "manage-states": "Управление состоянием дашборда", - "states": "Состояния дашборда", - "search-states": "Поиск состояния дашборда", - "selected-states": "Выбрано { count, plural, =1 {1 состояние} few {# состояния} other {# состояний} } дашборда", - "edit-state": "Изменить состояние дашборда", - "delete-state": "Удалить состояние дашборда", - "add-state": "Добавить состояние дашборда", - "state": "Состояние дашборда", - "state-name": "Название", - "state-name-required": "Название состояния дашборда обязательно.", - "state-id": "ИД состояния", - "state-id-required": "ИД состояния дашборда обязателен.", - "state-id-exists": "Состояния дашборда с таким именем уже существует.", - "is-root-state": "Корневое состояние", - "delete-state-title": "Удалить состояние дашборда", - "delete-state-text": "Вы точно хотите удалить состояние дашборда '{{stateName}}'?", - "show-details": "Показать подробности", - "hide-details": "Скрыть подробности", - "select-state": "Выбрать состояние", - "state-controller": "Контроллер состояния" - }, - "datakey": { - "settings": "Настройки", - "advanced": "Дополнительно", - "label": "Метка", - "color": "Цвет", - "units": "Укажите символы, которые нужно указывать после значения", - "decimals": "Число знаков после запятой", - "data-generation-func": "Функция генерации данных", - "use-data-post-processing-func": "Использовать функцию пост-обработки данных", - "configuration": "Конфигурация ключа данных", - "timeseries": "Телеметрия", - "attributes": "Атрибуты", - "entity-field": "Поле объекта", - "alarm": "Параметры оповещения", - "timeseries-required": "Телеметрия объекта обязательна.", - "timeseries-or-attributes-required": "Телеметрия/атрибуты обязательны.", - "maximum-timeseries-or-attributes": "Максимальное количество параметров телеметрии или атрибутов равно {{count}}", - "alarm-fields-required": "Параметры оповещения обязательны.", - "function-types": "Тип функции", - "function-types-required": "Тип функции обязателен.", - "maximum-function-types": "Максимальное количество типов функции равно {{count}}", - "time-description": "время текущего значения;", - "value-description": "текущее значение;", - "prev-value-description": "результат предыдущего вызова функции;", - "time-prev-description": "время предыдущего значения;", - "prev-orig-value-description": "исходное предыдущее значение;" - }, - "datasource": { - "type": "Тип источника данных", - "name": "Название", - "add-datasource-prompt": "Пожалуйста, добавьте источник данных" - }, - "details": { - "edit-mode": "Режим редактирования", - "edit-json": "Редактировать JSON", - "toggle-edit-mode": "Режим редактирования" - }, - "device": { - "device": "Устройство", - "device-required": "Устройство обязательно.", - "devices": "Устройства", - "management": "Управление устройствами", - "view-devices": "Просмотреть устройства", - "device-alias": "Псевдоним устройства", - "aliases": "Псевдонимы устройства", - "no-alias-matching": "'{{alias}}' не найден.", - "no-aliases-found": "Псевдонимы не найдены.", - "no-key-matching": "'{{key}}' не найден.", - "no-keys-found": "Ключи не найдены.", - "create-new-alias": "Создать новый!", - "create-new-key": "Создать новый!", - "duplicate-alias-error": "Найден дублирующийся псевдоним '{{alias}}'.
В рамках дашборда псевдонимы устройств должны быть уникальными.", - "configure-alias": "Настроить '{{alias}}' псевдоним", - "no-devices-matching": "Устройство '{{entity}}' не найдено.", - "alias": "Псевдоним", - "alias-required": "Псевдоним устройства обязателен.", - "remove-alias": "Удалить псевдоним устройства", - "add-alias": "Добавить псевдоним устройства", - "name-starts-with": "Название начинается с", - "device-list": "Список устройств", - "use-device-name-filter": "Использовать фильтр", - "device-list-empty": "Устройства не выбраны.", - "device-name-filter-required": "Фильтр названия устройства обязателен.", - "device-name-filter-no-device-matched": "Устройства, названия которых начинаются с '{{device}}', не найдены.", - "add": "Добавить устройство", - "assign-to-customer": "Присвоить клиенту", - "assign-device-to-customer": "Присвоить устройство(а) клиенту", - "assign-device-to-customer-text": "Пожалуйста, выберите устройства, которые нужно присвоить клиенту", - "make-public": "Открыть общий доступ к устройству", - "make-private": "Закрыть общий доступ к устройству", - "no-devices-text": "Устройства не найдены", - "assign-to-customer-text": "Пожалуйста, выберите клиента, которому нужно присвоить устройство(а)", - "device-details": "Подробности об устройстве", - "add-device-text": "Добавить новое устройство", - "credentials": "Учетные данные", - "manage-credentials": "Управление учетными данными", - "delete": "Удалить устройство", - "assign-devices": "Присвоить устройство", - "assign-devices-text": "Присвоить { count, plural, =1 {1 устройство} few {# устройства} other {# устройств} } клиенту", - "delete-devices": "Удалить устройства", - "unassign-from-customer": "Отозвать у клиенту", - "unassign-devices": "Отозвать устройства", - "unassign-devices-action-title": "Отозвать у клиента { count, plural, =1 {1 устройство} few {# устройства} other {# устройств} }", - "assign-new-device": "Присвоить новое устройство", - "make-public-device-title": "Вы точно хотите открыть общий доступ к устройству '{{deviceName}}'?", - "make-public-device-text": "После подтверждения устройство и все связанные с ним данные будут общедоступными.", - "make-private-device-title": "Вы точно хотите закрыть общий доступ к устройству '{{deviceName}}'", - "make-private-device-text": "После подтверждения устройство и все связанные с ним данные будут закрыты для общего доступа.", - "view-credentials": "Просмотреть учетные данные", - "delete-device-title": "Вы точно хотите удалить устройство '{{deviceName}}'?", - "delete-device-text": "Внимание, после подтверждения устройство и все связанные с ним данные будут безвозвратно утеряны.", - "delete-devices-title": "Вы точно хотите удалить { count, plural, =1 {1 устройство} few {# устройства} other {# устройств} }?", - "delete-devices-action-title": "Удалить { count, plural, =1 {1 устройство} few {# устройства} other {# устройств} }", - "delete-devices-text": "Внимание, после подтверждения выбранные устройства и все связанные с ними данные будут безвозвратно утеряны..", - "unassign-device-title": "Вы точно хотите отозвать устройство '{{deviceName}}'?", - "unassign-device-text": "После подтверждения устройство будет недоступно клиенту.", - "unassign-device": "Отозвать устройство", - "unassign-devices-title": "Вы точно хотите отозвать { count, plural, =1 {1 устройство} few {# устройства} other {# устройств} }?", - "unassign-devices-text": "После подтверждения выбранные устройства будут недоступны клиенту.", - "device-credentials": "Учетные данные устройства", - "credentials-type": "Тип учетных данных", - "access-token": "Токен", - "access-token-required": "Токен обязателен.", - "access-token-invalid": "Длина токена должна быть от 1 до 32 символов.", - "secret": "Секрет", - "secret-required": "Секрет обязателен.", - "device-type": "Тип устройства", - "device-type-required": "Тип устройства обязатеен.", - "select-device-type": "Выберите тип устройства", - "enter-device-type": "Введите тип устройства", - "any-device": "Любое устройство", - "no-device-types-matching": "Тип устройства, соответствующий '{{entitySubtype}}', не найден.", - "device-type-list-empty": "Не выбран тип устройства.", - "device-types": "Типы устройств", - "name": "Название", - "name-required": "Название обязательно.", - "description": "Описание", - "events": "События", - "details": "Подробности", - "copyId": "Копировать идентификатор устройства", - "copyAccessToken": "Копировать токен", - "idCopiedMessage": "Идентификатор устройства скопирован в буфер обмена", - "accessTokenCopiedMessage": "Токен устройства скопирован в буфер обмена", - "assignedToCustomer": "Присвоен клиенту", - "unable-delete-device-alias-title": "Не удалось удалить псевдоним устройства", - "unable-delete-device-alias-text": "Не удалось удалить псевдоним '{{deviceAlias}}' устройства, т.к. он используется следующими виджетами:
{{widgetsList}}", - "is-gateway": "Гейтвей", - "public": "Общедоступный", - "device-public": "Устройство общедоступно", - "select-device": "Выбрать устройство", - "import": "Импортировать устройства", - "device-file": "Файл с устройствами" - }, - "dialog": { - "close": "Закрыть диалог" - }, - "direction": { - "column": "Колонка", - "row": "Строка" - }, - "error": { - "unable-to-connect": "Не удалось подключиться к серверу! Пожалуйста, проверьте интернет-соединение.", - "unhandled-error-code": "Код необработанной ошибки: {{errorCode}}", - "unknown-error": "Неизвестная ошибка" - }, - "entity": { - "entity": "Объект", - "entities": "Объекты", - "aliases": "Псевдонимы объекта", - "entity-alias": "Псевдоним объекта", - "unable-delete-entity-alias-title": "Не удалось удалить псевдоним объекта", - "unable-delete-entity-alias-text": "Псевдоним объекта '{{entityAlias}}' не может быть удален, так как используется следующим(и) виджетом(ами):
{{widgetsList}}", - "duplicate-alias-error": "Найден дубликат псевдонима '{{alias}}'.
В рамках одного дашборда псевдонимы объектов должны быть уникальными.", - "missing-entity-filter-error": "Отсутствует фильтр для псевдонима '{{alias}}'.", - "configure-alias": "Настроить псевдоним '{{alias}}'", - "alias": "Псевдоним", - "alias-required": "Псевдоним объекта обязателен.", - "remove-alias": "Убрать псевдоним объекта", - "add-alias": "Добавить псевдоним объекта", - "entity-list": "Список объектов", - "entity-type": "Тип объекта", - "entity-types": "Типы объекта", - "entity-type-list": "Список типов объекта", - "any-entity": "Любой объект", - "enter-entity-type": "Введите тип объекта", - "no-entities-matching": "Объекты, соответствующие '{{entity}}', не найдены.", - "no-entity-types-matching": "Типы объектов, соответствующие '{{entityType}}', не найдены.", - "name-starts-with": "Название, начинающееся с", - "use-entity-name-filter": "Использовать фильтр", - "entity-list-empty": "Не выбраны объекты.", - "entity-name-filter-required": "Фильтр по названию объекта обязателен.", - "entity-name-filter-no-entity-matched": "Объекты, чье название начинается с '{{entity}}', не найдены.", - "all-subtypes": "Все", - "select-entities": "Выберите объекты", - "no-aliases-found": "Псевдонимы не найдены.", - "no-alias-matching": "Псевдоним '{{alias}}' не найден.", - "create-new-alias": "Создать новый!", - "key": "Ключ", - "key-name": "Название ключа", - "no-keys-found": "Ключ не найден.", - "no-key-matching": "Ключ '{{key}}' не найден.", - "create-new-key": "Создать новый!", - "type": "Тип", - "type-required": "Тип объекта обязателен.", - "type-device": "Устройство", - "type-devices": "Устройства", - "list-of-devices": "{ count, plural, =1 {Одно устройство} other {Список из # устройств} }", - "device-name-starts-with": "Устройства, чьи название начинается с '{{prefix}}'", - "type-asset": "Актив", - "type-assets": "Активы", - "list-of-assets": "{ count, plural, =1 {Один актив} other {Список из # активов} }", - "asset-name-starts-with": "Активы, чьи название начинается с '{{prefix}}'", - "type-entity-view": "Представление Объекта", - "type-entity-views": "Представления Объекта", - "list-of-entity-views": "{ count, plural, =1 {Одно представление объекта} other {Список из # представлений объекта} }", - "entity-view-name-starts-with": "Представления Объекта, чьи название начинается с '{{prefix}}'", - "type-rule": "Правило", - "type-rules": "Правила", - "list-of-rules": "{ count, plural, =1 {Одно правило} other {Список из # правил} }", - "rule-name-starts-with": "Правила, чьи названия начинаются с '{{prefix}}'", - "type-plugin": "Плагин", - "type-plugins": "Плагины", - "list-of-plugins": "{ count, plural, =1 {Один плагин} other {Список из # плагинов} }", - "plugin-name-starts-with": "Плагины, чьи имена начинаются с '{{prefix}}'", - "type-tenant": "Владелец", - "type-tenants": "Владельцы", - "list-of-tenants": "{ count, plural, =1 {Один владелец} other {Список из # владельцев} }", - "tenant-name-starts-with": "Владельцы, чьи имена начинаются с '{{prefix}}'", - "type-customer": "Клиент", - "type-customers": "Клиенты", - "list-of-customers": "{ count, plural, =1 {Один клиент} other {Список из # клиентов} }", - "customer-name-starts-with": "Клиенты, чьи имена начинаются с '{{prefix}}'", - "type-user": "Пользователь", - "type-users": "Пользователи", - "list-of-users": "{ count, plural, =1 {Один пользователь} other {Список из # пользователей} }", - "user-name-starts-with": "Пользователи, чьи имена начинаются с '{{prefix}}'", - "type-dashboard": "Дашборд", - "type-dashboards": "Дашборды", - "list-of-dashboards": "{ count, plural, =1 {Один дашборд} other {Список из # дашбордов} }", - "dashboard-name-starts-with": "Дашборды, чьи названия начинаются с '{{prefix}}'", - "type-alarm": "Оповещение", - "type-alarms": "Оповещения", - "list-of-alarms": "{ count, plural, =1 {Одно оповещение} other {Список из # оповещений} }", - "alarm-name-starts-with": "Оповещения, чьи названия начинаются с '{{prefix}}'", - "type-rulechain": "Цепочка правил", - "type-rulechains": "Цепочки правил", - "list-of-rulechains": "{ count, plural, =1 {Одна цепочка правил} other {Список из # цепочек правил} }", - "rulechain-name-starts-with": "Цепочки правил, чьи названия начинаются с '{{prefix}}'", - "type-rulenode": "Правило", - "type-rulenodes": "Правила", - "list-of-rulenodes": "{ count, plural, =1 {Одно правило} other {Список из # правил} }", - "rulenode-name-starts-with": "Правила, чьи названия начинаются с '{{prefix}}'", - "type-current-customer": "Текущий клиент", - "type-current-tenant": "Текущий владелец", - "search": "Поиск объектов", - "selected-entities": "Выбран(ы) { count, plural, =1 {1 объект} few {# объекта} other {# объектов} }", - "entity-name": "Название объекта", - "entity-label": "Метка объекта", - "details": "Подробности об объекте", - "no-entities-prompt": "Объекты не найдены", - "no-data": "Нет данных для отображения", - "columns-to-display": "Отобразить следующие колонки" - }, - "entity-field": { - "created-time": "Время создания", - "name": "Название", - "type": "Тип", - "first-name": "Имя", - "last-name": "Фамилия", - "email": "Электронная почта", - "title": "Название", - "country": "Страна", - "state": "Штат/Область", - "city": "Город", - "address": "Адрес", - "address2": "Адрес 2", - "zip": "Индекс", - "phone": "Телефон", - "label": "Метка" - }, - "entity-view": { - "entity-view": "Представление Объекта", - "entity-view-required": "Представление объекта обязательно.", - "entity-views": "Представления Объектов", - "management": "Управление представлениями объектов", - "view-entity-views": "Просмотр представлений объектов", - "entity-view-alias": "Псевдоним Представления Объекта", - "aliases": "Псевдонимы Представления Объекта", - "no-alias-matching": "Псевдоним '{{alias}}' не найден.", - "no-aliases-found": "Псевдонимы не найдены.", - "no-key-matching": "Ключ '{{key}}' не найден.", - "no-keys-found": "Ключи не найдены.", - "create-new-alias": "Создать новый!", - "create-new-key": "Создать новый!", - "duplicate-alias-error": "Найден дубликат псевдонима '{{alias}}'.
В рамках одного дашборда псевдонимы представлений объектов должны быть уникальными.", - "configure-alias": "Настроить псевдоним '{{alias}}'", - "no-entity-views-matching": "Объекты, соответствующие '{{entity}}', не найдены.", - "alias": "Псевдоним", - "alias-required": "Псевдоним представления объекта обязателен.", - "remove-alias": "Убрать псевдоним представления объекта", - "add-alias": "Добавить псевдоним представления объекта", - "name-starts-with": "Представления объектов, чьи название начинается с", - "entity-view-list": "Список представлений объектов", - "use-entity-view-name-filter": "Использовать фильтр", - "entity-view-list-empty": "Не выбраны представления объектов.", - "entity-view-name-filter-required": "Для представлений объектов фильтр по названиям обязателен.", - "entity-view-name-filter-no-entity-view-matched": "Представление объектов, чьи название начинаются с '{{entityView}}', не найдены.", - "add": "Представление объекта", - "assign-to-customer": "Назначить клиенту", - "assign-entity-view-to-customer": "Назначить представление(я) объекта(ов) клиенту", - "assign-entity-view-to-customer-text": "Пожалуйста, выберите представления объектов, которые нужно назначить клиенту", - "no-entity-views-text": "Представления объектов не найдены", - "assign-to-customer-text": "Пожалуйста, выберите клиента, которому нужно назначить представления объектов", - "entity-view-details": "Подробности о представлении объекта", - "add-entity-view-text": "Добавить новое представление объекта", - "delete": "Удалить представление объекта", - "assign-entity-views": "Назначить представления объектов", - "assign-entity-views-text": "Назначить клиенту { count, plural, =1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }", - "delete-entity-views": "Удалить представления объектов", - "unassign-from-customer": "Отозвать у клиента", - "unassign-entity-views": "Отозвать представления объектов", - "unassign-entity-views-action-title": "Отозвать у клиента { count, plural, =1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }", - "assign-new-entity-view": "Назначит новое представление объекта", - "delete-entity-view-title": "Вы точно хотите удалить представление объекта '{{entityViewName}}'?", - "delete-entity-view-text": "Внимание, после подтверждения представление объекта и все связанные с ним данные будут безвозвратно удалены.", - "delete-entity-views-title": "Вы точно хотите удалить { count, plural, =1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }?", - "delete-entity-views-action-title": "Удалить { count, plural, =1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }", - "delete-entity-views-text": "Внимание, после подтверждения выбранные представления объектов и все связанные с ними данные будут безвозвратно удалены.", - "unassign-entity-view-title": "Вы точно хотите отозвать представление объекта '{{entityViewName}}'?", - "unassign-entity-view-text": "После подтверждение представление объекта будет недоступно клиенту.", - "unassign-entity-view": "Отозвать представление объекта", - "unassign-entity-views-title": "Вы точно хотите отозвать { count, plural, =1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }?", - "unassign-entity-views-text": "После подтверждение выбранные представления объектов будет недоступно клиенту.", - "entity-view-type": "Тип представления объекта", - "entity-view-type-required": "Тип представления объекта обязателен.", - "select-entity-view-type": "Выберите тип представления объекта", - "enter-entity-view-type": "Введите тип представления объекта", - "any-entity-view": "Любое представление объекта", - "no-entity-view-types-matching": "Типы представления объекта, соответствующие '{{entitySubtype}}', не найдены.", - "entity-view-type-list-empty": "Не выбраны типы представления объекта.", - "entity-view-types": "Типы представления объекта", - "name": "Название", - "name-required": "Название обязательно.", - "description": "Описание", - "events": "События", - "details": "Подробности", - "copyId": "Копировать ИД представление объекта", - "assignedToCustomer": "Назначено клиенту", - "unable-entity-view-device-alias-title": "Не удалось удалить псевдоним представления объекта", - "unable-entity-view-device-alias-text": "Не удалось удалить псевдоним устройства '{{entityViewAlias}}', т.к. он используется следующими виджетами:
{{widgetsList}}", - "select-entity-view": "Выбрать представление объекта", - "make-public": "Открыть общий доступ к представлению объекта", - "make-private": "Закрыть общий доступ к представлению объекта", - "start-date": "Дата начала", - "start-ts": "Время начала", - "end-date": "Дата окончания", - "end-ts": "Время окончания", - "date-limits": "Временной лимит", - "client-attributes": "Клиентские атрибуты", - "shared-attributes": "Общие атрибуты", - "server-attributes": "Серверные атрибуты", - "timeseries": "Телеметрия", - "client-attributes-placeholder": "Клиентские атрибуты", - "shared-attributes-placeholder": "Общие атрибуты", - "server-attributes-placeholder": "Серверные атрибуты", - "timeseries-placeholder": "Телеметрия", - "target-entity": "Целевой объект", - "attributes-propagation": "Пробросить атрибуты", - "attributes-propagation-hint": "Представление объекта автоматически копирует указанные атрибуты с Целевого Объекта каждый раз, когда вы сохраняете или обновляете это представление. В целях производительности атрибуты целевого объекта не пробрасываются в представление объекта на каждом их изменении. Вы можете включить автоматический проброс, настроив в вашей цепочке правило \"copy to view\" и соединив его с сообщениями типа \"Post attributes\" и \"Attributes Updated\".", - "timeseries-data": "Данные телеметрии", - "timeseries-data-hint": "Настроить ключи данных телеметрии целевого объекта, которые будут доступны представлению объекта. Эти данные только для чтения.", - "make-public-entity-view-title": "Вы уверенны, что хотите открыть общий доступ к представленю объекта '{{entityViewName}}'?", - "make-public-entity-view-text": "После подтверждения представление объекта и все связанные с ним данные станут публичными и доступными для других пользователей.", - "make-private-entity-view-title": "Вы уверенны, что хотите закрыть общий доступ к представлению объекта '{{entityViewName}}'?", - "make-private-entity-view-text": "После подтверждения представление объекта и все звязанные с ним данные станут приватными и не будут доступны для других пользователей." - }, - "event": { - "event-type": "Тип события", - "type-error": "Ошибка", - "type-lc-event": "Событие жизненного цикла", - "type-stats": "Статистика", - "type-debug-rule-node": "Отладка", - "type-debug-rule-chain": "Отладка", - "no-events-prompt": "События не найдены", - "error": "Ошибка", - "alarm": "Аварийное оповещение", - "event-time": "Время возникновения события", - "server": "Сервер", - "body": "Тело", - "method": "Метод", - "type": "Тип", - "message-id": "ИД сообщения", - "message-type": "Тип сообщения", - "data-type": "Тип данных", - "relation-type": "Тип отношения", - "metadata": "Метаданные", - "data": "Данные", - "event": "Событие", - "status": "Статус", - "success": "Успех", - "failed": "Неудача", - "messages-processed": "Сообщения обработаны", - "errors-occurred": "Возникли ошибки", - "all-events": "Все", - "entity-type": "Тип объекта", - "clear-request-title": "Удалить все события", - "clear-request-text": "Вы точно хотите удалить все события?" - }, - "extension": { - "extensions": "Расширение", - "selected-extensions": "Выбрано { count, plural, =1 {1 расширение} few {# расширения} other {# расширений} }", - "type": "Тип", - "key": "Ключ", - "value": "Значение", - "id": "ИД", - "extension-id": "ИД расширения", - "extension-type": "Тип расширения", - "transformer-json": "JSON *", - "unique-id-required": "Такое ИД расширения уже существует.", - "delete": "Удалить расширение", - "add": "Добавить расширение", - "edit": "Редактировать расширение", - "delete-extension-title": "Вы точно хотите удалить расширение '{{extensionId}}'?", - "delete-extension-text": "Внимание, после подтверждения расширение и все связанные с ним данные будут безвозвратно удалены.", - "delete-extensions-title": "Вы точно хотите удалить { count, plural, =1 {1 расширение} few {# расширения} other {# расширений} }?", - "delete-extensions-text": "Внимание, после подтверждения выбранные расширения будут удалены.", - "converters": "Конвертеры", - "converter-id": "ИД конвертера", - "configuration": "Конфигурация", - "converter-configurations": "Конфигурация конвертера", - "token": "Токен безопасности", - "add-converter": "Добавить конвертер", - "add-config": "Добавить конфигурацию конвертера", - "device-name-expression": "Маска названия устройства", - "device-type-expression": "Маска типа устройства", - "custom": "Пользовательский", - "to-double": "To Double", - "transformer": "Преобразователь", - "json-required": "JSON преобразователя обязателен.", - "json-parse": "Не удалось распознать JSON преобразователя.", - "attributes": "Атрибуты", - "add-attribute": "Добавить атрибут", - "add-map": "Добавить элемент сопоставления", - "timeseries": "Телеметрия", - "add-timeseries": "Добавить параметр телеметрии", - "field-required": "Параметр обязателен", - "brokers": "Брокеры", - "add-broker": "Добавить брокер", - "host": "Хост", - "port": "Порт", - "port-range": "Значение порта лежит в диапазоне от 1 до 65535.", - "ssl": "SSL", - "credentials": "Учетные данные", - "username": "Имя пользователя", - "password": "Пароль", - "retry-interval": "Интервал повтора в миллисекундах", - "anonymous": "Анонимный", - "basic": "Общий", - "pem": "PEM", - "ca-cert": "Файл CA сертификата *", - "private-key": "Файл приватного ключа *", - "cert": "Файл сертификата *", - "no-file": "Не выбран файл.", - "drop-file": "Перетяните файл или нажмите для выбора файла.", - "mapping": "Сопоставление", - "topic-filter": "Фильтр тем", - "converter-type": "Тип конвертера", - "converter-json": "JSON", - "json-name-expression": "JSON выражение для названия устройства", - "topic-name-expression": "Выражение для названия устройства в названии темы", - "json-type-expression": "JSON выражение для типа устройства", - "topic-type-expression": "Выражение для типа устройства в названии темы", - "attribute-key-expression": "Выражение для атрибута", - "attr-json-key-expression": "JSON выражение для атрибута", - "attr-topic-key-expression": "Выражение для атрибута в названии темы", - "request-id-expression": "Выражение для ИД запроса", - "request-id-json-expression": "JSON выражение для ИД запроса", - "request-id-topic-expression": "Выражение для ИД запроса в названии темы", - "response-topic-expression": "Выражение для темы ответов", - "value-expression": "Выражение для значения", - "topic": "Тема", - "timeout": "Таймаут в миллисекундах", - "converter-json-required": "JSON конвертер обязателен.", - "converter-json-parse": "Не удалось распознать JSON конвертера.", - "filter-expression": "Выражение для фильтрации", - "connect-requests": "Запросы о подключении устройства", - "add-connect-request": "Добавить запросы о подключении устройства", - "disconnect-requests": "Запросы об отсоединении устройства", - "add-disconnect-request": "Добавить запрос об отсоединении устройства", - "attribute-requests": "Запросы для атрибутов", - "add-attribute-request": "Добавить запрос для атрибутов", - "attribute-updates": "Обновление атрибутов", - "add-attribute-update": "Добавить обновление атрибутов", - "server-side-rpc": "Серверный RPC", - "add-server-side-rpc-request": "Добавить серверный RPC", - "device-name-filter": "Фильтр для названия устройства", - "attribute-filter": "Фильтр для атрибутов", - "method-filter": "Фильтр для процедур", - "request-topic-expression": "Выражение для темы запросов", - "response-timeout": "Время ожидания ответа в миллисекундах", - "topic-expression": "Выражение для названия темы", - "client-scope": "Клиентский", - "add-device": "Добавить устройство", - "opc-server": "Серверы", - "opc-add-server": "Добавить сервер", - "opc-add-server-prompt": "Пожалуйста, добавьте сервер", - "opc-application-name": "Название приложения", - "opc-application-uri": "URI приложения", - "opc-scan-period-in-seconds": "Частота сканирования в секундах", - "opc-security": "Безопасность", - "opc-identity": "Идентификация", - "opc-keystore": "Хранилище ключей", - "opc-type": "Тип", - "opc-keystore-type": "Тип", - "opc-keystore-location": "Расположение *", - "opc-keystore-password": "Пароль", - "opc-keystore-alias": "Псевдоним", - "opc-keystore-key-password": "Пароль для ключ", - "opc-device-node-pattern": "Паттерн OPC узла устройства", - "opc-device-name-pattern": "Паттерн названия устройства", - "modbus-server": "Серверы/ведомые устройства", - "modbus-add-server": "Добавить сервер/ведомое устройство", - "modbus-add-server-prompt": "Пожалуйста, добавить сервер/ведомое устройство", - "modbus-transport": "Транспорт", - "modbus-tcp-reconnect": "Переподключатсься автоматически", - "modbus-port-name": "Название последовательного порта", - "modbus-encoding": "Кодирование символов", - "modbus-parity": "Паритет", - "modbus-baudrate": "Скорость передачи", - "modbus-databits": "Биты данных", - "modbus-stopbits": "Стоп-биты", - "modbus-databits-range": "Параметр \"Биты данных\" может принимать значения 7 или 8.", - "modbus-stopbits-range": "Параметр \"Стоп-биты\" может принимать значения 1 или 2.", - "modbus-unit-id": "ИД устройства", - "modbus-unit-id-range": "ИД устройства должен быть в диапазоне от 1 до 247.", - "modbus-device-name": "Название устройства", - "modbus-poll-period": "Частота опроса (в миллисекундах)", - "modbus-attributes-poll-period": "Частота опроса для атрибутов (в миллисекундах)", - "modbus-timeseries-poll-period": "Частота опроса для телеметрии (в миллисекундах)", - "modbus-poll-period-range": "Значение параметра \"Частота опроса\" должно быть больше ноля.", - "modbus-tag": "Тег", - "modbus-function": "Modbus функция", - "modbus-register-address": "Адрес регистра", - "modbus-register-address-range": "Адрес регистра должен быть в диапазоне от 0 до 65535.", - "modbus-register-bit-index": "Номер бита", - "modbus-register-bit-index-range": "Номер бита должен быть в диапазоне от 0 до 15.", - "modbus-register-count": "Количество регистров", - "modbus-register-count-range": "Количество регистров должно быть больше ноля.", - "modbus-byte-order": "Порядок байтов", - "sync": { - "status": "Статус", - "sync": "Синхронизирован", - "not-sync": "Не синхронизирован", - "last-sync-time": "Время последней синхронизации", - "not-available": "Не доступен" - }, - "export-extensions-configuration": "Экспортировать конфигурацию расширений", - "import-extensions-configuration": "Импортировать конфигурацию расширений", - "import-extensions": "Импортировать расширения", - "import-extension": "Импортировать расширение", - "export-extension": "Экспортировать расширение", - "file": "Файл расширений", - "invalid-file-error": "Не правильный формат файла" - }, - "fullscreen": { - "expand": "Во весь экран", - "exit": "Выйти из полноэкранного режима", - "toggle": "Во весь экран", - "fullscreen": "Полноэкранный режим" - }, - "function": { - "function": "Функция" - }, - "grid": { - "delete-item-title": "Вы точно хотите удалить этот объект?", - "delete-item-text": "Внимание, после подтверждения объект и все связанные с ним данные будут безвозвратно утеряны.", - "delete-items-title": "Вы точно хотите удалить { count, plural, =1 {1 объект} few {# объекта} other {# объектов} }?", - "delete-items-action-title": "Удалить { count, plural, =1 {1 объект} few {# объекта} other {# объектов} }", - "delete-items-text": "Внимание, после подтверждения выбранные объекты и все связанные с ними данные будут безвозвратно утеряны.", - "add-item-text": "Добавить новый объект", - "no-items-text": "Объекты не найдены", - "item-details": "Подробности об объекте", - "delete-item": "Удалить объект", - "delete-items": "Удалить объекты", - "scroll-to-top": "Прокрутка к началу" - }, - "help": { - "goto-help-page": "Перейти к справке" - }, - "home": { - "home": "Главная", - "profile": "Профиль", - "logout": "Выйти из системы", - "menu": "Меню", - "avatar": "Аватар", - "open-user-menu": "Открыть меню пользователя" - }, - "import": { - "no-file": "Файл не выбран", - "drop-file": "Перетащите JSON файл или кликните для выбора файла.", - "drop-file-csv": "Перетащите CSV файл или кликните для выбора файла.", - "column-value": "Значение", - "column-title": "Название", - "column-example": "Пример значений данных", - "column-key": "Ключ атрибута/телеметрии", - "csv-delimiter": "Разделитель в CSV файле", - "csv-first-line-header": "Первая строка содержит названия колонок", - "csv-update-data": "Обновить атрибут/телеметрию", - "import-csv-number-columns-error": "Файл должен содержать как минимум две колонки", - "import-csv-invalid-format-error": "Неверный формат данных. Строка: '{{line}}'", - "column-type": { - "name": "Название", - "type": "Тип", - "label": "Метка", - "column-type": "Тип колонки", - "client-attribute": "Клиентский атрибут", - "shared-attribute": "Общий атрибут", - "server-attribute": "Серверный атрибут", - "timeseries": "Телеметрия", - "entity-field": "Entity field", - "access-token": "Токен" - }, - "stepper-text": { - "select-file": "Выберите файл", - "configuration": "Конфигурация импорта", - "column-type": "Выберите тип колонок", - "creat-entities": "Создание новых объектов" - }, - "message": { - "create-entities": "{{count}} новый(х) объект(ов) было успешно создано.", - "update-entities": "{{count}} объект(ов) успешно обновлено.", - "error-entities": "Возникла ошибка при создании {{count}} объекта(ов)." - } - }, - "item": { - "selected": "Выбранные" - }, - "js-func": { - "no-return-error": "Функция должна возвращать значение!", - "return-type-mismatch": "Функция должна возвращать значение типа '{{type}}'!" - }, - "key-val": { - "key": "Ключ", - "value": "Значение", - "remove-entry": "Удалить элемент", - "add-entry": "Добавить элемент", - "no-data": "Элементы отсутствуют" - }, - "layout": { - "layout": "Макет", - "manage": "Управление макетами", - "settings": "Настройки макета", - "color": "Цвет", - "main": "Основной", - "right": "Правый", - "select": "Выбрать макет" - }, - "legend": { - "direction": "Расположение элементов легенды", - "position": "Расположение легенды", - "show-max": "Показать максимальное значение", - "show-min": "Показать минимальное значение", - "show-avg": "Показать среднее значение", - "show-total": "Показать сумму", - "settings": "Настройки легенды", - "min": "Мин", - "max": "Макс", - "avg": "Среднее", - "total": "Сумма", - "comparison-time-ago": { - "days": "(день назад)", - "weeks": "(неделю назад)", - "months": "(месяц назад)", - "years": "(год назад)" - } - }, - "login": { - "login": "Войти", - "request-password-reset": "Запрос на сброс пароля", - "reset-password": "Сбросить пароль", - "create-password": "Создать пароль", - "passwords-mismatch-error": "Введенные пароли должны быть одинаковыми!", - "password-again": "Введите пароль еще раз", - "sign-in": "Пожалуйста, войдите в систему", - "username": "Имя пользователя (эл. адрес)", - "remember-me": "Запомнить меня", - "forgot-password": "Забыли пароль?", - "password-reset": "Пароль сброшен", - "expired-password-reset-message": "Срок действия Вашего пароля закончился! Пожалуйста, создайте новый пароль.", - "new-password": "Новый пароль", - "new-password-again": "Повторите новый пароль", - "password-link-sent-message": "Ссылка для сброса пароля была успешно отправлена!", - "email": "Эл. адрес", - "login-with": "Войти через {{name}}", - "or": "или" - }, - "position": { - "top": "Верх", - "bottom": "Низ", - "left": "Левый край", - "right": "Правый край" - }, - "profile": { - "profile": "Профиль", - "last-login-time": "Время последнего входа в систему", - "change-password": "Изменить пароль", - "current-password": "Текущий пароль", - "copy-jwt-token": "Копировать JWT токен", - "tokenCopiedMessage": "JWT токен скопирован в буфер обмена", - "tokenCopiedWarnMessage": "JWT токен недействителен! Перезагрузите страницу." - }, - "relation": { - "relations": "Отношения", - "direction": "Направления", - "search-direction": { - "FROM": "От", - "TO": "К" - }, - "direction-type": { - "FROM": "от", - "TO": "к" - }, - "from-relations": "Исходящие отношения", - "to-relations": "Входящие отношения", - "selected-relations": "Выбрано { count, plural, =1 {1 отношение} few {# отношения} other {# отношений} }", - "type": "Тип", - "to-entity-type": "К типу объекта", - "to-entity-name": "К объекта", - "from-entity-type": "От типа объекта", - "from-entity-name": "От объекта", - "to-entity": "К объекту", - "from-entity": "От объекта", - "delete": "Удалить отношение", - "relation-type": "Тип отношения", - "relation-type-required": "Тип отношения обязателен.", - "any-relation-type": "Любой тип", - "add": "Добавить отношение", - "edit": "Редактировать отношение", - "delete-to-relation-title": "Вы точно хотите удалить отношение, идущее к объекту '{{entityName}}'?", - "delete-to-relation-text": "Внимание, после подтверждения объект '{{entityName}}' будет отвязан от текущего объекта.", - "delete-to-relations-title": "Вы точно хотите удалить { count, plural, =1 {1 отношение} few {# отношения} other {# отношений} }?", - "delete-to-relations-text": "Внимание, после подтверждения выбранные объекты будут отвязаны от текущего объекта.", - "delete-from-relation-title": "Вы точно хотите удалить отношение, идущее от объекта '{{entityName}}'?", - "delete-from-relation-text": "Внимание, после подтверждения текущий объект будет отвязан от объекта '{{entityName}}'.", - "delete-from-relations-title": "Вы точно хотите удалить { count, plural, =1 {1 отношение} few {# отношения} other {# отношений} }?", - "delete-from-relations-text": "Внимание, после подтверждения выбранные объекты будут отвязаны от соответствующих объектов.", - "remove-relation-filter": "Удалить фильтр отношений", - "add-relation-filter": "Добавить фильтр отношений", - "any-relation": "Любое отношение", - "relation-filters": "Фильтры отношений", - "additional-info": "Дополнительная информация (JSON)", - "invalid-additional-info": "Не удалось распознать JSON с дополнительной информацией." - }, - "rulechain": { - "rulechain": "Цепочка правил", - "rulechains": "Цепочки правил", - "root": "Корневая", - "delete": "Удалить цепочку правил", - "name": "Названия", - "name-required": "Название необходимо.", - "description": "Описание", - "add": "Добавить цепочку правил", - "set-root": "Сделать цепочку корневой", - "set-root-rulechain-title": "Вы точно хотите сделать цепочку правил '{{ruleChainName}}' корневой?", - "set-root-rulechain-text": "После подтверждения цепочка правил станет корневой и будет обрабатывать все входящие сообщения.", - "delete-rulechain-title": "Вы точно хотите удалить цепочку правил '{{ruleChainName}}'?", - "delete-rulechain-text": "Внимание, после подтверждения цепочка правил и все связанные с ней данные будут безвозвратно удалены.", - "delete-rulechains-title": "Вы точно хотите удалить { count, plural, =1 {1 цепочку правил} few {# цепочки правил} other {# цепочек правил} }?", - "delete-rulechains-action-title": "Удалить { count, plural, =1 {1 цепочку правил} few {# цепочки правил} other {# цепочек правил} }", - "delete-rulechains-text": "Внимание, после подтверждения выбранные цепочки правил и все связанные с ними данные будут безвозвратно удалены.", - "add-rulechain-text": "Добавить новую цепочку правил", - "no-rulechains-text": "Цепочки правил не найдены", - "rulechain-details": "Подробности о цепочке правил", - "details": "Подробности", - "events": "События", - "system": "Системная", - "import": "Импортировать цепочку правил", - "export": "Экспортировать цепочку правил", - "export-failed-error": "Не удалось экспортировать цепочку правил: {{error}}", - "create-new-rulechain": "Создать новую цепочку правил", - "rulechain-file": "Файл цепочки правил", - "invalid-rulechain-file-error": "Не удалось импортировать цепочку правил: неправильный формат.", - "copyId": "Копировать ИД цепочки правил", - "idCopiedMessage": "ИД цепочки правил скопирован в буфер обмена", - "select-rulechain": "Выбрать цепочку правил", - "no-rulechains-matching": "Цепочки правил, соответствующие '{{entity}}', не найдены.", - "rulechain-required": "Цепочка правил обязательна", - "management": "Управление цепочками правил", - "debug-mode": "Режим отладки" - }, - "rulenode": { - "details": "Подробности", - "events": "События", - "search": "Поиск правил", - "open-node-library": "Открыть библиотеку правил", - "add": "Добавить правило", - "name": "Название", - "name-required": "Название обязательно.", - "type": "Тип", - "delete": "Удалить правило", - "select-all-objects": "Выделить все правила и связи", - "deselect-all-objects": "Отменить выделение правил и связей", - "delete-selected-objects": "Удалить выделенные правила и связи", - "delete-selected": "Удалить выделенные", - "select-all": "Выделить всё", - "copy-selected": "Копировать выделенное", - "deselect-all": "Отменить выделение", - "rulenode-details": "Подробности о правиле", - "debug-mode": "Режим отладки", - "configuration": "Настройки", - "link": "Связь", - "link-details": "Подробности о связи правила", - "add-link": "Добавить связь", - "link-label": "Метка связи", - "link-label-required": "Метка связи обязателен.", - "custom-link-label": "Пользовательская метка связи", - "custom-link-label-required": "Пользовательская метка связи обязателен.", - "link-labels": "Метки связи", - "link-labels-required": "Метки связи обязательны.", - "no-link-labels-found": "Метки связи не найдены", - "no-link-label-matching": "Метка '{{label}}' не найдена.", - "create-new-link-label": "Создать новую!", - "type-filter": "Фильтр", - "type-filter-details": "Фильтр входящих сообщений с заданными условиями", - "type-enrichment": "Насыщение", - "type-enrichment-details": "Добавить данные в метадату сообщения", - "type-transformation": "Преобразование", - "type-transformation-details": "Изменить содержимое сообщение и его метадату", - "type-action": "Действие", - "type-action-details": "Выполнить заданное действие", - "type-external": "Сторонние", - "type-external-details": "Взаимодействовать со сторонними системами", - "type-rule-chain": "Цепочка правил", - "type-rule-chain-details": "Перенаправить входящее сообщение в другую цепочку правил", - "type-input": "Вход", - "type-input-details": "Логический вход цепочки правил перенаправляет входящие сообщения в следующее правило", - "type-unknown": "Неизвестный", - "type-unknown-details": "Неопределенное правило", - "directive-is-not-loaded": "Указанная директива конфигурации '{{directiveName}}' не доступна.", - "ui-resources-load-error": "Не удалось загрузить UI ресурсы.", - "invalid-target-rulechain": "Не удалось определить целевую цепочку правил!", - "test-script-function": "Протестировать скрипт", - "message": "Сообщение", - "message-type": "Тип сообщения", - "select-message-type": "Выбрать тип сообщения", - "message-type-required": "Тип сообщения обязателен", - "metadata": "Метаданные", - "metadata-required": "Метаданные объекта не могут быть пустыми.", - "output": "Выход", - "test": "Протестировать", - "help": "Помощь", - "reset-debug-mode": "Сбросить режим отладки во всех правилах" - }, - "queue": { - "select_name": "Выберите имя для Queue", - "name": "Имя для Queue", - "name_required": "Поле 'Имя для Queue' обязательно к заполнению!" - }, - "tenant": { - "tenant": "Владелец", - "tenants": "Владельцы", - "management": "Управление владельцами", - "add": "Добавить владельца", - "admins": "Администраторы", - "manage-tenant-admins": "Управление администраторами владельца", - "delete": "Удалить владельца", - "add-tenant-text": "Добавить нового владельца", - "no-tenants-text": "Владельцы не найдены", - "tenant-details": "Подробности об владельце", - "delete-tenant-title": "Вы точно хотите удалить владельца '{{tenantTitle}}'?", - "delete-tenant-text": "Внимание, после подтверждения владелец и все связанные с ним данные будут безвозвратно утеряны.", - "delete-tenants-title": "Вы точно хотите удалить { count, plural, =1 {1 владельца} other {# владельцев} }?", - "delete-tenants-action-title": "Удалить { count, plural, =1 {1 владельца} other {# владельцев} }", - "delete-tenants-text": "Внимание, после подтверждения выбранные Владельцы и все связанные с ними данные будут безвозвратно утеряны.", - "title": "Имя", - "title-required": "Имя обязательно.", - "description": "Описание", - "details": "Подробности", - "events": "События", - "copyId": "Копировать ИД владельца", - "idCopiedMessage": "ИД владельца скопирован в буфер обмена", - "select-tenant": "Выбрать владельца", - "no-tenants-matching": "Владельцы, соответствующие '{{entity}}', не найдены.", - "tenant-required": "Владелец обязателен" - }, - "timeinterval": { - "seconds-interval": "{ seconds, plural, =1 {1 секунда} few {# секунды} other {# секунд} }", - "minutes-interval": "{ minutes, plural, =1 {1 минута} few {# минуты} other {# минут} }", - "hours-interval": "{ hours, plural, =1 {1 час} few {# часа} other {# часов} }", - "days-interval": "{ days, plural, =1 {1 день} few {# дня} other {# дней} }", - "days": "Дни", - "hours": "Часы", - "minutes": "Минуты", - "seconds": "Секунды", - "advanced": "Дополнительно" - }, - "timewindow": { - "days": "{ days, plural, =1 {1 день} few {# дня} other {# дней} }", - "hours": "{ hours, plural, =1 {1 час} few {# часа} other {# часов} }", - "minutes": "{ minutes, plural, =1 {1 минута} few {# минуты} other {# минут} }", - "seconds": "{ seconds, plural, =1 {1 секунда} few {# секунды} other {# секунд} }", - "realtime": "Режим реального времени", - "history": "История", - "last-prefix": "Последние", - "period": "с {{ startTime }} до {{ endTime }}", - "edit": "Изменить временное окно", - "date-range": "Диапазон дат", - "last": "Последние", - "time-period": "Период времени", - "hide": "Скрыть" - }, - "user": { - "user": "Пользователь", - "users": "Пользователи", - "customer-users": "Пользователи клиента", - "tenant-admins": "Администраторы владельца", - "sys-admin": "Системный администратор", - "tenant-admin": "Администратор владельца", - "customer": "Клиент", - "anonymous": "Аноним", - "add": "Добавить пользователя", - "delete": "Удалить пользователя", - "add-user-text": "Добавить нового пользователя", - "no-users-text": "Пользователи не найдены", - "user-details": "Подробности о пользователе", - "delete-user-title": "Вы точно хотите удалить пользователя '{{userEmail}}'?", - "delete-user-text": "Внимание, после подтверждения пользователь и все связанные с ним данные будут безвозвратно утеряны.", - "delete-users-title": "Вы точно хотите удалить { count, plural, =1 {1 пользователя} other {# пользователей} }?", - "delete-users-action-title": "Удалить { count, plural, =1 {1 пользователя} other {# пользователей} }", - "delete-users-text": "Внимание, после подтверждения выбранные пользователи и все связанные с ними данные будут безвозвратно утеряны.", - "activation-email-sent-message": "Активационное письмо успешно отправлено!", - "resend-activation": "Повторить отправку активационного письма", - "email": "Эл. адрес", - "email-required": "Эл. адрес обязателен.", - "invalid-email-format": "Неправильный формат эл. адреса'.", - "first-name": "Имя", - "last-name": "Фамилия", - "description": "Описание", - "default-dashboard": "Дашборд по умолчанию", - "always-fullscreen": "Всегда в полноэкранном режиме", - "select-user": "Выбрать пользователя", - "no-users-matching": "Пользователи, соответствующие '{{entity}}', не найдены.", - "user-required": "Необходимо указать пользователя", - "activation-method": "Метод активации", - "display-activation-link": "Отобразить ссылку для активации", - "send-activation-mail": "Отправить активационное письмо", - "activation-link": "Активационная ссылка для пользователя", - "activation-link-text": "Для активации пользователя используйте ссылку :", - "copy-activation-link": "Копировать активационную ссылку", - "activation-link-copied-message": "Ссылка для активации пользователя скопирована в буфер обмена", - "details": "Подробности", - "login-as-tenant-admin": "Войти как администратор владельца", - "login-as-customer-user": "Войти как пользователь клиента", - "disable-account": "Отключить учетную запись пользователя", - "enable-account": "Включить учетную запись пользователя", - "enable-account-message": "Учетная запись пользователя была успешно включена!", - "disable-account-message": "Учетная запись пользователя была успешно отключена!", - "copyId": "Копировать ИД пользователя", - "idCopiedMessage": "ИД пользователя скопирован в буфер обмена" - }, - "value": { - "type": "Тип значения", - "string": "Строка", - "string-value": "Строковое значение", - "integer": "Целое число", - "integer-value": "Целочисленное значение", - "invalid-integer-value": "Неправильный формат целого числа", - "double": "Число двойной точности", - "double-value": "Значение двойной точности", - "boolean": "Логический тип", - "boolean-value": "Логическое значение", - "false": "Ложь", - "true": "Правда", - "long": "Целое число" - }, - "widget": { - "widget-library": "Галерея виджетов", - "widget-bundle": "Набор виджетов", - "select-widgets-bundle": "Выберите набор виджетов", - "management": "Управление виджетами", - "editor": "Редактор виджетов", - "widget-type-not-found": "Ошибка при загрузке конфигурации виджета.
Возможно, связанный с ней\n тип виджета уже удален.", - "widget-type-load-error": "Не удалось загрузить виджет по следующим причинам:", - "remove": "Удалить виджет", - "edit": "Редактировать виджет", - "remove-widget-title": "Вы точно хотите удалить виджет '{{widgetTitle}}'?", - "remove-widget-text": "Внимание, после подтверждения виджет и все связанные с ним данные будут безвозвратно утеряны.", - "timeseries": "Телеметрия", - "search-data": "Поиск данных", - "no-data-found": "Данные не найдено", - "latest": "Последние значения", - "rpc": "Управляющий виджет", - "alarm": "Виджет оповещений", - "static": "Статический виджет", - "select-widget-type": "Выберите тип виджета", - "missing-widget-title-error": "Укажите название виджета!", - "widget-saved": "Виджет сохранен", - "unable-to-save-widget-error": "Не удалось сохранить виджет! Виджет содержит ошибки!", - "save": "Сохранить виджет", - "saveAs": "Сохранить виджет как", - "save-widget-type-as": "Сохранить тип виджета как", - "save-widget-type-as-text": "Пожалуйста, введите название виджета и/или укажите целевой набор виджетов", - "toggle-fullscreen": "Во весь экран", - "run": "Запустить виджет", - "title": "Название виджета", - "title-required": "Название виджета обязательно.", - "type": "Тип виджета", - "resources": "Ресурсы", - "resource-url": "JavaScript/CSS URL", - "remove-resource": "Удалить ресурс", - "add-resource": "Добавить ресурс", - "html": "HTML", - "tidy": "Форматировать", - "css": "CSS", - "settings-schema": "Схема конфигурации", - "datakey-settings-schema": "Схема конфигурации ключа данных", - "javascript": "Javascript", - "add-widget-type": "Добавить новый тип виджета", - "widget-template-load-failed-error": "Не удалось загрузить шаблон виджета!", - "add": "Добавить виджет", - "undo": "Откатить изменения в виджете", - "export": "Экспортировать виджет" - }, - "widget-action": { - "header-button": "Кнопка заголовка виджета", - "open-dashboard-state": "Перейти к новому состоянию дашборда", - "update-dashboard-state": "Обновить текущее состояние дашборда", - "open-dashboard": "Перейти к другому дашборду", - "custom": "Пользовательское действие", - "custom-pretty": "Пользовательское действие (с HTML шаблоном)", - "target-dashboard-state": "Целевое состояние дашборда", - "target-dashboard-state-required": "Целевое состояние дашборда обязательно", - "set-entity-from-widget": "Установить объект из виджета", - "target-dashboard": "Целевой дашборд", - "open-right-layout": "Открыть мобильный режим дашборда" - }, - "widgets-bundle": { - "current": "Текущий набор", - "widgets-bundles": "Наборы виджетов", - "add": "Добавить набор виджетов", - "delete": "Удалить набор виджетов", - "title": "Название", - "title-required": "Название обязательно.", - "add-widgets-bundle-text": "Добавить новый набор виджетов", - "no-widgets-bundles-text": "Наборы виджетов не найдены", - "empty": "Пустой набор виджетов", - "details": "Подробности", - "widgets-bundle-details": "Подробности о наборе виджетов", - "delete-widgets-bundle-title": "Вы точно хотите удалить набор виджетов '{{widgetsBundleTitle}}'?", - "delete-widgets-bundle-text": "Внимание, после подтверждения набор виджетов и все связанные с ним данные будут безвозвратно утеряны.", - "delete-widgets-bundles-title": "Вы точно хотите удалить { count, plural, =1 {1 набор виджетов} few {# набора виджетов} other {# наборов виджетов} }?", - "delete-widgets-bundles-action-title": "Удалить { count, plural, =1 {1 набор виджетов} few {# набора виджетов} other {# наборов виджетов} }", - "delete-widgets-bundles-text": "Внимание, после подтверждения выбранные наборы виджетов и все связанные с ними данные будут безвозвратно утеряны..", - "no-widgets-bundles-matching": "Набор виджетов '{{widgetsBundle}}' не найден.", - "widgets-bundle-required": "Набор виджетов обязателен.", - "system": "Системный", - "import": "Импортировать набор виджетов", - "export": "Экспортировать набор виджетов", - "export-failed-error": "Не удалось экспортировать набор виджетов: {{error}}", - "create-new-widgets-bundle": "Создать новый набор виджетов", - "widgets-bundle-file": "Файл набора виджетов", - "invalid-widgets-bundle-file-error": "Не удалось импортировать набор виджетов: неизвестная схема данных набора виджетов." - }, - "widget-config": { - "data": "Данные", - "settings": "Настройки", - "advanced": "Дополнительно", - "title": "Название", - "general-settings": "Общие настройки", - "display-title": "Показать название на виджете", - "drop-shadow": "Тень", - "enable-fullscreen": "Во весь экран", - "background-color": "Цвет фона", - "text-color": "Цвет текста", - "padding": "Отступ", - "margin": "Margin", - "widget-style": "Стиль виджета", - "title-style": "Стиль названия", - "mobile-mode-settings": "Мобильный режим", - "order": "Порядок", - "height": "Высота", - "units": "Специальный символ после значения", - "decimals": "Количество цифр после запятой", - "timewindow": "Временное окно", - "use-dashboard-timewindow": "Использовать временное окно дашборда", - "display-timewindow": "Показывать временное окно", - "legend": "Легенда", - "display-legend": "Показать легенду", - "datasources": "Источники данных", - "maximum-datasources": "Максимальной количество источников данных равно {{count}}", - "datasource-type": "Тип", - "datasource-parameters": "Параметры", - "remove-datasource": "Удалить источник данных", - "add-datasource": "Добавить источник данных", - "target-device": "Целевое устройство", - "alarm-source": "Источник оповещения", - "actions": "Действия", - "action": "Действие", - "add-action": "Добавить действие", - "search-actions": "Поиск действий", - "action-source": "Источник действий", - "action-source-required": "Источник действий обязателен.", - "action-name": "Название", - "action-name-required": "Название действия обязательно.", - "action-name-not-unique": "Действие с таким именем уже существует.
Название должно быть уникально в рамках одного источника действий.", - "action-icon": "Иконка", - "action-type": "Тип", - "action-type-required": "Тип действий обязателен.", - "edit-action": "Редактировать действие", - "delete-action": "Удалить действие", - "delete-action-title": "Удалить действие виджета", - "delete-action-text": "Вы точно хотите удалить действие виджета '{{actionName}}'?", - "title-icon": "Иконка в названии виджета", - "display-icon": "Показывать иконку в названии виджета", - "icon-color": "Цвет иконки", - "icon-size": "Размер иконки", - "advanced-settings": "Расширенные настройки", - "data-settings": "Настройки данных", - "no-data-display-message": "\"Нет данных для отображения\" альтернативный текст" - }, - "widget-type": { - "import": "Импортировать тип виджета", - "export": "Экспортировать тип виджета", - "export-failed-error": "Не удалось экспортировать тип виджета: {{error}}", - "create-new-widget-type": "Создать новый тип виджета", - "widget-type-file": "Файл типа виджета", - "invalid-widget-type-file-error": "Не удалось импортировать виджет: неизвестная схема данных типа виджета." - }, - "widgets": { - "date-range-navigator": { - "localizationMap": { - "Sun": "Вс", - "Mon": "Пн", - "Tue": "Вт", - "Wed": "Ср", - "Thu": "Чт", - "Fri": "Пт", - "Sat": "Сб", - "Jan": "Янв.", - "Feb": "Февр.", - "Mar": "Март", - "Apr": "Апр.", - "May": "Май", - "Jun": "Июнь", - "Jul": "Июль", - "Aug": "Авг.", - "Sep": "Сент.", - "Oct": "Окт.", - "Nov": "Нояб.", - "Dec": "Дек.", - "January": "Январь", - "February": "Февраль", - "March": "Март", - "April": "Апрель", - "June": "Июнь", - "July": "Июль", - "August": "Август", - "September": "Сентябрь", - "October": "Октября", - "November": "Ноябрь", - "December": "Декабрь", - "Custom Date Range": "Пользовательский диапазон дат", - "Date Range Template": "Шаблон диапазона дат", - "Today": "Сегодня", - "Yesterday": "Вчера", - "This Week": "На этой неделе", - "Last Week": "Прошлая неделя", - "This Month": "Этот месяц", - "Last Month": "Прошлый месяц", - "Year": "Год", - "This Year": "В этом году", - "Last Year": "Прошлый год", - "Date picker": "Выбор даты", - "Hour": "Час", - "Day": "День", - "Week": "Неделю", - "2 weeks": "2 Недели", - "Month": "Месяц", - "3 months": "3 Месяца", - "6 months": "6 Месяцев", - "Custom interval": "Пользовательский интервал", - "Interval": "Интервал", - "Step size": "Размер шага", - "Ok": "Ok" - } - }, - "input-widgets": { - "attribute-not-allowed": "Атрибут не может быть выбран в этом виджете", - "date": "Дата", - "blocked-location": "Геолокация заблокирована в вашем браузере", - "claim-device": "Подтвердить устройство", - "claim-failed": "Не удалось подтвердить устройство!", - "claim-not-found": "Устройство не найдено!", - "claim-successful": "Устройство успешно подтверждено!", - "discard-changes": "Отменить изменения", - "device-name": "Название устройства", - "device-name-required": "Необходимо указать название устройства", - "entity-attribute-required": "Значение атрибута обязателено", - "entity-coordinate-required": "Необходимо указать широту и долготу", - "entity-timeseries-required": "Значение телеметрии обязательно", - "get-location": "Получить текущее местоположение", - "latitude": "Широта", - "longitude": "Долгота", - "not-allowed-entity": "Выбраный объект не имеет общих атрибутов", - "no-attribute-selected": "Атрибут не выбран", - "no-datakey-selected": "Ни один datakey не выбран", - "no-entity-selected": "Объект не выбран", - "no-coordinate-specified": "Ключ для широты/долготы не указан", - "no-support-geolocation": "Ваш браузер не поддерживает геолокацию", - "no-image": "Нет изображения", - "no-support-web-camera": "Нет поддерживаемой веб-камеры", - "no-timeseries-selected": "Параметр телеметрии не выбран", - "secret-key": "Секретный ключ", - "secret-key-required": "Необходимо указать секретный ключ", - "switch-attribute-value": "Изменить значение атрибута", - "switch-camera": "Изменить камеру", - "switch-timeseries-value": "Изменить значение телеметрии", - "take-photo": "Сделать фото", - "time": "Время", - "timeseries-not-allowed": "Телеметрия не может быть выбрана в этом виджете", - "update-failed": "Не удалось обновить", - "update-successful": "Успешно обновлено", - "update-attribute": "Обновить атрибут", - "update-timeseries": "Обновить телеметрию", - "value": "Значение" - }, - "persistent-table": { - "rpc-id": "RPC ID", - "message-type": "Тип сообщения", - "method": "Метод", - "params": "Параметры", - "created-time": "Время создания", - "expiration-time": "Время жизни", - "retries": "Повторные попытки", - "status": "Статус", - "filter": "Фильтр", - "refresh": "Обновить", - "add": "Добавить RPC запрос", - "details": "Детали", - "delete": "Удалить", - "delete-request-title": "Удалить RPC запрос", - "delete-request-text": "Вы точно хотите удалить RPC запрос?", - "details-title": "Детали RPC ID: ", - "additional-info": "Дополнительная информация", - "response": "Ответ", - "any-status": "Любой статус", - "rpc-status-list": "Список RPC статусов", - "no-request-prompt": "Запросы не найдены", - "send-request": "Отправить запрос", - "add-title": "Добавить новый RPC запрос", - "method-error": "Метод обязателен.", - "white-space-error": "Пробелы не допускаются.", - "rpc-status": { - "QUEUED": "В ОЧЕРЕДИ", - "SENT": "ОТПРАВЛЕННО", - "DELIVERED": "ДОСТАВЛЕННО", - "SUCCESSFUL": "УСПЕШНО", - "TIMEOUT": "ВРЕМЯ ИСТЕКЛО", - "EXPIRED": "ПРОСРОЧЕНО", - "FAILED": "НЕУДАЧНО" - }, - "rpc-search-status-all": "ВСЕ", - "message-types": { - "false": "Двусторонний", - "true": "Односторонний" - } - } - }, - "icon": { - "icon": "Иконка", - "select-icon": "Выбрать иконку", - "material-icons": "Иконки в стиле Material", - "show-all": "Показать все иконки" - }, - "custom": { - "widget-action": { - "action-cell-button": "Кнопка действия в ячейке таблицы", - "row-click": "Действий при щелчке на строку", - "marker-click": "Действия при щелчке на маркер", - "polygon-click": "Действия при щелчке на полигон", - "tooltip-tag-action": "Действие при нажатии на ссылку в подсказке", - "node-selected": "Действий при выборе ноды", - "element-click": "Действий при щелчке на HTML элементе", - "pie-slice-click": "Действий при щелчке на секции круговой диаграммы", - "row-double-click": "Действий при двойном щелчке на строку" - } - }, - "language": { - "language": "Язык" - } -} diff --git a/ui-ngx/src/assets/locale/locale.constant-tr_TR.json b/ui-ngx/src/assets/locale/locale.constant-tr_TR.json index e9be2e691a..b5b70cd8f9 100644 --- a/ui-ngx/src/assets/locale/locale.constant-tr_TR.json +++ b/ui-ngx/src/assets/locale/locale.constant-tr_TR.json @@ -2430,7 +2430,6 @@ "search": "Kural Ara", "selected-rulechains": "{ count, plural, =1 {1 kural} other {# kural} } seçildi", "open-rulechain": "Kuralı Aç", - "assign-new-rulechain": "Yeni kural zinciri atayın", "edge-template-root": "Şablon Kökü", "assign-to-edge": "Uca Ata", "edge-rulechain": "Uç kuralı zinciri", diff --git a/ui-ngx/src/assets/locale/locale.constant-uk_UA.json b/ui-ngx/src/assets/locale/locale.constant-uk_UA.json index da3b6ecaee..dce1bf0a2e 100644 --- a/ui-ngx/src/assets/locale/locale.constant-uk_UA.json +++ b/ui-ngx/src/assets/locale/locale.constant-uk_UA.json @@ -6,13 +6,20 @@ "access-forbidden": "Доступ заборонено", "access-forbidden-text": "Недостатньо прав для доступу!
Спробуйте увійти як інший користувач, якщо ви все ще хочете отримати доступ до цього ресурсу.", "refresh-token-expired": "Дані про сесію застарілі", - "refresh-token-failed": "Не вдається відновити сеанс" + "refresh-token-failed": "Не вдається відновити сеанс", + "permission-denied": "У дозволі відмовлено", + "permission-denied-text": "Ви не маєте дозволу на виконання цієї операції!" + }, + "account": { + "account": "Обліковий запис", + "notification-settings": "Налаштування сповіщень" }, "action": { "activate": "Активувати", "suspend": "Призупинити", "save": "Зберегти", "saveAs": "Зберегти як", + "move": "Перемістити", "cancel": "Скасувати", "ok": "OK", "delete": "Видалити", @@ -21,6 +28,7 @@ "no": "Ні", "update": "Оновити", "remove": "Видалити", + "select": "Вибрати", "search": "Пошук", "clear-search": "Очистити пошук", "assign": "Надати", @@ -32,6 +40,7 @@ "edit-mode": "Режим редагування", "enter-edit-mode": "Ввійти в режим редагування", "decline-changes": "Відхилити зміни", + "decline": "Відхилити", "close": "Закрити", "back": "Назад", "run": "Запустити", @@ -51,9 +60,27 @@ "share-via": "Поділитися через {{provider}}", "continue": "Продовжити", "discard-changes": "Скасувати зміни", - "move": "Перемістити", - "select": "Вибрати", - "done": "Завершено" + "download": "Завантажити", + "next": "Наступний", + "next-with-label": "Наступний: {{label}}", + "read-more": "Прочитати більше", + "hide": "Приховати", + "done": "Завершено", + "print": "Друкувати", + "restore": "Відновити", + "confirm": "Підтвердити", + "more": "Більше", + "less": "Менше", + "skip": "Пропустити", + "send": "Надіслати", + "reset": "Скидання", + "show-more": "Показати більше", + "dont-show-again": "Більше не показувати", + "see-documentation": "Див. документацію", + "clear": "Очистити", + "upload": "Надіслати", + "delete-anyway": "Все одно видалити", + "delete-selected": "Видалити вибране" }, "aggregation": { "aggregation": "Агрегація", @@ -68,6 +95,7 @@ "none": "Відсутня" }, "admin": { + "settings": "Налаштування", "general": "Загальне", "general-settings": "Загальні налаштування", "outgoing-mail": "Поштовий сервер", @@ -126,15 +154,15 @@ "minimum-max-failed-login-attempts-range": "Максимальна кількість невдалих спроб входу не може бути негативною", "user-lockout-notification-email": "У разі блокування облікового запису користувача, надішліть сповіщення на електронну пошту", "smpp-provider": { - "smpp-version": "SMPP верія", + "smpp-version": "SMPP верcія", "smpp-host": "SMPP хост", "smpp-host-required": "Хост SMPP обов'язковий.", "smpp-port": "SMPP порт", "smpp-port-required": "Порт SMPP обов'язковий.", "system-id": "Id системи", - "system-id-required": "Id системи обязателен.", + "system-id-required": "ID системи обов'язковий.", "password": "Пароль", - "password-required": "Пароль обязателен.", + "password-required": "Пароль обов'язковий.", "type-settings": "Налаштування типів", "source-settings": "Налаштування джерела", "destination-settings": "Налаштування призначення", @@ -144,12 +172,13 @@ "service-type": "Тип обслуговування", "source-address": "Адреса джерела", "source-ton": "Тип номера джерела", - "source-npi": "Идентификация плана нумерации джерела", + "source-npi": "Ідентифікація плану нумерації джерела", "destination-ton": "Тип номера призначення", "destination-npi": "Ідентифікація плану нумерації призначення", "address-range": "Діапазон адрес", "coding-scheme": "Схема кодування" - } + }, + "resources": "Ресурси" }, "alarm": { "alarm": "Сигнал тривоги", @@ -249,8 +278,8 @@ "filter-type": "Тип фільтра", "filter-type-required": "Необхідно вказати тип фільтра.", "entity-filter-no-entity-matched": "Не знайдено жодних сутностей, які відповідають вказаному фільтру.", - "no-entity-filter-specified": "Фільтр обїектів не вказано", - "root-state-entity": "Використовувати сутінсть стану як кореневу", + "no-entity-filter-specified": "Фільтр сутностей не вказано", + "root-state-entity": "Використовувати сутність стану як кореневу", "last-level-relation": "Використовувати лише відношення останнього рівня", "group-state-entity": "Використовувати групу сутностей стану як кореневу", "root-entity": "Коренева сутність", @@ -323,7 +352,7 @@ "copyId": "Копіювати Id активу", "idCopiedMessage": "Id активу був скопійований у буфер обміну", "select-asset": "Виберіть актив", - "no-assets-matching": "Не знайдено жодних активів, що відповідають'{{entity}}'.", + "no-assets-matching": "Не знайдено жодних активів, що відповідають '{{entity}}'.", "asset-required": "Необхідно задати актив", "name-starts-with": "Назва активу починається з", "selected-assets": "{ count, plural, =1 {1 актив} other {# активи} } selected", @@ -367,6 +396,9 @@ "selected-attributes": "{ count, plural, =1 {1 attribute} other {# attributes} } selected ...вибрані вибрати", "selected-telemetry": "{ count, plural, =1 {1 telemetry unit} other {# telemetry units} } selected" }, + "api-usage": { + "api-usage": "Використання API" + }, "audit-log": { "audit": "Операція", "audit-logs": "Журнал операцій", @@ -476,14 +508,14 @@ "test": "Тест", "metadata": "Метадані", "metadata-required": "Записи метаданих не можуть бути порожніми.", - "integration-metadata": "Метедані інтеграції", + "integration-metadata": "Метадані інтеграції", "integration-metadata-required": "Параметри метаданих інтеграції не можуть бути порожніми.", "output": "Вихідні дані", "import": "Імпорт перетворювача даних", "export": "Експорт перетворювача даних", "export-failed-error": "Неможливо експортувати перетворювач даних: {{помилка}}", "create-new-converter": "Створити новий перетворювач даних", - "converter-file": "Файл перетворювача даних(конвектер файл)", + "converter-file": "Файл перетворювача даних", "invalid-converter-file-error": "Неможливо імпортувати перетворювач даних: недійсна структура даних перетворювача.", "type": "Тип", "type-required": "Необхідно задати тип.", @@ -620,7 +652,7 @@ "unassign-dashboard-text": "Після підтвердження, клієнт буде позбавлений панелі приладів. Панель приладів і пов'язані з нею дані будуть недоступні клієнтові.", "unassign-dashboard": "Позбавити панелі приладів", "unassign-dashboards-title": "Ви впевнені, що хочете позбавити { count, plural, =1 {1 панелі приладів} other {# панелей приладів} }?", - "unassign-dashboards-text": "Після підтвердження, клієтн буде позбавлений усіх вибраних панелей приладів і даних, які з ними пов'язані.", + "unassign-dashboards-text": "Після підтвердження, клієнт буде позбавлений усіх вибраних панелей приладів і даних, які з ними пов'язані.", "public-dashboard-title": "Панель приладів тепер публічна", "public-dashboard-text": "Ваша панель приладів {{dashboardTitle}} тепер публічна і доступна іншим link:", "public-dashboard-notice": "Note: Не забудьте зробити спільні пристрої загальнодоступними, щоб отримати доступ до їхніх даних.", @@ -645,7 +677,7 @@ "settings": "Налаштування", "columns-count": "Кількість стовпців", "columns-count-required": "Необхідно вказати кількість стовпців.", - "min-columns-count-message": "Дозволений мінімум -10 стовпців.", + "min-columns-count-message": "Дозволений мінімум - 10 стовпців.", "max-columns-count-message": "Дозволений максимум - 1000 стовпців.", "widgets-margins": "Відступ між віджетами", "horizontal-margin": "Горизонтальний відступ", @@ -686,8 +718,8 @@ "widget-file": "Файл віджета", "invalid-widget-file-error": "Неможливо імпортувати віджет: неправильна структура даних віджета.", "widget-import-missing-aliases-title": "Налаштувати псевдоніми, що використовуються імпортованим віджетом", - "open-toolbar": "Відкрити панель інструменів ", - "close-toolbar": "Закрити панель інструменів", + "open-toolbar": "Відкрити панель інструментів", + "close-toolbar": "Закрити панель інструментів", "configuration-error": "Помилка конфігурації", "alias-resolution-error-title": "Помилка конфігурації псевдонімів панелі візуалізації", "invalid-aliases-config": "Неможливо знайти пристрої, які відповідають певному фільтру псевдонімів.
Зверніться до свого адміністратора, щоб вирішити цю проблему.", @@ -717,7 +749,7 @@ "show-details": "Показати деталі", "hide-details": "Приховати деталі", "select-state": "Виберіть цільовий стан", - "state-controller": "Контроллер стану" + "state-controller": "Контролер стану" }, "datakey": { "settings": "Налаштування", @@ -732,11 +764,11 @@ "timeseries": "Телеметрія", "attributes": "Атрибути", "entity-field": "Поле сутності", - "alarm": "Поля сигнала тривоги", + "alarm": "Поля сигналу тривоги", "timeseries-required": "Необхідно вказати Телеметрія.", "timeseries-or-attributes-required": "Необхідно вказати телеметрію/атрибути.", "maximum-timeseries-or-attributes": "Максимальні { count, plural, =1 {1 телеметрія/атрибут дозволені.} other {# телеметрія/атрибути дозволені} }", - "alarm-fields-required": "Необхідно вказати поля сигнала тривоги.", + "alarm-fields-required": "Необхідно вказати поля сигналу тривоги.", "function-types": "Типи функцій", "function-types-required": "Необхідно вказати типи функцій.", "maximum-function-types": "Maximum { count, plural, =1 {1 function type is allowed.} other {# function types are allowed} }", @@ -771,7 +803,7 @@ "no-keys-found": "Ключі не знайдено.", "create-new-alias": "Створити новий!", "create-new-key": "Створити новий!", - "duplicate-alias-error": "Псевдонім з таким іменем '{{alias}}' вже існює.
Псевдоніми пристроїв повинні бути унікальними на панелі візуалізації.", + "duplicate-alias-error": "Псевдонім з таким іменем '{{alias}}' вже існує.
Псевдоніми пристроїв повинні бути унікальними на панелі візуалізації.", "configure-alias": "Налаштувати псевдонім '{{alias}}'", "no-devices-matching": "Не знайдено жодних пристроїв, які відповідають '{{entity}}'.", "alias": "Псевдонім", @@ -861,6 +893,14 @@ "list-of-groups": "{ count, plural, =1 {Одна група пристроїв} other {Список # груп пристроїв} }", "group-name-starts-with": "Групи пристроїв, імена яких починаються з '{{prefix}}'" }, + "asset-profile": { + "asset-profile": "Профіль активу", + "asset-profiles": "Профілі активів" + }, + "device-profile": { + "device-profile": "Профіль пристрою", + "device-profiles": "Профілі пристроїв" + }, "dialog": { "close": "Закрити діалогове вікно" }, @@ -868,6 +908,11 @@ "column": "Колонка", "row": "Рядок" }, + "edge": { + "management": "Керування Edge", + "instances": "Інстанси", + "rulechain-templates": "Шаблони ланцюжків правил" + }, "error": { "unable-to-connect": "Неможливо підключитися до сервера! Перевірте підключення до Інтернету.", "unhandled-error-code": "Неопрацьований помилковий код: {{errorCode}}", @@ -879,7 +924,7 @@ "aliases": "Псевдоніми сутності", "entity-alias": "Псевдонім сутності", "unable-delete-entity-alias-title": "Неможливо видалити псевдонім сутності", - "unable-delete-entity-alias-text": "Псевдонім сутності'{{entityAlias}}' неможливо видалити, так як це використовується наступним віджетом(s):
{{widgetsList}}", + "unable-delete-entity-alias-text": "Псевдонім сутності '{{entityAlias}}' неможливо видалити, оскільки він використовується наступним віджетом(s):
{{widgetsList}}", "duplicate-alias-error": "Знайдено повторюваний псевдонім '{{alias}}'.
Псевдоніми сутностей повинні бути унікальними на панелі візуалізації.", "missing-entity-filter-error": "Відсутній фільтр для псевдоніма '{{alias}}'.", "configure-alias": "Налаштувати '{{alias}}' псевдонім", @@ -1118,9 +1163,9 @@ "view-entity-views": "Переглянути представлення сутностей", "entity-view-alias": "Псевдонім представлення сутності", "aliases": "Псевдоніми представлення сутності", - "no-alias-matching": "Псевдонім'{{alias}}' не знайдено.", + "no-alias-matching": "Псевдонім '{{alias}}' не знайдено.", "no-aliases-found": "Псевдоніми не знайдено.", - "no-key-matching": "'Ключ {{key}}' не знайдено.", + "no-key-matching": "Ключ '{{key}}' не знайдено.", "no-keys-found": "Ключі не знайдено.", "create-new-alias": "Створити новий!", "create-new-key": "Створити новий!", @@ -1135,7 +1180,7 @@ "entity-view-list": "Список представленнь сутності", "use-entity-view-name-filter": "Використати фільтр", "entity-view-list-empty": "Не вибрано жодного представлення сутності.", - "entity-view-name-filter-required": "Необхідно вказвти фільтр назв представлення сутності.", + "entity-view-name-filter-required": "Необхідно вказати фільтр назв представлення сутності.", "entity-view-name-filter-no-entity-view-matched": "Представлення сутностей, назви яких починаються з '{{entityView}}' не знайдено.", "add": "Додати представлення сутності", "assign-to-customer": "Призначити клієнту", @@ -1398,8 +1443,11 @@ "import-extension": "Імпортувати розширення", "export-extension": "Експортувати розширення", "file": "Файл розширень", - "invalid-file-error": "Не правильний формат файла" + "invalid-file-error": "Неправильний формат файлу" }, + "feature": { + "advanced-features": "Додаткові можливості" + }, "fullscreen": { "expand": "Відкрити у повноекранному режимі", "exit": "Вийти з повноекранного режиму", @@ -1410,7 +1458,7 @@ "function": "Функція" }, "grid": { - "delete-item-title": "Ви впенені, що хочете видалити цей елемент?", + "delete-item-title": "Ви впевнені, що хочете видалити цей елемент?", "delete-item-text": "Будьте обережні, після підтвердження, цей елемент і всі пов'язані з ним дані, стануть недоступними.", "delete-items-title": "Ви впенені, що хочете видалити { count, plural, =1 {1 елемент} other {# елементи} }?", "delete-items-action-title": "Видалити{ count, plural, =1 {1 елемент} other {# елементи} }", @@ -1695,6 +1743,12 @@ "login-with": "Увійти через {{name}}", "or": "або" }, + "notification": { + "notification-center": "Центр сповіщень" + }, + "ota-update": { + "ota-updates": "Оновлення OTA" + }, "position": { "top": "Угорі", "bottom": "Знизу", @@ -1710,6 +1764,12 @@ "tokenCopiedMessage": "JWT токен скопійовано в буфер обміну", "tokenCopiedWarnMessage": "JWT токен не є дійсним! Перезавантажте сторінку." }, + "profiles": { + "profiles": "Профілі" + }, + "security": { + "security": "Безпека" + }, "relation": { "relations": "Відношення", "direction": "Напрямок", @@ -1752,41 +1812,44 @@ "additional-info": "Додаткова інформація (JSON)", "invalid-additional-info": "Не вдалося розібрати JSON з додатковою інформацією ." }, + "resource": { + "resources-library": "Бібліотека ресурсів" + }, "rulechain": { - "rulechain": "Ланцюг правил", - "rulechains": "Ланцюги правил", + "rulechain": "Ланцюжок правил", + "rulechains": "Ланцюжки правил", "root": "Основний", - "delete": "Видалити ланцюг правил", + "delete": "Видалити ланцюжок правил", "name": "Ім'я", "name-required": "Необхідно вказати ім'я.", "description": "Опис", - "add": "Додати ланцюг правил", - "set-root": "Зробити ланцюг правил основним", - "set-root-rulechain-title": "Ви впевнені, що хочете зробити ланцюг правил '{{ruleChainName}}' основним?", - "set-root-rulechain-text": "Після підтвердження ланцюг правил стане основним і буде обробляти всі вхідні транспортні повідомлення.", - "delete-rulechain-title": "Ви впевнені, що хочете видалити ланцюг правил '{{ruleChainName}}'?", - "delete-rulechain-text": "Будьте обережні, після підтвердження ланцюг правил і всі пов'язані з ним дані стануть недоступними.", + "add": "Додати ланцюжок правил", + "set-root": "Зробити ланцюжок правил основним", + "set-root-rulechain-title": "Ви впевнені, що хочете зробити ланцюжок правил '{{ruleChainName}}' основним?", + "set-root-rulechain-text": "Після підтвердження ланцюжок правил стане основним і буде обробляти всі вхідні транспортні повідомлення.", + "delete-rulechain-title": "Ви впевнені, що хочете видалити ланцюжок правил '{{ruleChainName}}'?", + "delete-rulechain-text": "Будьте обережні, після підтвердження ланцюжок правил і всі пов'язані з ним дані стануть недоступними.", "delete-rulechains-title": "Ви впевнені, що хочете видалити { count, plural, =1 {1 ланцюг правил} other {# ланцюги правил} }?", "delete-rulechains-action-title": "Видалити{ count, plural, =1 {1 ланцюг правил} other {# ланцюги правил} }", - "delete-rulechains-text": "Будьте обережні, після підтвердження, вибрані ланцюги правил і всі пов'язані з ними дані стануть недоступними.", - "add-rulechain-text": "Додати новий ланцюг правил", - "no-rulechains-text": "Ланцюг правил не знайдено", - "rulechain-details": "Деталі ланцюга правил", + "delete-rulechains-text": "Будьте обережні, після підтвердження, вибрані ланцюжки правил і всі пов'язані з ними дані стануть недоступними.", + "add-rulechain-text": "Додати новий ланцюжок правил", + "no-rulechains-text": "Ланцюжок правил не знайдено", + "rulechain-details": "Деталі ланцюжка правил", "details": "Деталі", "events": "Події", "system": "Система", - "import": "Імпортувати ланцюг правил", - "export": "Експортувати ланцюг правил", - "export-failed-error": "Не вдалося експортувати ланцюг правил: {{error}}", - "create-new-rulechain": "Створити новий ланцюг правил", - "rulechain-file": "Файл ланцюга правил", - "invalid-rulechain-file-error": "Неможливо імпортувати ланцюг правил: недійсна структуру даних ланцюга правил.", - "copyId": "Копіювати Id ланцюга правил", - "idCopiedMessage": "Id ланцюга правил скопійовано в буфер обміну", - "select-rulechain": "Вибрати ланцюг правил", - "no-rulechains-matching": "Не знайдено жодних ланцюгів правил, які відповідають '{{entity}}'.", - "rulechain-required": "Необхідно вказати ланцюг правил", - "management": "Управління ланцюгами правил", + "import": "Імпортувати ланцюжок правил", + "export": "Експортувати ланцюжок правил", + "export-failed-error": "Не вдалося експортувати ланцюжок правил: {{error}}", + "create-new-rulechain": "Створити новий ланцюжок правил", + "rulechain-file": "Файл ланцюжка правил", + "invalid-rulechain-file-error": "Неможливо імпортувати ланцюжок правил: недійсна структуру даних ланцюжка правил.", + "copyId": "Копіювати Id ланцюжка правил", + "idCopiedMessage": "Id ланцюжка правил скопійовано в буфер обміну", + "select-rulechain": "Вибрати ланцюжок правил", + "no-rulechains-matching": "Не знайдено жодних ланцюжків правил, які відповідають '{{entity}}'.", + "rulechain-required": "Необхідно вказати ланцюжок правил", + "management": "Управління ланцюжками правил", "debug-mode": "Режим налагодження" }, "rulenode": { @@ -1820,7 +1883,7 @@ "link-labels": "Мітки посилання", "link-labels-required": "Необхідно вказати мітки посилання.", "no-link-labels-found": "Не знайдено жодних міток посилання", - "no-link-label-matching": "Мітка'{{label}}' не знайдена.", + "no-link-label-matching": "Мітку '{{label}}' не знайдено.", "create-new-link-label": "Створити нову!", "type-filter": "Фільтр", "type-filter-details": "Фільтрувати вхідні повідомлення з заданими умовами", @@ -1834,15 +1897,15 @@ "type-analytics-details": "Виконує аналіз потокових або збережених даних", "type-external": "Зовнішній", "type-external-details": "Взаємодіє з зовнішньою системою", - "type-rule-chain": "Ланцюг правил", - "type-rule-chain-details": "Перенаправити вхідне повідомлення на вказаний ланцюг правил", + "type-rule-chain": "Ланцюжок правил", + "type-rule-chain-details": "Перенаправити вхідне повідомлення на вказаний ланцюжок правил", "type-input": "Вхід", - "type-input-details": "Логічний вхід ланцюга правил, перенаправляє вхідні повідомлення на наступний пов'язаний вузол правил", + "type-input-details": "Логічний вхід ланцюжка правил, перенаправляє вхідні повідомлення на наступний пов'язаний вузол правил", "type-unknown": "Невідомий", "type-unknown-details": "Невизначений вузол правил", "directive-is-not-loaded": "Вказана директива конфігурації '{{directiveName}}' недоступна.", "ui-resources-load-error": "Не вдалося завантажити UI ресурси.", - "invalid-target-rulechain": "Не вдається визначити цільовий ланцюг правил!", + "invalid-target-rulechain": "Не вдається визначити цільовий ланцюжок правил!", "test-script-function": "Протестувати скрипт", "message": "Повідомлення", "message-type": "Тип повідомлення", @@ -1860,7 +1923,7 @@ "scheduler-event": "Подія планувальника", "select-scheduler-event": "Вибрати подію", "no-scheduler-events-matching": "Не знайдено жодних подій, які відповідають '{{entity}}'.", - "scheduler-event-required": "Необхвдно вказати заплановану подію", + "scheduler-event-required": "Необхідно вказати заплановану подію", "management": "Управління планувальником", "scheduler-events": "Планування подій", "add-scheduler-event": "Додати подію", @@ -1902,7 +1965,7 @@ "repeat-on-monday": "Повторити в понеділок", "repeat-on-tuesday": "Повторити у вівторок", "repeat-on-wednesday": "Повторити в середу", - "repeat-on-thursday": "Повторити в червер", + "repeat-on-thursday": "Повторити в четвер", "repeat-on-friday": "Повторити в п'ятницю", "repeat-on-saturday": "Повторити в суботу", "event-type": "Тип події", @@ -1915,7 +1978,7 @@ "week": "Тиждень", "day": "День", "agenda-week": "Порядок тижня", - "agenda-day": "Порялок дня", + "agenda-day": "Порядок дня", "list-year": "Список року", "list-month": "Список місяця", "list-week": "Список тижня", @@ -1994,7 +2057,7 @@ "download-blob-entity": "Завантажити файл", "delete-blob-entity": "Видалити файл", "delete-blob-entity-title": "Ви впевнені, що хочете видалити файл '{{blobEntityName}}'?", - "delete-blob-entity-text": "Будьте обережні, після підствердження, дані файлу стануть недоступними." + "delete-blob-entity-text": "Будьте обережні, після підтвердження, дані з файлу стануть недоступними для відновлення." }, "timezone": { "timezone": "Часовий пояс", @@ -2018,7 +2081,7 @@ "add-tenant-text": "Додати нового власника", "no-tenants-text": "Не знайдено жодного власника", "tenant-details": "Подробиці про власника", - "delete-tenant-title": "Ви впевнені, що хочете видалити власника'{{tenantTitle}}'?", + "delete-tenant-title": "Ви впевнені, що хочете видалити власника '{{tenantTitle}}'?", "delete-tenant-text": "Будьте обережні, після підтвердження власник і всі пов'язані з ним дані стануть недоступними.", "delete-tenants-title": "Ви впевнені, що хочете видалити { count, plural, =1 {1 власник} other {# власники} }?", "delete-tenants-action-title": "Видалити { count, plural, =1 {1 власник} other {# власники} }", @@ -2076,7 +2139,7 @@ "add-user-text": "Додати нового користувача", "no-users-text": "Не знайдено жодного користувача", "user-details": "Подробиці про користувача", - "delete-user-title": "Ви впевнені, що хочете видалити користувача'{{userEmail}}'?", + "delete-user-title": "Ви впевнені, що хочете видалити користувача '{{userEmail}}'?", "delete-user-text": "Будьте обережні, після підтвердження, користувач і всі пов'язані з ним дані стануть недоступними.", "delete-users-title": "Ви впевнені, що хочете видалити { count, plural, =1 {1 користувача} other {# користувачів} }?", "delete-users-action-title": "Видалити { count, plural, =1 {1 користувача} other {# користувачів} }", @@ -2128,6 +2191,9 @@ "true": "Правдиве", "long": "Довге" }, + "version-control": { + "version-control": "Керування версіями" + }, "widget": { "widget-library": "Бібліотека віджетів", "widget-bundle": "Пакет віджетів", @@ -2145,7 +2211,7 @@ "no-data-found": "Даних не знайдено", "latest": "Останні значення", "rpc": "Керуючий віджет", - "alarm": "Віджет сигнала тривоги", + "alarm": "Віджет сигналу тривоги", "static": "Статичний віджет", "select-widget-type": "Вибрати тип віджета", "missing-widget-title-error": "Необхідно вказати назву віджета!", @@ -2252,7 +2318,7 @@ "remove-datasource": "Видалити джерело даних", "add-datasource": "Додати джерело даних", "target-device": "Цільовий пристрій", - "alarm-source": "Джерело сигнала тривоги", + "alarm-source": "Джерело сигналу тривоги", "actions": "Дії", "action": "Дія", "add-action": "Додати дію", @@ -2367,7 +2433,7 @@ "no-coordinate-specified": "Ключ для широти/довготи не вказаний", "no-support-geolocation": "Ваш браузер не підтримує геолокацію", "no-image": "Немає зображення", - "no-support-web-camera": "Нет поддерживаемой веб-камеры", + "no-support-web-camera": "Немає підтримуваної веб-камери", "no-timeseries-selected": "Параметр телеметрії не вибрано", "secret-key": "Секретний ключ", "secret-key-required": "Необхідно вказати секретний ключ", @@ -2412,10 +2478,10 @@ "rpc-status": { "QUEUED": "В ЧЕРЗІ", "SENT": "ВІДПРАВЛЕНО", - "DELIVERED": "ДОСТАВЛЕННО", + "DELIVERED": "ДОСТАВЛЕНО", "SUCCESSFUL": "УСПІШНО", "TIMEOUT": "ЧАС МИНУВ", - "EXPIRED": "ПРОСРОЧЕНО", + "EXPIRED": "ПРОТЕРМІНОВАНО", "FAILED": "НЕ ВДАЛО" }, "rpc-search-status-all": "ВСІ", @@ -2426,7 +2492,7 @@ } }, "white-labeling": { - "white-labeling": "Білий маркування", + "white-labeling": "Біле маркування", "login-white-labeling": "Login White Labeling", "preview": "Попередній перегляд", "app-title": "Назва програми", @@ -2441,7 +2507,7 @@ "logo-size-error": "Зображення логотипу занадто велике. Максимально дозволений розмір зображення логотипу{{kbSize}} KBytes.", "logo-type-error": "Недійсний формат файлу логотипу. Приймаються тільки зображення.", "drop-logo-image": "Зніміть зображення логотипу або клацніть, щоб вибрати файл для завантаження.", - "no-logo-image": "Не вибрано жожного логотипу", + "no-logo-image": "Не вибрано жодного логотипу", "logo-height": "Висота логотипу, px", "primary-palette": "Основна палітра", "accent-palette": "Палітра акцент", diff --git a/ui-ngx/src/assets/locale/locale.constant-zh_CN.json b/ui-ngx/src/assets/locale/locale.constant-zh_CN.json index 2c241a1c44..28c4d20f59 100644 --- a/ui-ngx/src/assets/locale/locale.constant-zh_CN.json +++ b/ui-ngx/src/assets/locale/locale.constant-zh_CN.json @@ -10,11 +10,16 @@ "permission-denied": "权限被拒绝", "permission-denied-text": "您没有执行此操作的权限!" }, + "account": { + "account": "账号", + "notification-settings": "通知设置" + }, "action": { "activate": "激活", "suspend": "暂停", "save": "保存", "saveAs": "另存为", + "move": "移动", "cancel": "取消", "ok": "确定", "delete": "删除", @@ -35,6 +40,7 @@ "edit-mode": "编辑模式", "enter-edit-mode": "进入编辑模式", "decline-changes": "撤销更改", + "decline": "撤销", "close": "关闭", "back": "后退", "run": "运行", @@ -66,7 +72,12 @@ "more": "更多", "less": "更少", "skip": "跳过", - "send": "发送" + "send": "发送", + "reset": "重置", + "show-more": "显示更多", + "dont-show-again": "不再显示", + "see-documentation": "查看文档", + "clear": "清除" }, "aggregation": { "aggregation": "聚合", @@ -94,6 +105,23 @@ "base-url-required": "基本URL必填。", "prohibit-different-url": "禁止从客户端请求头中使用主机名", "prohibit-different-url-hint": "应为生产环境启用此设置。禁用时可能会导致安全问题", + "device-connectivity": { + "device-connectivity": "设备连接", + "http-s": "HTTP(s)", + "mqtt-s": "MQTT(s)", + "coap-s": "COAP(s)", + "http": "HTTP", + "https": "HTTPs", + "mqtt": "MQTT", + "mqtts": "MQTTs", + "coap": "COAP", + "coaps": "COAPs", + "hint": "如果主机或端口字段为空,将使用默认的协议值。", + "host": "主机", + "port": "端口", + "port-pattern": "端口必须是正整数。", + "port-range": "端口应在1到65535的范围内。" + }, "mail-from": "邮件来自", "mail-from-required": "邮件发件人必填。", "smtp-protocol": "SMTP协议", @@ -173,6 +201,7 @@ "domain-name-unique": "域名和协议必须是唯一的。", "domain-name-max-length": "域名应该少于256个字符。", "error-verification-url": "域名不应包含符号 “/” 和 “:”。例:thingsboard.io", + "connection-settings": "连接设置", "oauth2": { "access-token-uri": "访问令牌URI", "access-token-uri-required": "访问令牌 URI 必填。", @@ -263,7 +292,28 @@ "platform-android": "Android", "platform-ios": "iOS", "all-platforms": "所有平台", - "allowed-platforms": "允许平台" + "smtp-provider": "SMTP提供商", + "allowed-platforms": "允许的平台", + "authentication": "身份验证", + "basic": "基本", + "provider": "提供商", + "redirect-url": "重定向URL", + "domain-name": "域名", + "redirect-url-template": "重定向URL模板", + "microsoft-tenant-id": "目录(租户)ID", + "microsoft-tenant-id-required": "需要目录(租户)ID", + "token-uri": "令牌URI", + "token-uri-required": "需要令牌URI", + "redirect-uri": "重定向URI", + "google-provider": "谷歌", + "microsoft-provider": "Office 365", + "sendgrid-provider": "Sendgrid", + "custom-provider": "自定义", + "generate-access-token": "生成访问令牌", + "update-access-token": "更新访问令牌", + "access-token-status": "访问令牌状态:", + "token-status-generated": "已生成", + "token-status-not-generated": "未生成" }, "smpp-provider": { "smpp-version": "SMPP版本", @@ -481,6 +531,7 @@ "severity-indeterminate": "不确定", "acknowledge": "应答", "clear": "清除", + "delete": "删除", "search": "查找告警", "selected-alarms": "已选择 { count, plural, =1 {1 个告警} other {# 个告警} }", "no-data": "无数据显示", @@ -491,10 +542,14 @@ "aknowledge-alarms-text": "确定要确认 { count, plural, =1 {1 个告警} other {# 个告警} }吗?", "aknowledge-alarm-title": "确认告警", "aknowledge-alarm-text": "确定要确认告警吗?", + "selected-alarms-are-acknowledged": "所选的告警已经被确认", "clear-alarms-title": "清除 { count, plural, =1 {1 个告警} other {# 个告警} }", "clear-alarms-text": "确定要清除 { count, plural, =1 {1 个告警} other {# 个告警} }?", - "clear-alarm-title": "清除警报", - "clear-alarm-text": "确定要清除警报吗?", + "clear-alarm-title": "清除告警", + "clear-alarm-text": "确定要清除告警吗?", + "delete-alarms-title": "删除 { count, plural, =1 {1 个告警} other {# 个告警} }", + "delete-alarms-text": "您确定要删除 { count, plural, =1 {1 个告警} other {# 个告警} } 吗?", + "selected-alarms-are-cleared": "所选的告警已清除", "alarm-status-filter": "告警状态筛选器", "alarm-filter-title": "告警筛选器", "assigned": "已分配", @@ -512,7 +567,11 @@ "search-propagated-alarms": "检索已传递的警报", "comments": "告警评论", "show-more": "显示更多", - "additional-info": "附加信息" + "additional-info": "附加信息", + "alarm-type": "告警类型", + "enter-alarm-type": "输入告警类型", + "no-alarm-types-matching": "找不到与 '{{entitySubtype}}' 相匹配的告警类型。", + "alarm-type-list-empty": "未选择告警类型。" }, "alarm-activity": { "add": "添加评论", @@ -666,6 +725,7 @@ "attribute": { "attributes": "属性", "latest-telemetry": "最新遥测数据", + "no-latest-telemetry": "没有最新的遥测数据", "attributes-scope": "设备属性范围", "scope-telemetry": "遥测", "scope-latest-telemetry": "最新遥测数据", @@ -679,6 +739,8 @@ "key-required": "属性键必填。", "value": "数值", "value-required": "属性值必填。", + "telemetry-key-required": "需要遥测键", + "telemetry-value-required": "需要遥测数值", "delete-attributes-title": "确定要删除 { count, plural, =1 {1 个属性} other {# 个属性} }吗?", "delete-attributes-text": "注意,确认后所有选中的属性都会被删除。", "delete-attributes": "删除属性", @@ -694,7 +756,19 @@ "no-attributes-text": "未找到属性", "no-telemetry-text": "未找到遥测数据", "copy-key": "复制键", - "copy-value": "复制值" + "add-telemetry": "添加遥测数据", + "copy-value": "复制数值", + "delete-timeseries": { + "start-time": "开始时间", + "ends-on": "结束时间", + "strategy": "策略", + "delete-strategy": "删除策略", + "all-data": "删除所有数据", + "all-data-except-latest-value": "删除除最新值外的所有数据", + "latest-value": "删除最新值", + "all-data-for-time-period": "删除指定时间段的所有数据", + "rewrite-latest-value": "重写最新值" + } }, "api-usage": { "api-features": "Api统计", @@ -713,8 +787,14 @@ "email-messages-monthly-activity": "每月产生的邮件消息", "exceptions": "异常", "executions": "执行数", + "scripts": "Scripts", + "scripts-hourly-activity": "脚本每小时活动", + "scripts-daily-activity": "脚本每日活动", + "scripts-monthly-activity": "脚本每月活动", "javascript": "JavaScript", "javascript-executions": "JavaScript 执行数", + "tbel": "TBEL", + "tbel-executions": "TBEL 执行数", "latest-error": "最新错误", "messages": "消息", "notifications": "通知", @@ -753,6 +833,18 @@ "view-details": "查看详细信息", "view-statistics": "查看统计信息" }, + "api-limit": { + "cassandra-queries": "Cassandra查询次数", + "entity-version-creation": "实体版本创建次数", + "entity-version-load": "实体版本加载次数", + "notification-requests": "通知请求次数", + "notification-requests-per-rule": "每个规则的通知请求次数", + "rest-api-requests": "REST API请求次数", + "rest-api-requests-per-customer": "每个客户的REST API请求次数", + "transport-messages": "传输消息次数", + "transport-messages-per-device": "每个设备的传输消息次数", + "ws-updates-per-session": "每个会话的WS更新次数" + }, "audit-log": { "audit": "审计", "audit-logs": "审计日志", @@ -804,7 +896,8 @@ "type-provision-success": "设备已预配置", "type-provision-failure": "设备预配置失败", "type-timeseries-updated": "遥测数据已更新", - "type-timeseries-deleted": "遥测数据已删除" + "type-timeseries-deleted": "遥测数据已删除", + "type-sms-sent": "短信发送" }, "confirm-on-exit": { "message": "有未保存的更改,确定要离开此页吗?", @@ -835,7 +928,9 @@ "created-time": "创建时间", "loading": "正在加载中...", "proceed": "继续", - "open-details-page": "打开详情页" + "open-details-page": "打开详情页", + "not-found": "未找到", + "documentation": "文档" }, "content-type": { "json": "Json", @@ -898,6 +993,13 @@ "edges": "客户边缘实例", "manage-edges": "管理边缘" }, + "date": { + "last-update-n-ago": "N分钟前的最后更新", + "last-update-n-ago-text": "最后更新{{ agoText }}", + "custom-date": "自定义日期", + "format": "格式", + "preview": "预览" + }, "datetime": { "date-from": "开始日期", "time-from": "开始时间", @@ -927,6 +1029,7 @@ "no-dashboards-text": "未找到仪表板", "no-widgets": "没有配置部件", "add-widget": "添加部件", + "add-widget-button-text": "添加部件", "title": "标题", "image": "仪表板图片", "mobile-app-settings": "移动端应用设置", @@ -973,7 +1076,7 @@ "no-dashboards-matching": "未找到匹配 '{{entity}}' 的仪表板。", "dashboard-required": "仪表板必填。", "select-existing": "选择现有仪表板", - "create-new": "创建新的仪表板", + "create-new": "创建仪表板", "new-dashboard-title": "新仪表板标题", "open-dashboard": "打开仪表板", "set-background": "设置背景", @@ -1030,11 +1133,11 @@ "import": "导入仪表板", "export": "导出仪表板", "export-failed-error": "无法导出仪表板: {{error}}", - "create-new-dashboard": "创建新的仪表板", + "create-new-dashboard": "创建仪表板", "dashboard-file": "仪表板文件", "invalid-dashboard-file-error": "无法导入仪表板: 仪表板数据结构无效。", "dashboard-import-missing-aliases-title": "配置导入仪表板使用的别名", - "create-new-widget": "创建新部件", + "create-new-widget": "创建部件", "import-widget": "导入部件", "widget-file": "部件文件", "invalid-widget-file-error": "无法导入窗口部件: 窗口部件数据结构无效。", @@ -1055,6 +1158,7 @@ "public-link-copied-message": "仪表板的公共链接已被复制到剪贴板", "manage-states": "仪表板状态管理", "states": "仪表板状态", + "states-short": "状态", "search-states": "仪表板状态检索", "selected-states": "已选择 { count, plural, =1 {1 个仪表板状态} other {# 个仪表板状态} }", "edit-state": "仪表板状态编辑", @@ -1083,11 +1187,14 @@ "unassign-dashboards-from-edge-text": "确认后,所有选定的仪表板将被取消分配,边缘将无法访问。", "assign-dashboard-to-edge": "将仪表板分配给边缘", "assign-dashboard-to-edge-text": "请选择要分配给边缘的仪表板", - "non-existent-dashboard-state-error": "找不到ID为 \"{{ stateId }}\" 的仪表板状态。" + "non-existent-dashboard-state-error": "找不到ID为 '{{ stateId }}' 的仪表板状态。", + "edit-mode": "编辑模式" }, "datakey": { "settings": "设置", + "general": "常规", "advanced": "高级", + "key": "键", "label": "标签", "color": "颜色", "units": "单位符号", @@ -1107,6 +1214,10 @@ "function-types": "函数类型", "function-type": "函数类型", "function-types-required": "函数类型必填。", + "data-keys": "数据键", + "data-key": "数据键", + "data-keys-required": "数据键是必须的。", + "data-key-required": "数据键是必须的。", "alarm-keys": "告警数据键", "alarm-key": "告警数据键", "alarm-key-functions": "告警数据键函数", @@ -1139,7 +1250,13 @@ "delta-calculation-result": "增量计算结果", "delta-calculation-result-previous-value": "上个值", "delta-calculation-result-delta-absolute": "绝对值", - "delta-calculation-result-delta-percent": "百分比" + "delta-calculation-result-delta-percent": "百分比", + "source": "来源", + "latest": "最新", + "latest-value": "最新值", + "delta": "增量", + "percent": "百分比", + "absolute": "绝对值" }, "datasource": { "type": "数据源类型", @@ -1166,8 +1283,8 @@ "no-aliases-found": "未找到别名。", "no-key-matching": "'{{key}}' 未找到。", "no-keys-found": "未找到密钥。", - "create-new-alias": "创建一个新的!", - "create-new-key": "创建一个新的!", + "create-new-alias": "创建别名", + "create-new-key": "创建键", "duplicate-alias-error": "找到重复别名 '{{alias}}'。
设备别名必须是唯一的。", "configure-alias": "配置 '{{alias}}' 别名", "no-devices-matching": "未找到与 '{{entity}}' 匹配的设备。", @@ -1273,7 +1390,7 @@ "client-id-pattern": "包含无效字符。", "user-name": "用户名", "user-name-required": "用户名必填。", - "client-id-or-user-name-necessary": "客户端ID和/或用户名是必需的", + "client-id-or-user-name-necessary": "客户端ID或用户名是必需的", "password": "密码", "secret": "密钥", "secret-required": "密钥必填", @@ -1284,6 +1401,7 @@ "any-device": "任意设备", "no-device-types-matching": "未找到匹配 '{{entitySubtype}}' 的设备类型。", "device-type-list-empty": "未选择设备类型", + "device-profile-type-list-empty": "至少应选择一个设备配置。", "device-types": "设备类型", "name": "名称", "name-required": "名称必填。", @@ -1325,7 +1443,25 @@ "device-details": "设备详细信息" }, "unassign-devices-from-edge-title": "确定要取消分配 { count, plural, =1 {1 个设备} other {# 个设备} } 吗?", - "unassign-devices-from-edge-text": "确认后,设备将被取消分配,边缘将无法访问。" + "unassign-devices-from-edge-text": "确认后,设备将被取消分配,边缘将无法访问。", + "time": "时间", + "connectivity": { + "check-connectivity": "检查连通性", + "device-created-check-connectivity": "设备已创建,检查连通性!", + "loading-check-connectivity-command": "正在加载检查连通性命令...", + "use-following-instructions": "请使用以下说明代表设备发送遥测数据", + "execute-following-command": "执行以下命令", + "install-curl-windows": "从 Windows 10 b17063 开始,cURL 已默认安装", + "install-curl-macos": "从 Mac OS X 10.2 6C115(Jaguar)开始,cURL 已默认安装", + "install-mqtt-windows": "使用说明下载、安装、设置和运行 mosquitto_pub", + "install-coap-client": "使用说明下载、安装、设置和运行 coap-client", + "install-necessary-client-tools": "安装必要的客户端工具", + "mqtts-x509-command": "使用以下文档通过 MQTT 连接带有 X509 授权的设备", + "coaps-x509-command": "使用以下文档通过基于 DTLS 的 CoAP 连接带有 X509 授权的设备", + "snmp-command": "使用以下文档通过 SNMP 连接设备。", + "sparkplug-command": "使用以下文档通过 MQTT Sparkplug 连接设备。", + "lwm2m-command": "使用以下文档通过 LWM2M 连接设备。" + } }, "asset-profile": { "asset-profile": "资产配置", @@ -1364,12 +1500,12 @@ "set-default-asset-profile-title": "确定要将 '{{assetProfileName}}' 设为默认资产配置吗?", "set-default-asset-profile-text": "确认后,资产配置将被标记为默认,并将用于未指定配置的新资产。", "no-asset-profiles-found": "未不到资产配置。", - "create-new-asset-profile": "创建一个新的!", + "create-new-asset-profile": "创建资产配置", "create-asset-profile": "创建资产配置", "import": "导入资产配置", "export": "导出资产配置", "export-failed-error": "无法导出资产配置: {{error}}", - "asset-profile-file": "资产配置文件", + "asset-profile-file": "资产配置", "invalid-asset-profile-file-error": "无法导入资产配置:无效的资产配置数据结构。" }, "device-profile": { @@ -1389,8 +1525,6 @@ "delete": "删除设备配置", "copyId": "复制设备配置 ID", "name-max-length": "名称长度必须少于256个字符", - "new-device-profile-name": "设备配置名称", - "new-device-profile-name-required": "设备配置名称必填。", "name": "名称", "name-required": "名称是必需的。", "type": "配置类型", @@ -1409,6 +1543,7 @@ "transport-type-lwm2m-hint": "LWM2M传输类型", "transport-type-snmp": "SNMP", "transport-type-snmp-hint": "指定 SNMP 传输配置", + "transport-type-http": "HTTP", "description": "说明", "default": "默认", "profile-configuration": "配置", @@ -1426,7 +1561,7 @@ "set-default-device-profile-title": "确定要将设备配置 '{{deviceProfileName}}' 设为默认值吗?", "set-default-device-profile-text": "确认后,设备配置将被标记为默认,并将用于未指定配置的新设备。", "no-device-profiles-found": "未找到设备配置。", - "create-new-device-profile": "创建一个新的!", + "create-new-device-profile": "创建设备配置", "mqtt-device-topic-filters": "MQTT 设备 Topic 筛选器", "mqtt-device-topic-filters-unique": "MQTT设备 Topic 筛选器必须唯一。", "mqtt-device-topic-filters-spark-plug": "MQTT Sparkplug B边缘网络(EoN)节点", @@ -1507,6 +1642,9 @@ "condition-duration-value-required": "持续时间值必填。", "condition-duration-time-unit-required": "时间单位必填。", "advanced-settings": "高级设置", + "alarm-rule-additional-info": "附加信息", + "edit-alarm-rule-additional-info": "编辑附加信息", + "alarm-rule-additional-info-placeholder": "请在此处提供评论和调整,以便在附加信息下的告警详情中显示", "alarm-rule-additional-info-hint": "提示: 使用 ${keyName} 来替代告警规则条件中使用的属性或遥测键的值。", "alarm-rule-mobile-dashboard": "移动端仪表板", "alarm-rule-mobile-dashboard-hint": "作为移动端告警详情仪表板使用。", @@ -1523,7 +1661,7 @@ "provision-strategy": "预配置策略", "provision-strategy-required": "预配置策略必填。", "provision-strategy-disabled": "禁用", - "provision-strategy-created-new": "允许创建新设备", + "provision-strategy-created-new": "允许创建设备", "provision-strategy-check-pre-provisioned": "检查预配置的设备", "provision-device-key": "预配置设备密钥名", "provision-device-key-required": "预配置设备密钥名必填。", @@ -1536,8 +1674,8 @@ "provision-strategy-x509": { "certificate-chain": "X509 证书链", "certificate-chain-hint": "X.509 证书策略用于通过客户端证书在双向TLS通信中提供设备的方式。", - "allow-create-new-devices": "创建新设备", - "allow-create-new-devices-hint": "如果选择创建新设备,则将客户端证书用作设备凭据。", + "allow-create-new-devices": "创建设备", + "allow-create-new-devices-hint": "如果选择创建设备,则将客户端证书用作设备凭据。", "certificate-value": "PEM 格式的证书", "certificate-value-required": "PEM 格式的证书必填。", "cn-regex-variable": "CN 正则表达式变量", @@ -1582,8 +1720,8 @@ "create-device-profile": "创建设备配置", "import": "导入设备配置", "export": "导出设备配置", - "export-failed-error": "无法导出设备配置文件: {{error}}", - "device-profile-file": "设备配置文件", + "export-failed-error": "无法导出设备配置: {{error}}", + "device-profile-file": "设备配置", "invalid-device-profile-file-error": "无法导入设备配置:无效的设备配置数据结构。", "power-saving-mode": "节能模式", "power-saving-mode-type": { @@ -1692,7 +1830,7 @@ "account-after-timeout-required": "帐户超时必填。", "account-after-timeout-pattern": "帐户超时必须是一个正整数。", "account-after-timeout-tooltip": "Bootstrap-Server帐户资源的超时值。", - "server-type": "Server type", + "server-type": "服务器类型", "add-new-server-title": "添加新的服务器配置", "add-server-config": "添加服务器配置", "add-lwm2m-server-config": "添加LwM2M服务器", @@ -1840,6 +1978,8 @@ "make-private-edge-text": "确认后,边缘及其所有数据将被设为私有,不被其他人访问。", "import": "导入边缘", "install-connect-instructions": "安装和连接说明", + "install-connect-instructions-edge-created": "边缘已创建!请检查安装和连接说明", + "loading-edge-instructions": "正在加载边缘说明...", "label": "标签", "load-entity-error": "加载数据失败,实体已经被删除。", "assign-new-edge": "分配新边缘", @@ -1891,11 +2031,15 @@ "type-rule-chain-metadata": "规则链元数据", "type-edge": "边缘", "type-user": "用户", + "type-tenant": "租户", + "type-tenant-profile": "租户配置", "type-customer": "客户", "type-relation": "关联", "type-widgets-bundle": "部件包", "type-widgets-type": "部件类型", "type-admin-settings": "管理员设置", + "type-ota-package": "OTA包", + "type-queue": "队列", "action-type-added": "增加", "action-type-deleted": "删除", "action-type-updated": "更新", @@ -1911,6 +2055,8 @@ "action-type-rpc-call": "RPC调用", "action-type-alarm-ack": "告警确认", "action-type-alarm-clear": "告警清除", + "action-type-alarm-assigned": "告警已分配", + "action-type-alarm-unassigned": "告警未分配", "action-type-assigned-to-edge": "分配给边缘", "action-type-unassigned-from-edge": "取消分配边缘", "action-type-credentials-request": "认证请求", @@ -1927,6 +2073,7 @@ "entities-count": "实体数量", "alarms-count": "告警数量", "aliases": "实体别名", + "aliases-short": "别名", "entity-alias": "实体别名", "unable-delete-entity-alias-title": "无法删除实体别名", "unable-delete-entity-alias-text": "实体别名 '{{entityAlias}}' 被以下部件使用不能删除:
{{widgetsList}}", @@ -1942,6 +2089,7 @@ "entity-types": "实体类型", "entity-type-list": "实体类型列表", "any-entity": "任意实体", + "add-entity-type": "添加实体类型", "enter-entity-type": "输入实体类型", "no-entities-matching": "未找到匹配 '{{entity}}' 的实体。", "no-entity-types-matching": "未找到匹配 '{{entityType}}' 类型的实体。", @@ -1949,18 +2097,20 @@ "help-text": "根据需要可以使用'%'进行匹配,例如:'%entity_name_contains%', '%entity_name_ends', 'entity_starts_with'。", "use-entity-name-filter": "用户筛选器", "entity-list-empty": "没有选择实体。", + "entity-type-list-required": "至少应选择一个实体类型。", "entity-name-filter-required": "实体名筛选器必填。", "entity-name-filter-no-entity-matched": "未找到以 '{{entity}}' 开头的实体", "all-subtypes": "全部", "select-entities": "选择实体", "no-aliases-found": "未找到别名", "no-alias-matching": "未找到 '{{alias}}'", - "create-new-alias": "创建一个新的!", + "create-new-alias": "创建别名", + "create-new": "创建", "key": "键名", "key-name": "键名", "no-keys-found": "未找到键名", "no-key-matching": "未找到键名 '{{key}}'", - "create-new-key": "创建一个新的!", + "create-new-key": "创建键", "type": "类型", "type-required": "实体类型必填。", "type-device": "设备", @@ -1969,6 +2119,7 @@ "device-name-starts-with": "以 '{{prefix}}' 开头的设备", "type-device-profile": "设备配置", "type-device-profiles": "设备配置", + "clear-selected-profiles": "清除已选择的配置", "list-of-device-profiles": "{ count, plural, =1 {1 个设备配置} other {# 个设备配置} }", "device-profile-name-starts-with": "名称以 '{{prefix}}' 开头的设备配置", "type-asset-profile": "资产配置", @@ -2030,6 +2181,9 @@ "type-widgets-bundle": "部件包", "type-widgets-bundles": "部件包", "list-of-widgets-bundles": "{ count, plural, =1 {1 个部件包} other {# 个部件包} }", + "type-widget": "部件", + "type-widgets": "部件", + "list-of-widgets": "{ count, plural, =1 {1 个部件} other {# 个部件} }", "search": "实体检索", "selected-entities": "已选择 { count, plural, =1 {1 个实体} other {# 个实体} }", "entity-name": "实体名", @@ -2049,9 +2203,15 @@ "type-queue": "队列", "type-notification": "通知", "type-notification-rule": "通知规则", + "type-notification-rules": "通知规则", + "list-of-notification-rules": "{ count, plural, =1 {1 个通知规则} other {# 个通知规则} }", "type-notification-target": "通知收件人", + "type-notification-targets": "通知接收者", + "list-of-notification-targets": "{ count, plural, =1 {1 个通知接收者} other {# 个通知接收者} }", "type-notification-request": "通知请求", - "type-notification-template": "通知模板" + "type-notification-template": "通知模板", + "type-notification-templates": "通知模板", + "list-of-notification-templates": "{ count, plural, =1 {1 个通知模板} other {# 个通知模板} }" }, "entity-field": { "created-time": "创建时间", @@ -2082,8 +2242,8 @@ "no-aliases-found": "未找到别名。", "no-key-matching": "'{{key}}' 未找到。", "no-keys-found": "未找到密钥。", - "create-new-alias": "创建一个新的!", - "create-new-key": "创建一个新的!", + "create-new-alias": "创建别名", + "create-new-key": "创建键", "duplicate-alias-error": "找到重复别名 '{{alias}}'。
实体视图别名必须是唯一的。", "configure-alias": "配置 '{{alias}}' 别名", "no-entity-views-matching": "未找到与 '{{entity}}' 匹配的实体视图。", @@ -2410,6 +2570,7 @@ "add-filter-prompt": "请添加筛选器", "no-filter-matching": "未找到 '{{filter}}' 。", "create-new-filter": "请新增!", + "create-new": "创建", "filter-required": "筛选器必填。", "operation": { "operation": "操作", @@ -2454,7 +2615,10 @@ "attribute": "属性", "timeseries": "Timeseries", "entity-field": "实体", - "constant": "常量" + "constant": "常量", + "client-attribute": "客户端属性", + "server-attribute": "服务端属性", + "shared-attribute": "共享属性" }, "value-type": { "value-type": "值类型", @@ -2497,6 +2661,11 @@ }, "gateway": { "add-entry": "添加配置", + "advanced": "高级", + "checking-device-activity": "检查设备活动", + "command": "Docker命令", + "command-copied-message": "Docker命令已复制到剪贴板", + "configuration": "配置", "connector-add": "添加连接器", "connector-enabled": "启用连接器", "connector-name": "连接器名称", @@ -2504,31 +2673,140 @@ "connector-type": "连接器类型", "connector-type-required": "连接器类型必填。", "connectors": "连接器配置", - "create-new-gateway": "创建新网关", + "connectors-config": "连接器配置", + "connectors-table-enabled": "已启用", + "connectors-table-name": "名称", + "connectors-table-type": "类型", + "connectors-table-status": "状态", + "connectors-table-actions": "操作", + "connectors-table-key": "键", + "connectors-table-class": "类", + "rpc-command-send": "发送", + "rpc-command-result": "结果", + "rpc-command-edit-params": "编辑参数", + "gateway-configuration": "通用配置", + "create-new-gateway": "创建网关", "create-new-gateway-text": "确定要创建名为 '{{gatewayName}}' 的新网关?", + "created-time": "创建时间", + "configuration-delete-dialog-header": "配置将被删除", + "configuration-delete-dialog-body": "只有对网关进行物理访问时,才有可能关闭远程配置。所有先前的配置都将被删除。

\n要关闭配置,请在下面输入网关名称", + "configuration-delete-dialog-input": "网关名称", + "configuration-delete-dialog-input-required": "网关名称是必需的", + "configuration-delete-dialog-confirm": "关闭", "delete": "删除配置", "download-tip": "下载配置", + "drop-file": "将文件拖放到此处或", "gateway": "网关", "gateway-exists": "同名设备已存在。", "gateway-name": "网关名称", "gateway-name-required": "网关名称必填。", "gateway-saved": "已成功保存网关配置。", + "grpc": "GRPC", + "grpc-keep-alive-timeout": "保持连接超时(毫秒)", + "grpc-keep-alive-timeout-required": "需要保持连接超时", + "grpc-keep-alive-timeout-min": "保持连接超时不能小于1", + "grpc-keep-alive-timeout-pattern": "保持连接超时无效", + "grpc-keep-alive": "保持连接(毫秒)", + "grpc-keep-alive-required": "需要保持连接", + "grpc-keep-alive-min": "保持连接不能小于1", + "grpc-keep-alive-pattern": "保持连接无效", + "grpc-min-time-between-pings": "最小Ping间隔(毫秒)", + "grpc-min-time-between-pings-required": "需要最小Ping间隔", + "grpc-min-time-between-pings-min": "最小Ping间隔不能小于1", + "grpc-min-time-between-pings-pattern": "最小Ping间隔无效", + "grpc-min-ping-interval-without-data": "无数据时的最小Ping间隔(毫秒)", + "grpc-min-ping-interval-without-data-required": "需要无数据时的最小Ping间隔", + "grpc-min-ping-interval-without-data-min": "无数据时的最小Ping间隔不能小于1", + "grpc-min-ping-interval-without-data-pattern": "无数据时的最小Ping间隔无效", + "grpc-max-pings-without-data": "无数据时的最大Ping数", + "grpc-max-pings-without-data-required": "需要无数据时的最大Ping数", + "grpc-max-pings-without-data-min": "无数据时的最大Ping数不能小于1", + "grpc-max-pings-without-data-pattern": "无数据时的最大Ping数无效", + "inactivity-check-period-seconds": "不活跃检查期(秒)", + "inactivity-check-period-seconds-required": "需要不活跃检查期", + "inactivity-check-period-seconds-min": "不活跃检查期不能小于1", + "inactivity-check-period-seconds-pattern": "不活跃检查期无效", + "inactivity-timeout-seconds": "不活跃超时(秒)", + "inactivity-timeout-seconds-required": "需要不活跃超时", + "inactivity-timeout-seconds-min": "不活跃超时不能小于1", + "inactivity-timeout-seconds-pattern": "不活跃超时无效", "json-parse": "无效的JSON。", "json-required": "字段不能为空。", + "logs": { + "logs": "日志", + "days": "天", + "hours": "小时", + "minutes": "分钟", + "seconds": "秒", + "date-format": "日期格式", + "date-format-required": "需要日期格式", + "log-format": "日志格式", + "log-type": "日志类型", + "log-format-required": "需要日志格式", + "remote": "远程日志记录", + "remote-logs": "远程日志", + "local": "本地日志记录", + "level": "日志级别", + "file-path": "文件路径", + "file-path-required": "需要文件路径", + "saving-period": "日志保存期限", + "saving-period-min": "日志保存期限不能小于1", + "saving-period-required": "需要日志保存期限", + "backup-count": "备份数量", + "backup-count-min": "备份数量不能小于1", + "backup-count-required": "需要备份数量" + }, + "min-pack-send-delay": "最小包发送延迟(毫秒)", + "min-pack-send-delay-required": "最小包发送延迟是必需的", + "min-pack-send-delay-min": "最小包发送延迟不能小于0", "no-connectors": "无连接器", "no-data": "没有配置", "no-gateway-found": "未找到网关。", "no-gateway-matching": "未找到 '{{item}}' 。", "path-logs": "日志文件的路径", "path-logs-required": "路径是必需的。", + "permit-without-calls": "保持连接许可,无需响应", "remote": "远程配置", "remote-logging-level": "日志记录级别", "remove-entry": "删除配置", + "remote-shell": "远程Shell", + "remote-configuration": "远程配置", + "other": "其他", "save-tip": "保存配置", "security-type": "安全类型", "security-types": { "access-token": "访问令牌", - "tls": "TLS" + "username-password": "用户名和密码", + "tls": "TLS", + "tls-access-token": "TLS + 访问令牌", + "tls-private-key": "TLS + 私钥" + }, + "server-port": "服务器端口", + "statistics": { + "statistic": "统计信息", + "statistics": "统计信息", + "statistic-commands-empty": "无可用统计信息", + "commands": "命令", + "send-period": "统计信息发送周期(秒)", + "send-period-required": "统计信息发送周期是必需的", + "send-period-min": "统计信息发送周期不能小于60", + "send-period-pattern": "统计信息发送周期无效", + "check-connectors-configuration": "检查连接器配置(秒)", + "check-connectors-configuration-required": "检查连接器配置是必需的", + "check-connectors-configuration-min": "检查连接器配置不能小于1", + "check-connectors-configuration-pattern": "检查连接器配置无效", + "add": "添加命令", + "timeout": "超时时间", + "timeout-ms": "超时时间(毫秒)", + "timeout-required": "超时时间是必需的", + "timeout-min": "超时时间不能小于1", + "timeout-pattern": "超时时间无效", + "attribute-name": "属性名称", + "attribute-name-required": "属性名称是必需的", + "command": "命令", + "command-required": "命令是必需的", + "command-pattern": "命令无效", + "remove": "删除命令" }, "storage": "存储", "storage-max-file-records": "文件中的最大记录数", @@ -2540,6 +2818,16 @@ "storage-max-records-min": "最小记录数为1。", "storage-max-records-pattern": "数字无效。", "storage-max-records-required": "最大记录项必填。", + "storage-read-record-count": "存储中的读取记录数", + "storage-read-record-count-min": "最小记录数为1。", + "storage-read-record-count-pattern": "数字不合法。", + "storage-read-record-count-required": "需要读取记录数。", + "storage-max-read-record-count": "存储中的最大读取记录数", + "storage-max-read-record-count-min": "最小记录数为1。", + "storage-max-read-record-count-pattern": "数字不合法。", + "storage-max-read-record-count-required": "最大读取记录数必需。", + "storage-data-folder-path": "数据文件夹路径", + "storage-data-folder-path-required": "需要数据文件夹路径。", "storage-pack-size": "最大事件包大小", "storage-pack-size-min": "最小值为1。", "storage-pack-size-pattern": "数字无效。", @@ -2549,9 +2837,11 @@ "storage-type": "存储类型", "storage-types": { "file-storage": "文件存储", - "memory-storage": "内存存储" + "memory-storage": "内存存储", + "sqlite": "SQLITE" }, "thingsboard": "ThingsBoard", + "general": "常规", "thingsboard-host": "ThingsBoard主机", "thingsboard-host-required": "主机必填。", "thingsboard-port": "ThingsBoard端口", @@ -2564,10 +2854,61 @@ "title-connectors-json": "连接器 {{typeName}} 配置", "tls-path-ca-certificate": "网关上CA证书的路径", "tls-path-client-certificate": "网关上客户端证书的路径", + "messages-ttl-check-in-hours": "消息TTL检查小时数", + "messages-ttl-check-in-hours-required": "需要提供消息TTL检查小时数。", + "messages-ttl-check-in-hours-min": "最小值为1。", + "messages-ttl-check-in-hours-pattern": "数字无效。", + "messages-ttl-in-days": "消息TTL天数", + "messages-ttl-in-days-required": "需要提供消息TTL天数。", + "messages-ttl-in-days-min": "最小值为1。", + "messages-ttl-in-days-pattern": "数字无效。", + "mqtt-qos": "QoS", + "mqtt-qos-required": "需要提供QoS", + "mqtt-qos-range": "QoS值的范围是从0到1", "tls-path-private-key": "网关上私钥的路径", "toggle-fullscreen": "切换全屏", "transformer-json-config": "配置JSON*", - "update-config": "添加/更新配置JSON" + "update-config": "添加/更新配置JSON", + "hints": { + "remote-configuration": "启用对网关的远程配置和管理", + "remote-shell": "通过远程Shell小部件启用对网关操作系统的远程控制", + "host": "ThingsBoard 主机名或IP地址", + "port": "ThingsBoard MQTT服务端口", + "token": "ThingsBoard 网关访问令牌", + "client-id": "ThingsBoard 网关MQTT客户端ID", + "username": "ThingsBoard 网关MQTT用户名", + "password": "ThingsBoard 网关MQTT密码", + "ca-cert": "CA证书文件的路径", + "date-form": "日志消息中的日期格式", + "data-folder": "包含数据的文件夹的路径(相对或绝对路径)", + "log-format": "日志消息格式", + "remote-log": "启用对网关的远程日志记录和日志读取", + "backup-count": "如果备份计数大于0,则在执行轮换时,最多保留备份计数个文件-最旧的文件将被删除", + "storage": "提供将数据发送到平台之前保存传入数据的配置", + "max-file-count": "将创建的文件的最大数量", + "max-read-count": "从存储中获取的消息计数并发送到ThingsBoard", + "max-records": "一个文件中存储的最大记录数", + "read-record-count": "从存储中获取的消息计数并发送到ThingsBoard", + "max-records-count": "在将数据发送到ThingsBoard之前,存储中的最大数据计数", + "ttl-check-hour": "网关多久检查一次数据是否过时", + "ttl-messages-day": "存储将保存数据的最大天数", + "commands": "用于收集附加统计信息的命令", + "attribute": "统计遥测键", + "timeout": "命令执行的超时时间", + "command": "命令执行的结果,将用作遥测的值", + "check-device-activity": "启用监视每个连接设备的活动", + "inactivity-timeout": "在此时间后,网关将断开设备的连接", + "inactivity-period": "设备活动检查的周期", + "minimal-pack-delay": "发送消息包之间的延迟(减小此设置会导致增加CPU使用率)", + "qos": "MQTT消息传递的服务质量(0-至多一次,1-至少一次)", + "server-port": "GRPC服务器侦听传入连接的网络端口", + "grpc-keep-alive-timeout": "在考虑连接死亡之前,服务器等待keepalive ping响应的最长时间", + "grpc-keep-alive": "没有活动RPC调用时两个连续keepalive ping消息之间的持续时间", + "grpc-min-time-between-pings": "服务器在发送keepalive ping消息之间应等待的最小时间量", + "grpc-max-pings-without-data": "在没有接收到任何数据之前,服务器可以发送的keepalive ping消息的最大数量,然后将连接视为死亡", + "grpc-min-ping-interval-without-data": "在没有发送或接收数据时,服务器在发送keepalive ping消息之间应等待的最小时间量", + "permit-without-calls": "允许服务器在没有活动RPC调用时保持GRPC连接活动" + } }, "grid": { "delete-item-title": "确定要删除此项吗?", @@ -2599,8 +2940,10 @@ "browse-files": "浏览文件" }, "image-input": { - "drop-image-or": "拖放一张图片或者", "drop-images-or": "拖放一张或多张图片", + "drag-and-drop": "拖放", + "or": "或", + "browse": "浏览", "no-images": "未选择任何图片", "images": "图片" }, @@ -2651,6 +2994,12 @@ "lwm2m-server-secret-key": "LwM2M server证书密钥", "lwm2m-server-public-key-id": "LwM2M server公钥" }, + "snmp": { + "host": "SNMP 主机地址", + "port": "SNMP 端口", + "version": "SNMP 版本 (例如:v1, v2c, 或 v3)", + "community-string": "SNMP 团体字符串" + }, "isgateway": "是否网关", "activity-time-from-gateway-device": "来自网关设备的活动时间", "description": "说明", @@ -2661,7 +3010,7 @@ "select-file": "选择一个文件", "configuration": "导入配置", "column-type": "选择列类型", - "creat-entities": "创建新实体" + "creat-entities": "创建实体" }, "message": { "create-entities": "{{count}} 个新实体已成功创建。", @@ -2687,6 +3036,7 @@ }, "layout": { "layout": "布局", + "layouts": "布局", "manage": "布局管理", "settings": "布局设置", "color": "颜色", @@ -2712,6 +3062,12 @@ "legend": { "direction": "图例方向", "position": "图例位置", + "show-values": "显示数值", + "min-option": "最小值", + "max-option": "最大值", + "average-option": "平均值", + "total-option": "总数", + "latest-option": "最新值", "sort-legend": "在图例中排序数据键", "show-max": "显示最大值", "show-min": "显示最小值", @@ -2731,7 +3087,9 @@ "weeks": "(一周前)", "months": "(一个月前)", "years": "(一年前)" - } + }, + "label": "标签", + "value": "值" }, "login": { "login": "登录", @@ -2746,7 +3104,7 @@ "remember-me": "记住我", "forgot-password": "忘记密码?", "password-reset": "密码重置", - "expired-password-reset-message": "您的凭据已过期!请创建新密码。", + "expired-password-reset-message": "您的凭据已过期!请创建密码。", "new-password": "新密码", "new-password-again": "再次输入新密码", "password-link-sent-message": "密码重置链接已成功发送!", @@ -2793,6 +3151,7 @@ "api-feature-hint": "如果字段为空,则触发器将应用于所有API功能", "api-usage-trigger-settings": "API使用触发设置", "new-platform-version-trigger-settings": "新平台版本触发设置", + "rate-limits-trigger-settings": "超出速率限制触发设置", "at-least-one-should-be-selected": "至少需要选择一个", "basic-settings": "基本设置", "button-text": "按钮文本", @@ -2833,6 +3192,8 @@ "email-preview": "Email 通知预览", "slack": "Slack", "slack-preview": "Slack 通知预览", + "microsoft-teams" : "Microsoft Teams", + "microsoft-teams-preview" : "Microsoft Teams 通知预览", "sms": "SMS", "sms-preview": "SMS 通知预览", "web": "Web", @@ -2870,6 +3231,7 @@ "dashboard": "打开仪表板", "link": "打开URL链接" }, + "loading-notifications": "加载通知中…", "management": "通知管理", "mark-all-as-read": "全部标记为已读", "mark-as-read": "标记为已读", @@ -2910,20 +3272,20 @@ "only-rule-chain-lifecycle-failures": "仅在规则链生命周期故障时通知", "only-rule-node-lifecycle-failures": "仅在规则节点生命周期故障时通知", "platform-users": "平台用户", + "rate-limits": "速率限制", + "rate-limits-hint": "如果该字段为空,则触发器将应用于所有速率限制", "recipient": "收件人", "recipient-group": "收件人组", "recipient-type": { "affected-tenant-administrators": "受影响的租户管理员", "affected-user": "受影响的用户", - "affected-user-hint": "受影响用户的提示", "all-users": "所有用户", "customer-users": "客户用户", "system-administrators": "系统管理员", "tenant-administrators": "租户管理员", "user-filters": "用户筛选器", "user-list": "用户列表", - "users-entity-owner": "实体所有者的用户", - "users-entity-owner-hint": "实体所有者用户的提示" + "users-entity-owner": "实体所有者的用户" }, "recipients": "收件人", "notification-recipients": "通知 / 收件人", @@ -2943,6 +3305,8 @@ "rule-engine-filter": "规则引擎筛选器", "rule-name": "规则名称", "rule-name-required": "名称必填。", + "rule-disable": "禁用通知规则", + "rule-enable": "启用通知规则", "rule-node-filter": "规则节点筛选器", "rules": "规则", "notification-rules": "通知 / 规则", @@ -2986,13 +3350,15 @@ "general": "通用", "rule-engine-lifecycle-event": "规则引擎生命周期事件", "rule-node": "规则节点", - "new-platform-version": "新的平台版本" + "new-platform-version": "新的平台版本", + "rate-limits": "超过速率限制" }, "templates": "模板", "notification-templates": "通知 / 模板", - "tenant-profiles-list-rule-hint": "如果字段为空,触发器将应用于所有租户配置文件", + "tenant-profiles-list-rule-hint": "如果字段为空,触发器将应用于所有租户配置", "tenants-list-rule-hint": "如果字段为空,触发器将应用于所有租户", "threshold": "阈值", + "theme-color": "主题颜色", "time": "时间", "track-rule-node-events": "追踪规则节点事件", "trigger": { @@ -3005,6 +3371,7 @@ "entity-action": "实体操作", "rule-engine-lifecycle-event": "规则引擎生命周期事件", "new-platform-version": "新的平台版本", + "rate-limits": "超过速率限制", "trigger": "触发器", "trigger-required": "触发器必填。" }, @@ -3013,7 +3380,21 @@ "updated": "已更新", "use-template": "使用模板", "view-all": "查看全部", - "warning": "警告" + "warning": "警告", + "webhook-url": "Webhook URL", + "webhook-url-required": "需要填写Webhook URL", + "channel-name": "频道名称", + "channel-name-required": "需要填写频道名称", + "settings": { + "notification-settings": "通知设置", + "reset-all": "重置全部设置", + "reset-all-title": "您确定要将表单重置吗?", + "reset-all-text": "确认后,设置表单将重置为默认值并保存。", + "type": "类型", + "enable-all": "全部启用", + "disable-all": "全部禁用", + "delivery-not-configured": "未配置传递方式" + } }, "ota-update": { "add": "添加包", @@ -3028,7 +3409,7 @@ "checksum-copied-message": "包校验和已复制到剪贴板", "change-firmware": "固件的更改可能会导致 { count, plural, =1 {1 个设备} other {# 个设备} } 的更新。", "change-software": "软件的更改可能会导致 { count, plural, =1 {1 个设备} other {# 个设备} } 的更新。", - "chose-compatible-device-profile": "上传的包仅适用于具有所选配置文件的设备。", + "chose-compatible-device-profile": "上传的包仅适用于具有所选配置的设备。", "chose-firmware-distributed-device": "选择将分发到设备的固件", "chose-software-distributed-device": "选择将分发到设备的软件", "content-type": "内容类型", @@ -3103,6 +3484,13 @@ "security": { "security": "安全", "general-settings": "通用安全设置", + "access-token": "访问令牌", + "access-token-required": "需要访问令牌", + "clientId": "客户端ID", + "clientId-required": "需要客户端ID", + "username": "用户名", + "username-required": "需要用户名", + "ca-cert": "CA证书", "2fa": { "2fa": "双因素认证", "2fa-description": "双因素认证可保护您的帐户免受未经授权的访问。在登录时必须输入安全验证码。", @@ -3175,6 +3563,7 @@ "relation": { "relations": "关联", "direction": "方向", + "clear-relation-type": "清除关系类型", "search-direction": { "FROM": "从", "TO": "到" @@ -3209,6 +3598,7 @@ "delete-from-relations-title": "确定删除 { count, plural, =1 {1 个关联} other {# 个关联} } 吗?", "delete-from-relations-text": "确定删除所有选择的关联关系后,当前实体将与对应的实体取消关联", "remove-relation-filter": "移除关联筛选器", + "remove-filter": "移除过滤器", "add-relation-filter": "添加关联筛选器", "any-relation": "任意关联", "relation-filters": "关联筛选器", @@ -3218,6 +3608,7 @@ }, "resource": { "add": "添加资源", + "all-types": "全部", "copyId": "复制资源ID", "delete": "删除资源", "delete-resource-text": "请注意:确认后,资源将不可恢复。", @@ -3243,7 +3634,13 @@ "system": "系统", "title": "标题", "title-required": "标题是必填项。", - "title-max-length": "标题长度应该少于256个字符。" + "title-max-length": "标题长度应该少于256个字符。", + "type": { + "jks": "JKS", + "js-module": "JS 模块", + "lwm2m-model": "LWM2M 模型", + "pkcs-12": "PKCS #12" + } }, "rulechain": { "rulechain": "规则链", @@ -3273,7 +3670,7 @@ "import": "导入规则链", "export": "导出规则链", "export-failed-error": "无法导出规则链:{{error}}", - "create-new-rulechain": "创建新的规则链", + "create-new-rulechain": "创建规则链", "rulechain-file": "规则链文件", "invalid-rulechain-file-error": "不能导入规则链:无效的规则链数据格式。", "copyId": "复制规则链ID", @@ -3286,7 +3683,6 @@ "search": "查找规则链", "selected-rulechains": "已选择 { count, plural, =1 {1 个规则链} other {# 个规则链} }", "open-rulechain": "打开规则链", - "assign-new-rulechain": "分配新的规则链", "edge-template-root": "模版根链", "assign-to-edge": "分配给边缘", "edge-rulechain": "边缘规则链", @@ -3314,11 +3710,13 @@ "events": "事件", "search": "查找节点", "open-node-library": "打开节点库", + "close-node-library": "关闭节点库", "add": "添加规则节点", "name": "名称", "name-required": "名称必填。", "name-max-length": "名称长度应该少于256个字符。", "type": "类型", + "rule-node-description": "规则节点描述", "delete": "删除规则节点", "select-all-objects": "选择所有节点和连接", "deselect-all-objects": "取消选择所有节点和连接", @@ -3343,7 +3741,7 @@ "link-labels-required": "链接标签必填。", "no-link-labels-found": "未找到链接标签", "no-link-label-matching": "未找到匹配 '{{label}}' 的链接标签。", - "create-new-link-label": "创建一个新的!", + "create-new-link-label": "创建链接标签", "type-filter": "筛选器", "type-filter-details": "使用配置条件筛选传入消息", "type-enrichment": "属性集", @@ -3377,7 +3775,8 @@ "output": "输出", "test": "测试", "help": "帮助", - "reset-debug-mode": "重置所有节点中的调试模式" + "reset-debug-mode": "重置所有节点中的调试模式", + "test-with-this-message": "使用此消息进行{{test}}测试" }, "timezone": { "timezone": "时区", @@ -3451,6 +3850,8 @@ "description": "说明", "description-hint": "此文本将显示在队列说明中,而不是所选策略中", "alt-description": "提交策略:{{submitStrategy}},处理策略:{{processingStrategy}}", + "custom-properties": "自定义属性", + "custom-properties-hint": "自定义队列(主题)创建属性,例如 'retention.ms:604800000;retention.bytes:1048576000'", "strategies": { "sequential-by-originator-label": "按发起者顺序处理", "sequential-by-originator-hint": "在确认设备A的前一条消息之前,不会提交设备A的新消息", @@ -3551,12 +3952,12 @@ "set-default-tenant-profile-title": "确定要将租户配置 '{{tenantProfileName}}' 设为默认值吗?", "set-default-tenant-profile-text": "确认后,此租户配置将被标记为默认配置,并将用于未指定配置的新租户。", "no-tenant-profiles-found": "未找到租户配置。", - "create-new-tenant-profile": "创建一个新的!", - "create-tenant-profile": "创建新的租户配置", + "create-new-tenant-profile": "创建租户配置", + "create-tenant-profile": "创建租户配置", "import": "导入租户配置", "export": "导出租户配置", "export-failed-error": "无法导出租户配置: {{error}}", - "tenant-profile-file": "租户配置文件", + "tenant-profile-file": "租户配置", "invalid-tenant-profile-file-error": "无法导入租户配置:无效的租户配置数据结构。", "advanced-settings": "高级设置", "entities": "实体", @@ -3612,6 +4013,9 @@ "max-j-s-executions": "最大 JavaScript 执行数", "max-j-s-executions-required": "最大 JavaScript 执行数必填。", "max-j-s-executions-range": "最大 JavaScript 执行数不能为负数", + "max-tbel-executions": "最大 TBEL 执行数", + "max-tbel-executions-required": "需要指定最大 TBEL 执行数。", + "max-tbel-executions-range": "最大 TBEL 执行数不能为负数。", "max-d-p-storage-days": "最大存储点天", "max-d-p-storage-days-required": "最大存储点天必填。", "max-d-p-storage-days-range": "最大存储点天不能为负数", @@ -3624,12 +4028,19 @@ "rpc-ttl-days": "RPC TTL天数", "rpc-ttl-days-required": "RPC TTL天数必填。", "rpc-ttl-days-days-range": "RPC TTL天数不能为负数", + "queue-stats-ttl-days": "队列统计信息TTL天数", + "queue-stats-ttl-days-required": "需要指定队列统计信息TTL天数", + "queue-stats-ttl-days-range": "队列统计信息TTL天数不能为负数", + "rule-engine-exceptions-ttl-days": "规则引擎异常TTL天数", + "rule-engine-exceptions-ttl-days-required": "需要指定规则引擎异常TTL天数", + "rule-engine-exceptions-ttl-days-range": "规则引擎异常TTL天数不能为负数", "max-rule-node-executions-per-message": "每条消息的最大规则节点执行数", "max-rule-node-executions-per-message-required": "每个消息的最大规则节点执行数必填。", "max-rule-node-executions-per-message-range": "每条消息的最大规则节点执行数不能为负", "max-emails": "最大电子邮件发送数", "max-emails-required": "最大电子邮件发送数必填。", "max-emails-range": "最大电子邮件发送数不能为负", + "sms-enabled": "启用短信", "max-sms": "最大短信发送数", "max-sms-required": "最大短信发送数必填。", "max-sms-range": "最大短信发送数不能为负", @@ -3740,16 +4151,24 @@ "days": "天" }, "timewindow": { + "timewindow": "时间窗口", "years": "{ years, plural, =1 {1 年 } other {# 年 } }", - "months": "{ months, plural, =1 { 月 } other {# 月 } }", - "weeks": "{ weeks, plural, =1 { 周 } other {# 周 } }", + "years-short": "{{ years }}y", + "months": "{ months, plural, =1 {1 月 } other {# 月 } }", + "months-short": "{{ months }}M", + "weeks": "{ weeks, plural, =1 {1 周 } other {# 周 } }", + "weeks-short": "{{ weeks }}w", "days": "{ days, plural, =1 {1 天 } other {# 天 } }", + "days-short": "{{ days }}d", "hours": "{ hours, plural, =0 {- 小时 } =1 {1 小时 } other {# 小时 } }", "hr": "{{ hr }} 时", + "hr-short": "{{ hr }}h", "minutes": "{ minutes, plural, =0 {- 分 } =1 {1 分 } other {# 分 } }", "min": "{{ min }} 分", + "min-short": "{{ min }}m", "seconds": "{ seconds, plural, =0 {- 秒 } =1 {1 秒 } other {# 秒 } }", "sec": "{{ sec }} 秒", + "sec-short": "{{ sec }}s", "short": { "days": "{ days, plural, =1 {1 天 } other {# 天 } }", "hours": "{ hours, plural, =1 {1 小时 } other {# 小时 } }", @@ -3768,7 +4187,426 @@ "hide": "隐藏", "interval": "区间", "just-now": "刚刚", - "ago": "之前" + "just-now-lower": "刚刚", + "ago": "之前", + "style": "时间窗口样式", + "icon": "图标", + "icon-position": "图标位置", + "icon-position-left": "左侧", + "icon-position-right": "右侧", + "font": "字体", + "color": "颜色", + "displayTypePrefix": "显示实时/历史前缀", + "preview": "预览" + }, + "tooltip": { + "value": "值", + "date": "日期", + "background-color": "背景颜色", + "background-blur": "背景模糊" + }, + "unit": { + "millimeter": "mm", + "centimeter": "cm", + "angstrom": "Å", + "nanometer": "nm", + "micrometer": "μm", + "meter": "m", + "kilometer": "km", + "inch": "in", + "foot": "ft", + "yard": "yd", + "mile": "mi", + "nautical-mile": "nmi", + "astronomical-unit": "au", + "reciprocal-metre": "m⁻¹", + "meter-per-meter": "m/m", + "steradian": "sr", + "thou": "th", + "barleycorn": "bc", + "hand": "hd", + "chain": "ch", + "furlong": "fur", + "league": "lea", + "fathom": "fath", + "cable": "cb", + "link": "li", + "rod": "rd", + "nanogram": "ng", + "microgram": "μg", + "milligram": "mg", + "gram": "g", + "kilogram": "kg", + "tonne": "t", + "ounce": "oz", + "pound": "lb", + "stone": "st", + "hundredweight-count": "cwt", + "short-tons": "s.t.", + "dalton": "Da", + "grain": "gr", + "drachm": "dr", + "quarter": "qr", + "slug": "slug", + "carat": "ct", + "cubic-millimeter": "mm³", + "cubic-centimeter": "cm³", + "cubic-meter": "m³", + "cubic-kilometer": "km³", + "microliter": "μL", + "milliliter": "mL", + "liter": "L", + "hectoliter": "hL", + "cubic-inch": "in³", + "cubic-foot": "ft³", + "cubic-yard": "yd³", + "fluid-ounce": "fl oz", + "pint": "pt", + "quart": "qt", + "gallon": "gal", + "oil-barrels": "bbl", + "cubic-meter-per-kilogram": "m³/kg", + "gill": "gi", + "hogshead": "hhd", + "teaspoon": "tsp", + "tablespoon": "tbsp", + "cup": "cup", + "celsius": "°C", + "kelvin": "K", + "rankine": "°R", + "fahrenheit": "°F", + "percent": "%", + "meter-per-second": "m/s", + "kilometer-per-hour": "km/h", + "foot-per-second": "ft/s", + "mile-per-hour": "mph", + "knot": "kn", + "millimeters-per-minute": "mm/min", + "kilometer-per-hour-squared": "km/h²", + "foot-per-second-squared": "ft/s²", + "pascal": "Pa", + "kilopascal": "kPa", + "megapascal": "MPa", + "gigapascal": "GPa", + "millibar": "mbar", + "bar": "bar", + "kilobar": "kbar", + "newton": "N", + "newton-meter": "N·m", + "foot-pounds": "ft·lbf", + "inch-pounds": "in·lbf", + "newton-per-meter": "N/m", + "atmospheres": "atm", + "pounds-per-square-inch": "psi", + "torr": "Torr", + "inches-of-mercury": "inHg", + "pascal-per-square-meter": "Pa/m²", + "pound-per-square-inch": "psi", + "newton-per-square-meter": "N/m²", + "kilogram-force-per-square-meter": "kgf/m²", + "pascal-per-square-centimeter": "Pa/cm²", + "ton-force-per-square-inch": "tonf/in²", + "kilonewton-per-square-meter": "kN/m²", + "newton-per-square-millimeter": "N/mm²", + "microjoule": "μJ", + "millijoule": "mJ", + "joule": "J", + "kilojoule": "kJ", + "megajoule": "MJ", + "gigajoule": "GJ", + "watt-hour": "Wh", + "kilowatt-hour": "kWh", + "electron-volts": "eV", + "joules-per-coulomb": "J/C", + "british-thermal-unit": "BTU", + "foot-pound": "ft·lb", + "calorie": "cal", + "small-calorie": "cal", + "kilocalorie": "kcal", + "joule-per-kelvin": "J/K", + "joule-per-kilogram-kelvin": "J/(kg·K)", + "joule-per-kilogram": "J/kg", + "watt-per-meter-kelvin": "W/(m·K)", + "joule-per-cubic-meter": "J/m³", + "therm": "thm", + "electric-dipole-moment": "Debye", + "magnetic-dipole-moment": "Am²", + "debye": "D", + "coulomb-per-square-meter-per-volt": "C/(m²·V)", + "milliwatt": "mW", + "microwatt": "μW", + "watt": "W", + "kilowatt": "kW", + "megawatt": "MW", + "gigawatt": "GW", + "metric-horsepower": "PS", + "milliwatt-per-square-centimeter": "mW/cm²", + "watt-per-square-centimeter": "W/cm²", + "kilowatt-per-square-centimeter": "kW/cm²", + "milliwatt-per-square-meter": "mW/m²", + "watt-per-square-meter": "W/m²", + "kilowatt-per-square-meter": "kW/m²", + "watt-per-square-inch": "W/in²", + "kilowatt-per-square-inch": "kW/in²", + "horsepower": "hp", + "btu-per-hour": "BTU/h", + "coulomb": "C", + "millicoulomb": "mC", + "microcoulomb": "μC", + "picocoulomb": "pC", + "coulomb-per-meter": "C/m", + "coulomb-per-cubic-meter": "C/m³", + "coulomb-per-square-meter": "C/m²", + "square-millimeter": "mm²", + "square-centimeter": "cm²", + "square-meter": "m²", + "hectare": "ha", + "square-kilometer": "km²", + "square-inch": "in²", + "square-foot": "ft²", + "square-yard": "yd²", + "acre": "ac", + "square-mile": "mi²", + "are": "a", + "barn": "b", + "circular-inch": "c in²", + "milliampere-hour": "mAh", + "ampere-hours": "Ah", + "kiloampere-hours": "kAh", + "nanoampere": "nA", + "picoampere": "pA", + "microampere": "μA", + "milliampere": "mA", + "ampere": "A", + "kiloamperes": "kA", + "microampere-per-square-centimeter": "μA/cm²", + "ampere-per-square-meter": "A/m²", + "ampere-per-meter": "A/m", + "oersted": "Oe", + "bohr-magneton": "μB", + "ampere-meter-squared": "A·m²", + "ampere-meter": "A·m", + "nanovolt": "nV", + "picovolt": "pV", + "millivolts": "mV", + "microvolts": "μV", + "volt": "V", + "kilovolts": "kV", + "dbmV": "dBmV", + "dbm": "dBm", + "volt-meter": "V·m", + "kilovolt-meter": "kV·m", + "megavolt-meter": "MV·m", + "microvolt-meter": "μV·m", + "millivolt-meter": "mV·m", + "nanovolt-meter": "nV·m", + "ohm": "Ω", + "microohm": "μΩ", + "milliohm": "mΩ", + "kilohm": "kΩ", + "megohm": "MΩ", + "gigohm": "GΩ", + "hertz": "Hz", + "kilohertz": "kHz", + "megahertz": "MHz", + "gigahertz": "GHz", + "rpm": "rpm", + "candela-per-square-meter": "cd/m²", + "candela": "cd", + "lumen": "lm", + "lux": "lx", + "foot-candle": "fc", + "lumen-per-square-meter": "lm/m²", + "lux-second": "lx·s", + "lumen-second": "lm·s", + "lumens-per-watt": "lm/W", + "absorbance": "AU", + "mole": "mol", + "nanomole": "nmol", + "micromole": "μmol", + "millimole": "mmol", + "kilomole": "kmol", + "mole-per-cubic-meter": "mol/m³", + "rssi": "RSSI", + "ppm": "ppm", + "ppb": "ppb", + "micrograms-per-cubic-meter": "μg/m³", + "aqi": "AQI", + "gram-per-cubic-meter": "g/m³", + "gram-per-kilogram": "g/kg", + "millimeters-per-second": "mm/s", + "neper": "Np", + "bel": "B", + "decibel": "dB", + "meters-per-second-squared": "m/s²", + "becquerel": "Bq", + "curie": "Ci", + "gray": "Gy", + "sievert": "Sv", + "roentgen": "R", + "cps": "cps", + "rad": "rad", + "rem": "rem", + "dps": "dps", + "rutherford": "Rd", + "coulombs-per-kilogram": "C/kg", + "becquerels-per-cubic-meter": "Bq/m³", + "curies-per-liter": "Ci/L", + "becquerels-per-second": "Bq/s", + "curies-per-second": "Ci/s", + "gy-per-second": "Gy/s", + "watt-per-steradian": "W/sr", + "watt-per-square-metre-steradian": "W/(m²·sr)", + "ph-level": "pH", + "turbidity": "NTU", + "mg-per-liter": "mg/L", + "microsiemens-per-centimeter": "μS/cm", + "millisiemens-per-meter": "mS/m", + "siemens-per-meter": "S/m", + "kilogram-per-cubic-meter": "kg/m³", + "gram-per-cubic-centimeter": "g/cm³", + "kilogram-per-square-meter": "kg/m²", + "milligram-per-milliliter": "mg/mL", + "pound-per-cubic-foot": "lb/ft³", + "ounces-per-cubic-inch": "oz/in³", + "tons-per-cubic-yard": "ton/yd³", + "particle-density": "PD", + "kilometers-per-liter": "km/L", + "miles-per-gallon": "mpg", + "liters-per-100-km": "L/100 km", + "gallons-per-mile": "gal/mi", + "liters-per-hour": "L/h", + "gallons-per-hour": "gal/h", + "beats-per-minute": "bpm", + "millimeters-of-mercury": "mmHg", + "milligrams-per-deciliter": "mg/dL", + "g-force": "G", + "kilonewton": "kN", + "kilogram-force": "kgf", + "pound-force": "lbf", + "kilopound-force": "kip", + "dyne": "dyn", + "poundal": "pdl", + "kip": "kip", + "gal": "Gal", + "gravity": "g₀", + "hectopascal": "hPa", + "atmosphere": "atm", + "millibars": "mbar", + "inch-of-mercury": "inHg", + "richter-scale": "Richter", + "second": "s", + "minute": "min", + "hour": "hr", + "day": "day", + "week": "wk", + "month": "mo", + "year": "yr", + "cubic-foot-per-minute": "ft³/min", + "cubic-meters-per-hour": "m³/h", + "cubic-meters-per-second": "m³/s", + "liter-per-second": "L/s", + "liter-per-minute": "L/min", + "gallons-per-minute": "GPM", + "cubic-foot-per-second": "ft³/s", + "milliliters-per-minute": "mL/min", + "bit": "bit", + "byte": "B", + "kilobyte": "KB", + "megabyte": "MB", + "gigabyte": "GB", + "terabyte": "TB", + "petabyte": "PB", + "exabyte": "EB", + "zettabyte": "ZB", + "yottabyte": "YB", + "bit-per-second": "bps", + "kilobit-per-second": "Kbps", + "megabit-per-second": "Mbps", + "gigabit-per-second": "Gbps", + "terabit-per-second": "Tbps", + "byte-per-second": "B/s", + "kilobyte-per-second": "KB/s", + "megabyte-per-second": "MB/s", + "gigabyte-per-second": "GB/s", + "degree": "°", + "radian": "rad", + "gradian": "grad", + "mil": "mil", + "revolution": "rev", + "siemens": "S", + "millisiemens": "mS", + "microsiemens": "μS", + "kilosiemens": "kS", + "megasiemens": "MS", + "gigasiemens": "GS", + "farad": "F", + "millifarad": "mF", + "microfarad": "μF", + "nanofarad": "nF", + "picofarad": "pF", + "kilofarad": "kF", + "megafarad": "MF", + "gigafarad": "GF", + "terfarad": "TF", + "farad-per-meter": "F/m", + "tesla": "T", + "gauss": "G", + "kilogauss": "kG", + "millitesla": "mT", + "microtesla": "μT", + "nanotesla": "nT", + "kilotesla": "kT", + "megatesla": "MT", + "millitesla-square-meters": "mT·m²", + "gamma": "γ", + "lambda": "λ", + "square-meter-per-second": "m²/s", + "square-centimeter-per-second": "cm²/s", + "stoke": "St", + "centistokes": "cSt", + "square-foot-per-second": "ft²/s", + "square-inch-per-second": "in²/s", + "pascal-second": "Pa·s", + "centipoise": "cP", + "poise": "P", + "reynolds": "Re", + "pound-per-foot-hour": "lb/(ft·hr)", + "newton-second-per-square-meter": "N·s/m²", + "dyne-second-per-square-centimeter": "dyn·s/cm²", + "kilogram-per-meter-second": "kg/(m·s)", + "tesla-square-meters": "T·m²", + "maxwell": "Mx", + "tesla-per-meter": "T/m", + "gauss-per-centimeter": "G/cm", + "weber": "Wb", + "microweber": "μWb", + "milliweber": "mWb", + "gauss-square-centimeter": "G·cm²", + "kilogauss-square-centimeter": "kG·cm²", + "henry": "H", + "millihenry": "mH", + "microhenry": "μH", + "nanohenry": "nH", + "henry-per-meter": "H/m", + "tesla-meter-per-ampere": "T·m/A", + "gauss-per-oersted": "G/Oe", + "kilogram-per-mole": "kg/mol", + "gram-per-mole": "g/mol", + "milligram-per-mole": "mg/mol", + "joule-per-mole": "J/mol", + "joule-per-mole-kelvin": "J/mol-K", + "millivolts-per-meter": "mV/m", + "volts-per-meter": "V/m", + "kilovolts-per-meter": "kV/m", + "radian-per-second": "rad/s", + "radian-per-second-squared": "rad/s^2", + "revolutions-per-minute-per-second": "rpm/s", + "revolutions-per-minute-per-second-squared": "rpm/s^2", + "deg-per-second": "deg/s", + "degrees-brix": "°Bx", + "katal": "kat", + "katal-per-cubic-metre": "kat/m^3" }, "user": { "user": "用户", @@ -3918,11 +4756,20 @@ "widget-bundle": "部件包", "all-bundles": "所有包", "select-widgets-bundle": "选择部件包", + "widgets": "部件", + "all-widgets": "所有部件", + "widget": "部件", + "select-widget": "选择部件", + "no-widgets-matching": "未找到与 '{{entity}}' 匹配的部件。", + "no-widgets": "暂无部件", + "no-widgets-text": "未找到部件", "management": "管理部件", "editor": "部件编辑器", + "confirm-to-exit-editor-html": "You have unsaved widget settings.
Are you sure you want to leave this page?", "widget-type-not-found": "加载部件配置出错。
可能关联的部件已经删除了。", "widget-type-load-error": "由于以下错误未加载部件:", "remove": "删除部件", + "delete": "Delete widget", "edit": "编辑部件", "remove-widget-title": "确定要删除 '{{widgetTitle}}'部件吗?", "remove-widget-text": "确认后,控件和所有相关数据将变得不可恢复。", @@ -3933,18 +4780,27 @@ "rpc": "控件部件", "alarm": "告警部件", "static": "静态部件", + "timeseries-short": "时序", + "latest-short": "最新", + "rpc-short": "控制", + "alarm-short": "告警", + "static-short": "静态", "select-widget-type": "选择窗口部件类型", "missing-widget-title-error": "部件标题必须指定!", "widget-saved": "部件已保存", "unable-to-save-widget-error": "无法保存部件!控件有错误!", "save": "保存部件", "saveAs": "部件另存为", - "save-widget-type-as": "部件类型另存为", - "save-widget-type-as-text": "请输入新的部件标题或选择目标部件包", + "move": "移动部件", + "save-widget-as": "另存部件为", + "save-widget-as-text": "请输入部件标题", "toggle-fullscreen": "切换全屏", "run": "运行部件", + "widget-title": "部件标题", "title": "部件标题", "title-required": "部件标题必填。", + "title-max-length": "标题应少于256个字符", + "system": "系统", "type": "部件类型", "resources": "资源", "resource-url": "JavaScript/CSS URL", @@ -3959,17 +4815,37 @@ "latest-datakey-settings-schema": "最新值数据键设置模式", "widget-settings": "部件设置", "description": "描述", + "tags": "标签", "image-preview": "图片预览", "settings-form-selector": "设置表单选择器", "data-key-settings-form-selector": "数据键设置表单选择器", "latest-data-key-settings-form-selector": "最新值数据键设置表单选择器", - "javascript": "Javascript", + "all": "全部", + "actual": "实际", + "deprecated": "已弃用", + "has-basic-mode": "具有基本模式", + "basic-mode-form-selector": "基本模式表单选择器", + "basic-mode": "基本", + "advanced-mode": "高级", + "javascript": "JavaScript", "js": "JS", - "add-widget-type": "添加部件类型", + "delete-widget-title": "确定要删除部件'{{widgetName}}'吗?", + "delete-widget-text": "确认后,部件及其所有相关数据将无法恢复。", + "delete-widgets-title": "确定要删除 { count, plural, =1 {1个部件} other {#个部件} }吗?", + "delete-widgets-text": "请谨慎操作,确认后,所有选定的部件将被删除,并且所有相关数据将无法恢复。", + "delete-widget": "删除部件", "widget-template-load-failed-error": "无法加载部件模板!", - "add": "添加部件", - "undo": "撤消部件更改", - "export": "导出部件", + "details": "详情", + "widget-details": "部件详情", + "add": "添加", + "add-existing-widget": "添加现有部件", + "add-new-widget": "添加新部件", + "search-widgets": "搜索部件", + "selected-widgets": "已选择 { count, plural, =1 {1 个部件} other {# 个部件} }", + "undo": "撤销", + "export": "导出", + "export-widgets": "导出部件", + "import": "导入部件", "no-data": "部件上没有要显示的数据", "data-overflow": "部件显示 {{count}} 条实体中的 {{total}} 条", "alarm-data-overflow": "部件显示了 {{allowedEntities}}(最大允许)实体中的告警,总共有 {{totalEntities}} 个实体", @@ -4038,6 +4914,7 @@ "widgets-bundle": { "current": "当前组", "widgets-bundles": "部件包", + "widgets-bundle-widgets": "包部件", "add": "添加部件包", "delete": "删除部件包", "title": "标题", @@ -4045,6 +4922,7 @@ "title-max-length": "标题长度应该少于256个字符。", "description": "描述", "image-preview": "图片预览", + "order": "其他", "add-widgets-bundle-text": "添加部件包", "no-widgets-bundles-text": "未找到部件包", "empty": "部件包是空的", @@ -4060,8 +4938,9 @@ "system": "系统", "import": "导入部件包", "export": "导出部件包", + "export-widgets-bundle-widgets-prompt": "在导出的数据中包含包部件(否则只会导出引用的部件完全限定名)", "export-failed-error": "无法导出部件包: {{error}}", - "create-new-widgets-bundle": "创建新的部件包", + "create-new-widgets-bundle": "创建部件包", "widgets-bundle-file": "部件包文件", "invalid-widgets-bundle-file-error": "无法导入部件包:无效的部件包数据结构。", "search": "查找部件包", @@ -4073,14 +4952,19 @@ "data": "数据", "settings": "设置", "advanced": "高级", + "appearance": "外观", + "widget-card": "部件卡片", + "mobile": "移动设备", "title": "标题", - "title-tooltip": "标题 Tooltip", - "general-settings": "基本设置", + "title-tooltip": "标题文字提示", + "general-settings": "常规设置", "display-title": "显示标题", - "drop-shadow": "阴影", + "card-title": "卡片标题", + "drop-shadow": "投影", "enable-fullscreen": "启用全屏", "background-color": "背景颜色", "text-color": "文字颜色", + "border-radius": "边框半径", "padding": "填充", "margin": "边缘", "widget-style": "部件样式", @@ -4092,13 +4976,21 @@ "mobile-hide": "在移动端隐藏部件", "desktop-hide": "在桌面端隐藏部件", "units": "特殊符号展示值", - "decimals": "浮点数后的位数", + "units-by-default": "默认单位", + "decimals": "小数位数", + "decimals-by-default": "默认小数位数", + "default-data-key-parameter-hint": "该参数适用于所有部件值,除非被数据键配置覆盖", + "units-short": "单位", + "decimals-short": "小数", + "decimals-suffix": "位小数", "timewindow": "时间窗口", - "use-dashboard-timewindow": "使用仪表板的时间窗口", + "use-dashboard-timewindow": "使用仪表板时间窗口", + "use-widget-timewindow": "使用部件时间窗口", "display-timewindow": "显示时间窗口", "legend": "图例", "display-legend": "显示图例", "datasources": "数据源", + "datasource": "数据源", "maximum-datasources": "最大允许 { count, plural, =1 {1 个数据源。} other {# 个数据源。} }", "timeseries-key-error": "需要至少指定一个 timeseries 数据键", "datasource-type": "类型", @@ -4127,26 +5019,84 @@ "delete-action-text": "确定要删除部件动作'{{actionName}}' 吗?", "title-icon": "标题图标", "display-icon": "显示标题图标", + "card-icon": "卡片图标", + "icon": "图标", "icon-color": "图标颜色", "icon-size": "图标大小", "advanced-settings": "高级设置", "data-settings": "数据设置", + "limits": "限制", "no-data-display-message": "\"没有数据可显示\" 替代信息", "data-page-size": "每个数据源的最大实体数", - "settings-component-not-found": "未找到设置的表单组件选择器 '{{selector}}'" + "settings-component-not-found": "未找到设置的表单组件选择器 '{{selector}}'", + "preview": "预览", + "set": "设置", + "set-message": "设置消息", + "advanced-title-style": "高级标题样式", + "card-style": "卡片样式", + "text": "文本", + "background": "背景", + "advanced-widget-style": "高级部件样式", + "card-buttons": "卡片按钮", + "show-card-buttons": "显示卡片按钮", + "card-border-radius": "卡片边框半径", + "card-appearance": "卡片外观", + "color": "颜色", + "tooltip": "文字提示", + "units-required": "单位是必须的。" }, "widget-type": { "import": "导入部件类型", "export": "导出部件类型", "export-failed-error": "无法导出部件类型: {{error}}", - "create-new-widget-type": "创建新的部件类型", - "widget-type-file": "部件类型文件", - "invalid-widget-type-file-error": "无法导入部件类型:无效的部件类型数据结构。" + "widget-file": "部件文件", + "invalid-widget-file-error": "无法导入部件:无效的部件数据结构。" }, "widgets": { + "background": { + "background": "背景", + "background-settings": "背景设置", + "background-type-image": "上传图像", + "background-type-image-url": "图像URL", + "background-type-color": "纯色背景", + "image-url": "图像URL", + "overlay": "覆盖", + "enable-overlay": "启用覆盖", + "blur": "模糊", + "preview": "预览" + }, + "battery-level": { + "layout": "布局", + "layout-vertical-solid": "垂直. 实心", + "layout-horizontal-solid": "水平. 实心", + "layout-vertical-divided": "垂直. 分割", + "layout-horizontal-divided": "水平. 分割", + "icon": "图标", + "value": "数值", + "auto-scale": "自动缩放", + "battery-level-color": "电池电量颜色", + "battery-shape-color": "电池形状颜色", + "battery-level-card-style": "电池电量卡片样式", + "sections-count": "分段数量" + }, + "signal-strength": { + "value": "数值", + "last-update": "上次更新", + "no-signal": "无信号", + "layout": "布局", + "layout-wifi": "Wi-Fi", + "layout-cellular-bar": "蜂窝网络条状", + "icon": "图标", + "date": "日期", + "active-bars-color": "活动信号条颜色", + "inactive-bars-color": "非活动信号条颜色", + "signal-strength-card-style": "信号强度卡片样式" + }, "chart": { "common-settings": "通用设置", "enable-stacking-mode": "启用堆叠模式", + "selection": "时间范围选择", + "enable-selection-mode": "启用选择模式", "line-shadow-size": "线条阴影大小", "display-smooth-lines": "显示平滑(曲线)线条", "default-bar-width": "非聚合数据的默认条形图宽度(毫秒)", @@ -4154,15 +5104,17 @@ "bar-alignment-left": "左", "bar-alignment-right": "右", "bar-alignment-center": "居中", + "default-font": "默认字体", "default-font-size": "默认字体大小", "default-font-color": "默认字体颜色", "thresholds-line-width": "所有阈值的默认线条宽度", - "tooltip-settings": "Tooltip 设置", - "show-tooltip": "显示 Tooltip", + "tooltip-settings": "文字提示设置", + "tooltip": "文字提示", + "show-tooltip": "显示文字提示", "hover-individual-points": "悬停在单个数据点上", "show-cumulative-values": "在堆叠模式下显示累积值", - "hide-zero-false-values": "Tooltip 隐藏 zero/false", - "tooltip-value-format-function": "Tooltip 值的格式化函数", + "hide-zero-false-values": "文字提示隐藏 zero/false", + "tooltip-value-format-function": "文字提示值的格式化函数", "grid-settings": "网格线设置", "show-vertical-lines": "显示垂直线条", "show-horizontal-lines": "显示水平线条", @@ -4235,6 +5187,7 @@ "add-threshold": "添加新阈值", "show-values-for-comparison": "显示历史比较值", "comparison-values-label": "历史值标签", + "comparison-line-color": "对比线颜色", "threshold-settings": "阈值设置", "use-as-threshold": "使用键值作为阈值", "threshold-line-width": "阈值线宽", @@ -4243,6 +5196,7 @@ "radius": "半径", "inner-radius": "内部半径", "tilt": "倾斜", + "common-pie-settings-range-error": "值应在0到1的范围内", "stroke-settings": "描边设置", "width-pixels": "宽度 (px)", "show-labels": "显示标签", @@ -4253,7 +5207,35 @@ "border-color": "边框颜色", "legend-settings": "图例设置", "display-legend": "显示图例", - "labels-font-color": "标签字体颜色" + "labels-font-color": "标签字体颜色", + "series": "系列", + "add-series": "添加系列", + "series-settings": "系列设置", + "remove-series": "删除系列", + "no-series": "未配置系列", + "no-series-error": "至少应指定一个系列", + "chart-appearance": "图表外观", + "vertical-grid-lines": "垂直网格线", + "horizontal-grid-lines": "水平网格线", + "chart-background": "图表背景", + "grid-lines-color": "网格线颜色", + "border": "边框", + "axis": "轴", + "vertical-axis": "垂直轴", + "ticks": "刻度", + "horizontal-axis": "水平轴" + }, + "color": { + "color-settings": "颜色设置", + "color-type-constant": "固定值", + "color-type-range": "数值范围", + "color-type-function": "函数", + "color": "颜色", + "value-range": "数值范围", + "from": "从", + "to": "至", + "color-function": "颜色函数", + "copy-color-settings-from": "从其他处复制颜色设置" }, "dashboard-state": { "dashboard-state-settings": "仪表板状态设置", @@ -4341,6 +5323,19 @@ "Ok": "Ok" } }, + "doughnut": { + "total": "总计", + "layout": "布局", + "layout-default": "默认", + "layout-with-total": "带总计", + "auto-scale": "自动缩放", + "clockwise-layout": "顺时针布局", + "sort-series": "按标签对系列排序", + "central-total-value": "中央总计值", + "tooltip-value-type-absolute": "绝对值", + "tooltip-value-type-percentage": "百分比", + "doughnut-card-style": "圆环样式" + }, "entities-hierarchy": { "hierarchy-data-settings": "层次数据设置", "relations-query-function": "关系查询函数", @@ -4369,7 +5364,12 @@ "read-only": "只读", "events-title": "事件标题", "events-filter": "事件过滤", - "event-key-contains": "包含事件key..." + "event-key-contains": "事件键包含...", + "show-connector": "显示连接器", + "connector-state-param-key": "连接器状态参数键", + "status": "状态", + "message": "消息", + "created-time": "创建时间" }, "gauge": { "default-color": "默认颜色", @@ -4377,10 +5377,14 @@ "ticks-settings": "刻度设置", "min-value": "最小值", "max-value": "最大值", + "min-value-short": "最小值", + "max-value-short": "最大值", "start-ticks-angle": "刻度起始角度", "ticks-angle": "刻度角度", + "major-ticks": "主刻度", "major-ticks-count": "主刻度数量", "major-ticks-color": "主刻度颜色", + "minor-ticks": "次刻度", "minor-ticks-count": "次刻度数量", "minor-ticks-color": "次刻度颜色", "tick-numbers-font": "刻度数字字体", @@ -4392,8 +5396,15 @@ "units-font": "单位文字字体", "value-box-settings": "数值框设置", "show-value-box": "显示数值框", - "value-int": "整数部分的位数", - "value-font": "数值文字字体", + "value-box": "数值框", + "value-int": "整数部位数", + "value-text": "数值文本", + "value-text-shadow": "数值文本阴影", + "value-font": "数值字体", + "rect-stroke-color-start": "矩形边框颜色 - 渐变起始", + "rect-stroke-color-end": "矩形边框颜色 - 渐变结束", + "background-color": "背景颜色", + "shadow-color": "阴影颜色", "value-box-rect-stroke-color": "数值框矩形描边颜色", "value-box-rect-stroke-color-end": "数值框矩形描边颜色 - 渐变结束", "value-box-background-color": "数值框背景颜色", @@ -4404,6 +5415,7 @@ "needle-settings": "指针设置", "needle-circle-size": "指针圆圈尺寸", "needle-color": "指针颜色", + "needle-color-start": "指针颜色 - 渐变起始", "needle-color-end": "指针颜色 - 渐变结束", "needle-color-shadow-up": "指针上半部分阴影颜色", "needle-color-shadow-down": "指针下半部分阴影颜色", @@ -4417,6 +5429,7 @@ "add-highlight": "添加高亮", "animation-settings": "动画设置", "enable-animation": "启用动画", + "animation-duration-rule": "动画持续时间和规则", "animation-duration": "动画持续时间", "animation-rule": "动画规则", "animation-linear": "线性", @@ -4431,17 +5444,21 @@ "animation-debounce": "弹跳反向", "animation-delastic": "弹性反向", "linear-gauge-settings": "线性量规设置", + "bar-stroke": "柱状图描边", "bar-stroke-width": "条形图描边宽度", "bar-stroke-color": "条形图描边颜色", "bar-background-color": "量规条形图背景颜色", "bar-background-color-end": "条形图背景颜色 - 渐变结束", "progress-bar-color": "进度条颜色", + "progress-bar": "进度条", + "progress-bar-color-start": "进度条颜色 - 渐变起始", "progress-bar-color-end": "进度条颜色 - 渐变结束", "major-ticks-names": "主刻度名称", "show-stroke-ticks": "显示刻度描边", "major-ticks-font": "主刻度字体", "border-color": "边框颜色", "border-width": "边框宽度", + "needle-circle": "指针圆圈", "needle-circle-color": "指针圆圈颜色", "animation-target": "动画目标", "animation-target-needle": "指针", @@ -4485,7 +5502,18 @@ "tick-color": "刻度颜色", "tick-values": "刻度值", "no-tick-values": "未配置刻度值", - "add-tick-value": "添加刻度值" + "add-tick-value": "添加刻度值", + "gauge-appearance": "仪表盘外观", + "units-title": "单位标题", + "value": "数值", + "ticks": "刻度", + "arrow-and-scale-color": "箭头和刻度默认颜色", + "scale-settings": "刻度设置", + "scale": "刻度尺寸", + "scale-color": "刻度颜色", + "compass-appearance": "指南针外观", + "labels": "标签", + "label-style": "标签样式" }, "gpio": { "pin": "引脚", @@ -4602,6 +5630,9 @@ "input-fields-alignment": "输入字段对齐方式", "input-fields-alignment-column": "列(默认)", "input-fields-alignment-row": "行", + "layout": "布局", + "row-gap": "行之间的间距(像素)", + "column-gap": "列之间的间距(像素)", "latitude-field-required": "纬度字段必填", "longitude-field-required": "经度字段必填", "attribute-settings": "属性设置", @@ -4650,12 +5681,19 @@ "datakey-value-type-date": "日期", "datakey-value-type-time": "时间", "datakey-value-type-select": "选择", + "datakey-value-type-color": "颜色", "value-is-required": "值必填", "ability-to-edit-attribute": "编辑属性的能力", "ability-to-edit-attribute-editable": "可编辑(默认)", "ability-to-edit-attribute-disabled": "禁用", "ability-to-edit-attribute-readonly": "只读", "disable-on-datakey-name": "在另一个数据键的值为假时禁用(指定数据键名称)", + "field-appearance": "字段外观", + "appearance-fill": "填充", + "appearance-outline": "轮廓", + "subscript-sizing": "下标大小", + "subscript-sizing-fixed": "固定", + "subscript-sizing-dynamic": "动态", "slide-toggle-settings": "滑动开关设置", "slide-toggle-label-position": "滑动开关标签位置", "slide-toggle-label-position-after": "之后", @@ -4771,6 +5809,14 @@ "no-columns-found": "找不到列", "no-columns-matching": "未找到 '{{column}}'。" }, + "range-chart": { + "chart": "图表", + "data-zoom": "数据缩放", + "range-colors": "范围颜色", + "out-of-range-color": "超出范围颜色", + "fill-area": "填充区域", + "range-chart-card-style": "范围图表卡片样式" + }, "rpc": { "value-settings": "值设置", "initial-value": "初始值", @@ -4930,17 +5976,17 @@ "use-label-function": "使用标签函数", "label-pattern": "标签 (模式示例:'${entityName}', '${entityName}: (Text ${keyName} units.)' )", "label-function": "标签函数", - "tooltip": "Tooltip", - "show-tooltip": "显示 Tooltip", - "show-tooltip-action": "显示 Tooltip 的操作", - "show-tooltip-action-click": "点击时显示 Tooltip(默认)", - "show-tooltip-action-hover": "悬停时显示 Tooltip", - "auto-close-tooltips": "自动关闭 Tooltip", - "use-tooltip-function": "使用 Tooltip 函数", - "tooltip-pattern": "Tooltip (例如 'Text ${keyName} units.' or Link text')", - "tooltip-function": "Tooltip 函数", - "tooltip-offset-x": "Tooltip X偏移相对于标记锚点乘以标记宽度", - "tooltip-offset-y": "Tooltip Y偏移相对于标记锚点乘以标记高度", + "tooltip": "文字提示", + "show-tooltip": "显示文字提示", + "show-tooltip-action": "显示文字提示的操作", + "show-tooltip-action-click": "点击时显示文字提示(默认)", + "show-tooltip-action-hover": "悬停时显示文字提示", + "auto-close-tooltips": "自动关闭文字提示", + "use-tooltip-function": "使用文字提示函数", + "tooltip-pattern": "文字提示 (例如 'Text ${keyName} units.' or Link text')", + "tooltip-function": "文字提示函数", + "tooltip-offset-x": "文字提示X偏移相对于标记锚点乘以标记宽度", + "tooltip-offset-y": "文字提示Y偏移相对于标记锚点乘以标记高度", "color": "颜色", "use-color-function": "使用颜色函数", "color-function": "颜色函数", @@ -4959,12 +6005,12 @@ "use-polygon-label-function": "使用多边形标签函数", "polygon-label-pattern": "多边形标签 (模板示例:'${entityName}', '${entityName}: (Text ${keyName} units.)' )", "polygon-label-function": "多边形标签函数", - "polygon-tooltip": "多边形 Tooltip", - "show-polygon-tooltip": "显示多边形 Tooltip", - "auto-close-polygon-tooltips": "自动关闭多边形 Tooltip", - "use-polygon-tooltip-function": "使用多边形 Tooltip 函数", - "polygon-tooltip-pattern": "Tooltip (例如 'Text ${keyName} units.' or Link text')", - "polygon-tooltip-function": "多边形 Tooltip 函数", + "polygon-tooltip": "多边形文字提示", + "show-polygon-tooltip": "显示多边形文字提示", + "auto-close-polygon-tooltips": "自动关闭多边形文字提示", + "use-polygon-tooltip-function": "使用多边形文字提示函数", + "polygon-tooltip-pattern": "文字提示(例如 'Text ${keyName} units.' or Link text')", + "polygon-tooltip-function": "多边形文字提示函数", "polygon-color": "多边形颜色", "polygon-opacity": "多边形不透明度", "use-polygon-color-function": "使用多边形颜色函数", @@ -4984,12 +6030,12 @@ "use-circle-label-function": "使用圆标签函数", "circle-label-pattern": "圆标签 (模板示例:'${entityName}', '${entityName}: (Text ${keyName} units.)' )", "circle-label-function": "圆标签函数", - "circle-tooltip": "圆 Tooltip", - "show-circle-tooltip": "显示圆 Tooltip", - "auto-close-circle-tooltips": "自动关闭圆 Tooltip", - "use-circle-tooltip-function": "使用圆 Tooltip 函数", - "circle-tooltip-pattern": "Tooltip (例如 'Text ${keyName} units.' or Link text')", - "circle-tooltip-function": "圆 Tooltip 函数", + "circle-tooltip": "圆文字提示", + "show-circle-tooltip": "显示圆文字提示", + "auto-close-circle-tooltips": "自动关闭圆文字提示", + "use-circle-tooltip-function": "使用圆文字提示函数", + "circle-tooltip-pattern": "文字提示 (例如 'Text ${keyName} units.' or Link text')", + "circle-tooltip-function": "圆文字提示函数", "circle-fill-color": "圆填充颜色", "circle-fill-color-opacity": "圆填充颜色不透明度", "use-circle-fill-color-function": "使用圆填充颜色函数", @@ -5018,10 +6064,10 @@ "route-map-settings": "路线地图设置", "trip-animation-settings": "行程动画设置", "normalization-step": "数据标准化步骤(毫秒)", - "tooltip-background-color": "Tooltip 背景颜色", - "tooltip-font-color": "Tooltip 字体颜色", - "tooltip-opacity": "Tooltip 不透明度(0-1)", - "auto-close-tooltip": "自动关闭 Tooltip", + "tooltip-background-color": "文字提示背景颜色", + "tooltip-font-color": "文字提示字体颜色", + "tooltip-opacity": "文字提示不透明度(0-1)", + "auto-close-tooltip": "自动关闭文字提示", "rotation-angle": "设置标记的附加旋转角度(度)", "path-settings": "路径设置", "path-color": "路径颜色", @@ -5046,7 +6092,7 @@ "point-color-function": "点颜色函数", "use-point-as-anchor": "使用点作为锚点", "point-as-anchor-function": "点作为锚点函数", - "independent-point-tooltip": "独立点 Tooltip", + "independent-point-tooltip": "独立点文字提示", "clustering-markers": "标记聚类", "use-icon-create-function": "使用标记颜色函数", "marker-color-function": "标记颜色函数" @@ -5059,10 +6105,137 @@ "markdown-css": "Markdown/HTML CSS" }, "simple-card": { + "label": "标签", "label-position": "标签位置", "label-position-left": "左侧", "label-position-top": "顶部" }, + "value-card": { + "layout": "布局", + "layout-square": "正方形", + "layout-vertical": "垂直", + "layout-centered": "居中", + "layout-simplified": "简化", + "layout-horizontal": "水平", + "layout-horizontal-reversed": "水平翻转", + "label": "标签", + "icon": "图标", + "value": "数值", + "date": "日期", + "value-card-style": "数值卡片样式", + "auto-scale": "自动缩放" + }, + "liquid-level-card": { + "layout-simple": "简单", + "layout-percentage": "百分比", + "layout-absolute": "绝对值", + "layout": "布局", + "background-overlay": "值背景叠加", + "total-volume": "总体积", + "tank": "储罐", + "shape": "形状", + "datasource-units": "数据源单位", + "widget-units": "小部件单位", + "decimals": "小数位数", + "liquid": "液体", + "liquid-color": "液体颜色", + "value": "值", + "value-font": "值字体", + "level": "水位", + "last-update": "最后更新", + "shape-by-attribute": "按属性名称设置储罐形状", + "tooltip-background": "背景颜色", + "background-blur": "背景模糊", + "tank-color": "储罐颜色", + "static": "静态", + "see-examples": "查看示例", + "attribute": "属性", + "shape-type": "类型", + "v-oval": "垂直椭圆", + "v-cylinder": "垂直圆柱体", + "v-capsule": "垂直胶囊", + "rectangle": "矩形", + "h-oval": "水平椭圆", + "h-ellipse": "水平椭圆", + "h-dish-ends": "水平盘形", + "h-cylinder": "水平圆柱体", + "h-capsule": "水平胶囊", + "h-elliptical_2_1": "水平2:1椭圆", + "icon": "卡片图标", + "title": "卡片标题", + "units": "单位", + "color-and-font": "颜色和字体", + "shape-attribute-name": "属性名称", + "total-volume-required": "需要总体积。", + "attribute-name-required": "需要属性名称。", + "attribute-key-not-set": "未设置属性 '{{attributeName}}' 键", + "attribute-key-invalid": "属性 '{{attributeName}}' 键无效" + }, + "aggregated-value-card": { + "subtitle": "副标题", + "chart": "图表", + "values": "数值", + "value-appearance": "数值外观", + "position": "位置", + "position-center": "中心", + "position-right-top": "右上", + "position-right-bottom": "右下", + "position-left-top": "左上", + "position-left-bottom": "左下", + "font": "字体", + "color": "颜色", + "arrow": "箭头", + "display-up-down-arrow": "显示向上/向下箭头", + "add-value": "添加数值", + "remove-value": "移除数值", + "no-values": "未配置数值", + "aggregation": "聚合", + "aggregated-value-card-style": "聚合数值卡片样式", + "auto-scale": "自动缩放" + }, + "value-chart-card": { + "layout": "布局", + "layout-left": "左侧", + "layout-right": "右侧", + "auto-scale": "自动缩放", + "icon": "图标", + "value": "数值", + "chart": "图表", + "value-chart-card-style": "数值图表卡片样式" + }, + "progress-bar": { + "layout": "布局", + "layout-default": "默认", + "layout-simplified": "简化", + "auto-scale": "自动缩放", + "icon": "图标", + "value": "数值", + "range": "范围", + "min": "最小", + "max": "最大", + "range-ticks": "范围刻度", + "bar": "进度条", + "bar-color": "进度条颜色", + "bar-background": "进度条背景", + "progress-bar-card-style": "进度条卡片样式" + }, + "alarm-count": { + "alarm-count-card-style": "告警计数卡片样式" + }, + "entity-count": { + "entity-count-card-style": "实体计数卡片样式" + }, + "count": { + "layout": "布局", + "layout-column": "列", + "layout-row": "行", + "label": "标签", + "icon": "图标", + "icon-background": "图标背景", + "value": "数值", + "chevron": "箭头", + "auto-scale": "自动缩放" + }, "table": { "common-table-settings": "常规表格设置", "enable-search": "启用搜索", @@ -5072,7 +6245,6 @@ "show-empty-space-hidden-action": "显示空白区域而不是隐藏单元格按钮操作", "dont-reserve-space-hidden-action": "不为隐藏的操作按钮预留空间", "display-timestamp": "显示时间戳列", - "display-milliseconds": "显示时间戳毫秒", "display-pagination": "显示分页", "default-page-size": "默认页面大小", "use-entity-label-tab-name": "在选项卡名称中使用实体标签", @@ -5113,7 +6285,43 @@ "allow-alarms-ack": "允许确认告警", "allow-alarms-clear": "允许清除告警", "display-alarm-activity": "显示告警活动", - "allow-alarms-assign": "允许分配告警" + "allow-alarms-assign": "允许分配告警", + "columns": "列", + "column-settings": "列设置", + "remove-column": "移除列", + "add-column": "添加列", + "no-columns": "没有配置列", + "columns-to-display": "显示的列", + "table-header": "表头", + "header-buttons": "表头按钮", + "table-buttons": "表格按钮", + "pagination": "分页", + "rows": "行", + "timeseries-column-error": "至少应指定一个时间序列列", + "alarm-column-error": "至少应指定一个告警列", + "table-tabs": "表格标签", + "show-cell-actions-menu-mobile": "在移动模式下显示单元格操作下拉菜单" + }, + "wind-speed-direction": { + "layout": "布局", + "layout-default": "默认", + "layout-advanced": "高级", + "layout-simplified": "简化", + "values": "数值", + "wind-direction": "风向", + "center-value": "中心数值", + "icon": "图标", + "arrow": "箭头", + "ticks": "刻度", + "labels-type": "标签类型", + "directional-names": "方向名称", + "degrees": "度数", + "major-ticks": "主要刻度", + "minor-ticks": "次要刻度", + "wind-speed-direction-card-style": "风速和风向卡片样式", + "ticks-color": "刻度颜色", + "ticks-labels-type": "刻度标签类型", + "arrow-color": "箭头颜色" }, "value-source": { "value-source": "值来源", @@ -5124,6 +6332,7 @@ "source-entity-attribute": "源实体属性" }, "widget-font": { + "font-settings": "字体设置", "font-family": "字体", "size": "大小", "relative-font-size": "相对字体大小(百分比)", @@ -5137,7 +6346,10 @@ "font-weight-bolder": "更粗", "font-weight-lighter": "更轻", "color": "颜色", - "shadow-color": "阴影颜色" + "shadow-color": "阴影颜色", + "preview": "预览", + "line-height": "行高", + "auto": "自动" }, "home": { "no-data-available": "暂无数据" @@ -5225,7 +6437,7 @@ "alarms": "告警", "dashboards": "仪表盘", "entities-and-relations": "实体和关系", - "profiles": "配置文件", + "profiles": "配置", "advanced-features": "高级功能", "notification-center": "通知中心", "api-usage": "API 使用情况", @@ -5240,21 +6452,111 @@ }, "devices": { "view-docs": "查看文档", - "inactive": "活动", - "active": "未活动", + "inactive": "非活动", + "active": "活动", "total": "总数" }, "alarms": { "critical": "严重", "assigned-to-me": "分配给我", "total": "总数" + }, + "getting-started": { + "get-started": "开始", + "finish": "完成", + "done-welcome-title": "欢迎加入我们", + "done-welcome-text": "你做得很好!", + "sys-admin": { + "step1": { + "title": "创建租户和租户管理员", + "content": "

租户是拥有或生产设备和资产的个人或组织,租户可以有多个租户管理员用户、客户、设备和资产。

租户管理员可以在租户账户中创建和管理设备、资产、客户和仪表板。

请按照文档进行操作:

", + "how-to-create-tenant": "如何创建租户和租户管理员" + }, + "step2": { + "title": "配置功能:邮件服务", + "content": "

邮件服务配置对于用户激活、密码恢复和报警通知的发送非常重要。

请按照文档进行操作:

", + "how-to-configure-mail-server": "如何配置邮件服务器" + }, + "step3": { + "title": "配置功能:短信提供商", + "content": "

配置短信提供商,通过短信向客户发送报警通知。

请按照文档进行操作:

", + "how-to-configure-sms-provider": "如何配置短信提供商" + }, + "step4": { + "title": "配置功能:双因素认证", + "content": "

通过双因素认证提高平台账户的安全性。

请按照文档进行操作:

", + "how-to-configure-2fa": "如何配置双因素认证" + }, + "step5": { + "title": "配置功能:OAuth 2", + "content": "

通过OAuth 2.0的单点登录功能,简化租户和客户用户的登录过程。

请按照文档进行操作:

", + "how-to-configure-oauth2": "如何配置OAuth 2" + }, + "step6": { + "title": "配置功能:Slack", + "content": "

根据设置的通知规则,通过Slack向租户和客户用户发送通知。

请按照文档进行操作:

", + "how-to-configure-notifications": "如何配置Slack" + } + }, + "tenant-admin": { + "step1": { + "title": "创建设备", + "content": "

让我们通过用户界面将您的第一个设备添加到平台。请按照文档进行操作:

", + "how-to-create-device": "如何创建设备" + }, + "step2": { + "title": "连接设备", + "content-before": "

要连接设备,您需要获取设备凭据。我们建议在本指南中使用默认生成的凭据,即访问令牌。

  • 转到设备表
  • 点击设备行以打开设备详情
  • 点击“复制访问令牌”按钮

使用简单的命令通过HTTP发布数据。不要忘记将$ACCESS_TOKEN替换为您的设备访问令牌:

", + "ubuntu": { + "install-curl": "Ubuntu上安装cURL:" + }, + "macos": { + "install-curl": "MacOS上安装cURL:" + }, + "windows": { + "install-curl": "从Windows 10 b17063开始,cURL已默认可用。" + }, + "replace-access-token": "将$ACCESS_TOKEN替换为您的设备令牌:", + "content-after": "

您还可以使用其他协议,如MQTT、CoAP等。

请按照文档进行操作:

", + "how-to-connect-device": "如何连接设备" + }, + "step3": { + "title": "创建仪表板", + "content": "

创建一个仪表板,用于可视化来自实体(如资产、设备等)的数据。

请按照文档进行操作:

", + "how-to-create-dashboard": "如何创建仪表板" + }, + "step4": { + "title": "配置报警规则", + "alarm-rules": "报警规则", + "content": "

当温度达到25°C时,让我们触发一个报警。请按照文档进行操作:

", + "how-to-configure-alarm-rules": "如何配置报警规则" + }, + "step5": { + "title": "创建报警", + "content-before": "

要触发报警,请发送一个新的温度值,该值为26℃或更高。

", + "replace-access-token": "将$ACCESS_TOKEN替换为您的设备令牌:", + "content-after": "

请按照文档进行操作:

", + "how-to-create-alarm": "如何创建报警" + }, + "step6": { + "title": "创建客户并分配仪表板", + "content": "

通过创建终端用户仪表板,客户用户只能查看自己的设备,另一个客户的数据将被隐藏。

请按照文档进行操作:

", + "how-to-create-customer-and-assign-dashboard": "如何创建客户并分配仪表板" + } + } } }, + "color": { + "color": "颜色" + }, "icon": { "icon": "图标", + "icons": "图标", "select-icon": "选择图标", "material-icons": "素材图标", - "show-all": "显示所有图标" + "show-all": "显示所有图标", + "search-icon": "搜索图标", + "no-icons-found": "没有找到符合'{{iconSearch}}'的图标" }, "phone-input": { "phone-input-label": "手机号码", @@ -5267,14 +6569,15 @@ "widget-action": { "action-cell-button": "动作单元格按钮", "row-click": "点击行时", - "polygon-click": "单击多边形", + "polygon-click": "点击多边形时", "marker-click": "点击标记时", - "circle-click": "在圆圈上单击", - "tooltip-tag-action": "Tooltip tag action", + "circle-click": "点击圆圈时", + "tooltip-tag-action": "文字提示标签操作", "node-selected": "选择节点时", "element-click": "点击HTML元素时", "pie-slice-click": "点击切片时", - "row-double-click": "双击行时" + "row-double-click": "双击行时", + "card-click": "点击卡片时" } }, "paginator": { diff --git a/ui-ngx/src/assets/locale/locale.constant-zh_TW.json b/ui-ngx/src/assets/locale/locale.constant-zh_TW.json index 85c9181ae8..5b415558a1 100644 --- a/ui-ngx/src/assets/locale/locale.constant-zh_TW.json +++ b/ui-ngx/src/assets/locale/locale.constant-zh_TW.json @@ -4476,7 +4476,6 @@ "show-empty-space-hidden-action": "顯示空格而不是隱藏儲存格的按鈕動作", "dont-reserve-space-hidden-action": "不要為隱藏的動作按鈕保留空格", "display-timestamp": "顯示時間戳列", - "display-milliseconds": "顯示毫秒時間戳", "display-pagination": "顯示分頁", "default-page-size": "預設頁面尺寸", "use-entity-label-tab-name": "在分頁標籤名稱中使用實體標籤", diff --git a/ui-ngx/src/assets/metadata/units.json b/ui-ngx/src/assets/metadata/units.json index 3237d6620b..53744cecb7 100644 --- a/ui-ngx/src/assets/metadata/units.json +++ b/ui-ngx/src/assets/metadata/units.json @@ -1316,6 +1316,11 @@ "symbol": "mg/mL", "tags": ["concentration","mass per volume","mg/mL"] }, +{ + "name": "unit.milligram-per-cubic-meter", + "symbol": "mg/m³", + "tags": ["concentration","mass per volume","mg/m³"] +}, { "name": "unit.pound-per-cubic-foot", "symbol": "lb/ft³", diff --git a/ui-ngx/src/environments/environment.prod.ts b/ui-ngx/src/environments/environment.prod.ts index f724eb6687..b76f84da34 100644 --- a/ui-ngx/src/environments/environment.prod.ts +++ b/ui-ngx/src/environments/environment.prod.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/environments/environment.ts b/ui-ngx/src/environments/environment.ts index 82d426e95c..adee999496 100644 --- a/ui-ngx/src/environments/environment.ts +++ b/ui-ngx/src/environments/environment.ts @@ -1,5 +1,5 @@ /// -/// Copyright © 2016-2023 The Thingsboard Authors +/// Copyright © 2016-2024 The Thingsboard Authors /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index 3b29fe986c..ee6d4167cd 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - @import './scss/constants'; @mixin form-row-column() { @@ -523,6 +522,7 @@ right: 0; background: $tb-primary-color; opacity: 0.04; + pointer-events: none; } } diff --git a/ui-ngx/src/index.html b/ui-ngx/src/index.html index 5b0ca17cd6..7b0a5987c3 100644 --- a/ui-ngx/src/index.html +++ b/ui-ngx/src/index.html @@ -1,6 +1,6 @@ - 4.1.0 + 4.2.0 2.7.2 1.5.2 5.9.3 diff --git a/transport/lwm2m/src/main/java/org/eclipse/leshan/server/observation/ObservationServiceImpl.java b/transport/lwm2m/src/main/java/org/eclipse/leshan/server/observation/ObservationServiceImpl.java new file mode 100644 index 0000000000..89a2f07179 --- /dev/null +++ b/transport/lwm2m/src/main/java/org/eclipse/leshan/server/observation/ObservationServiceImpl.java @@ -0,0 +1,296 @@ +/** + * 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. + * + * Copyright (c) 2016 Sierra Wireless and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v20.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.html. + * + * Contributors: + * Sierra Wireless - initial API and implementation + * Michał Wadowski (Orange) - Add Observe-Composite feature. + */ +package org.eclipse.leshan.server.observation; + +import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.node.LwM2mPath; +import org.eclipse.leshan.core.observation.CompositeObservation; +import org.eclipse.leshan.core.observation.Observation; +import org.eclipse.leshan.core.observation.SingleObservation; +import org.eclipse.leshan.core.peer.LwM2mPeer; +import org.eclipse.leshan.core.response.ObserveCompositeResponse; +import org.eclipse.leshan.core.response.ObserveResponse; +import org.eclipse.leshan.server.endpoint.LwM2mServerEndpoint; +import org.eclipse.leshan.server.endpoint.LwM2mServerEndpointsProvider; +import org.eclipse.leshan.server.profile.ClientProfile; +import org.eclipse.leshan.server.registration.Registration; +import org.eclipse.leshan.server.registration.RegistrationStore; +import org.eclipse.leshan.server.registration.RegistrationUpdate; +import org.eclipse.leshan.server.registration.UpdatedRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Implementation of the {@link ObservationService} accessing the persisted observation via the provided + * {@link RegistrationStore}. + * + * When a new observation is added or changed or canceled, the registered listeners are notified. + */ +@Slf4j +public class ObservationServiceImpl implements ObservationService, LwM2mNotificationReceiver { + + private final Logger LOG = LoggerFactory.getLogger(ObservationServiceImpl.class); + + private final RegistrationStore registrationStore; + private final LwM2mServerEndpointsProvider endpointProvider; + private final boolean updateRegistrationOnNotification; + + private final List listeners = new CopyOnWriteArrayList<>();; + + /** + * Creates an instance of {@link ObservationServiceImpl} + */ + public ObservationServiceImpl(RegistrationStore store, LwM2mServerEndpointsProvider endpointProvider) { + this(store, endpointProvider, false); + } + + /** + * Creates an instance of {@link ObservationServiceImpl} + * + * @param updateRegistrationOnNotification will activate registration update on observe notification. + * + * @since 1.1 + */ + public ObservationServiceImpl(RegistrationStore store, LwM2mServerEndpointsProvider endpointProvider, + boolean updateRegistrationOnNotification) { + this.registrationStore = store; + this.updateRegistrationOnNotification = updateRegistrationOnNotification; + this.endpointProvider = endpointProvider; + } + + @Override + public int cancelObservations(Registration registration) { + // check registration id + String registrationId = registration.getId(); + if (registrationId == null) + return 0; + + Collection observations = registrationStore.removeObservations(registrationId); + if (observations == null) + return 0; + + for (Observation observation : observations) { + cancel(observation); + } + + return observations.size(); + } + + @Override + public int cancelObservations(Registration registration, String nodePath) { + if (registration == null || registration.getId() == null || nodePath == null || nodePath.isEmpty()) + return 0; + + Set observations = getObservationsForCancel(registration.getId(), nodePath); + for (Observation observation : observations) { + cancelObservation(observation); + } + return observations.size(); + } + + @Override + public int cancelCompositeObservations(Registration registration, String[] nodePaths) { + if (registration == null || registration.getId() == null || nodePaths == null || nodePaths.length == 0) + return 0; + + Set observations = getCompositeObservationsForCancel(registration.getId(), nodePaths); + for (Observation observation : observations) { + cancelObservation(observation); + } + return observations.size(); + } + + @Override + public void cancelObservation(Observation observation) { + if (observation == null) + return; + + registrationStore.removeObservation(observation.getRegistrationId(), observation.getId()); + cancel(observation); + } + + private void cancel(Observation observation) { + List endpoints = endpointProvider.getEndpoints(); + for (LwM2mServerEndpoint lwM2mEndpoint : endpoints) { + lwM2mEndpoint.cancelObservation(observation); + } + + for (ObservationListener listener : listeners) { + listener.cancelled(observation); + } + } + + @Override + public Set getObservations(Registration registration) { + return getObservations(registration.getId()); + } + + private Set getObservations(String registrationId) { + if (registrationId == null) + return Collections.emptySet(); + + return new HashSet<>(registrationStore.getObservations(registrationId)); + } + + private Set getCompositeObservationsForCancel(String registrationId, String[] nodePaths) { + if (registrationId == null || nodePaths == null) + return Collections.emptySet(); + + // array of String to array of LWM2M path + List lwPaths = new ArrayList<>(nodePaths.length); + for (int i = 0; i < nodePaths.length; i++) { + lwPaths.add(new LwM2mPath(nodePaths[i])); + } + + // search composite-observation + Set result = new HashSet<>(); + for (Observation obs : getObservations(registrationId)) { + if (obs instanceof CompositeObservation) { + if (lwPaths.equals(((CompositeObservation) obs).getPaths())) { + result.add(obs); + } + } + } + return result; + } + + private Set getObservationsForCancel(String registrationId, String nodePath) { + if (registrationId == null || nodePath == null) + return Collections.emptySet(); + + Set result = new HashSet<>(); + LwM2mPath lwPath = new LwM2mPath(nodePath); + for (Observation obs : getObservations(registrationId)) { + if (obs instanceof SingleObservation) { + LwM2mPath lwPathObs = ((SingleObservation) obs).getPath(); + if (lwPath.equals(lwPathObs) || lwPathObs.startWith(lwPath)) { // nodePath = "3", lwPathObs = "3/0/9": cancel for tne all lwPathObs + result.add(obs); + } else if (!lwPath.equals(lwPathObs) && lwPath.startWith(lwPathObs)) { // nodePath = "3/0/9", lwPathObs = "3": error... + String errorMsg = String.format( + "Unexpected error : There is registration with id [%s] existing observation [%s] includes input observation [%s]!", + registrationId, lwPathObs, lwPath); + throw new IllegalStateException(errorMsg); + } + } + } + + return result; + } + + @Override + public void addListener(ObservationListener listener) { + listeners.add(listener); + } + + @Override + public void removeListener(ObservationListener listener) { + listeners.remove(listener); + } + + private Registration updateRegistrationOnRegistration(Observation observation, LwM2mPeer sender, + ClientProfile profile) { + if (updateRegistrationOnNotification) { + RegistrationUpdate regUpdate = new RegistrationUpdate(observation.getRegistrationId(), sender, null, null, + null, null, null, null, null, null, null, null); + UpdatedRegistration updatedRegistration = registrationStore.updateRegistration(regUpdate); + if (updatedRegistration == null || updatedRegistration.getUpdatedRegistration() == null) { + String errorMsg = String.format( + "Unexpected error: There is no registration with id %s for this observation %s", + observation.getRegistrationId(), observation); + LOG.error(errorMsg); + throw new IllegalStateException(errorMsg); + } + return updatedRegistration.getUpdatedRegistration(); + } + return profile.getRegistration(); + } + + // ********** NotificationListener interface **********// + @Override + public void onNotification(SingleObservation observation, LwM2mPeer sender, ClientProfile profile, + ObserveResponse response) { + try { + Registration updatedRegistration = updateRegistrationOnRegistration(observation, sender, profile); + for (ObservationListener listener : listeners) { + listener.onResponse(observation, updatedRegistration, response); + } + } catch (Exception e) { + for (ObservationListener listener : listeners) { + listener.onError(observation, profile.getRegistration(), e); + } + } + } + + @Override + public void onNotification(CompositeObservation observation, LwM2mPeer sender, ClientProfile profile, + ObserveCompositeResponse response) { + try { + Registration updatedRegistration = updateRegistrationOnRegistration(observation, sender, profile); + for (ObservationListener listener : listeners) { + listener.onResponse(observation, updatedRegistration, response); + } + } catch (Exception e) { + for (ObservationListener listener : listeners) { + listener.onError(observation, profile.getRegistration(), e); + } + } + } + + @Override + public void onError(Observation observation, LwM2mPeer sender, ClientProfile profile, Exception error) { + for (ObservationListener listener : listeners) { + listener.onError(observation, profile.getRegistration(), error); + } + } + + @Override + public void newObservation(Observation observation, Registration registration) { + for (ObservationListener listener : listeners) { + listener.newObservation(observation, registration); + } + } + + @Override + public void cancelled(Observation observation) { + for (ObservationListener listener : listeners) { + listener.cancelled(observation); + } + + } +} From cdc6daa7a906b1d2843a97e923750c6a87778a64 Mon Sep 17 00:00:00 2001 From: nick Date: Mon, 22 Jan 2024 10:57:05 +0200 Subject: [PATCH 153/397] lwm2m: fix buf license excludes --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index eac7903dd7..062a69746c 100755 --- a/pom.xml +++ b/pom.xml @@ -829,6 +829,7 @@ src/main/scripts/control/** src/main/scripts/windows/** src/main/resources/public/static/rulenode/** + src/main/java/org/eclipse/leshan/server/observation//** **/*.proto.js docker/haproxy/** docker/tb-node/** From e27ef320e748d4be15354dc8c1e65763cfe36204 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 22 Jan 2024 12:31:01 +0200 Subject: [PATCH 154/397] updated env variable name and descriptions --- application/src/main/resources/thingsboard.yml | 6 +++--- .../server/cache/TBRedisStandaloneConfiguration.java | 2 +- .../java/org/thingsboard/server/msa/ContainerTestSuite.java | 2 +- transport/coap/src/main/resources/tb-coap-transport.yml | 6 +++--- transport/http/src/main/resources/tb-http-transport.yml | 6 +++--- transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml | 6 +++--- transport/mqtt/src/main/resources/tb-mqtt-transport.yml | 6 +++--- transport/snmp/src/main/resources/tb-snmp-transport.yml | 6 +++--- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index e2f1a80d42..18565f463e 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -642,7 +642,7 @@ redis: # ssl config ssl: # Enable/disable secure connection - enabled: "${REDIS_SSL_ENABLED:false}" + enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) @@ -651,9 +651,9 @@ redis: pem: # Path redis server (CA) certificate cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file (optional) + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file (optional) + # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # Keystore server credentials keystore: diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisStandaloneConfiguration.java b/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisStandaloneConfiguration.java index f0f250bbaa..d4235e3662 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisStandaloneConfiguration.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisStandaloneConfiguration.java @@ -89,4 +89,4 @@ public class TBRedisStandaloneConfiguration extends TBRedisCacheConfiguration { } return jedisClientConfigurationBuilder.build(); } -} \ No newline at end of file +} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java index 6df75fdac4..bbaeabe907 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/ContainerTestSuite.java @@ -108,7 +108,7 @@ public class ContainerTestSuite { if (IS_REDIS_SSL) { addToFile(targetDir, "cache-redis.env", - Map.of("REDIS_SSL_ENABLED", "true", + Map.of("TB_REDIS_SSL_ENABLED", "true", "TB_REDIS_SSL_PEM_CERT", "/redis/certs/redisCA.crt")); } diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index 87e3cf870d..43a84b3d5a 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -96,7 +96,7 @@ redis: password: "${REDIS_PASSWORD:}" ssl: # Enable/disable secure connection - enabled: "${REDIS_SSL_ENABLED:false}" + enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) @@ -105,9 +105,9 @@ redis: pem: # Path redis server (CA) certificate cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file + # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # Keystore server credentials keystore: diff --git a/transport/http/src/main/resources/tb-http-transport.yml b/transport/http/src/main/resources/tb-http-transport.yml index 3f8af8bb91..e226319c20 100644 --- a/transport/http/src/main/resources/tb-http-transport.yml +++ b/transport/http/src/main/resources/tb-http-transport.yml @@ -129,7 +129,7 @@ redis: password: "${REDIS_PASSWORD:}" ssl: # Enable/disable secure connection - enabled: "${REDIS_SSL_ENABLED:false}" + enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) @@ -138,9 +138,9 @@ redis: pem: # Path redis server (CA) certificate cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file + # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # Keystore server credentials keystore: diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index 345f2eab5e..93a553eea5 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -96,7 +96,7 @@ redis: password: "${REDIS_PASSWORD:}" ssl: # Enable/disable secure connection - enabled: "${REDIS_SSL_ENABLED:false}" + enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) @@ -105,9 +105,9 @@ redis: pem: # Path redis server (CA) certificate cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file + # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # Keystore server credentials keystore: diff --git a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml index f04c06dc81..e2c65a4a63 100644 --- a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml +++ b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml @@ -97,7 +97,7 @@ redis: password: "${REDIS_PASSWORD:}" ssl: # Enable/disable secure connection - enabled: "${REDIS_SSL_ENABLED:false}" + enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) @@ -106,9 +106,9 @@ redis: pem: # Path redis server (CA) certificate cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file + # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # Keystore server credentials keystore: diff --git a/transport/snmp/src/main/resources/tb-snmp-transport.yml b/transport/snmp/src/main/resources/tb-snmp-transport.yml index a4e65a67c3..db20b596f0 100644 --- a/transport/snmp/src/main/resources/tb-snmp-transport.yml +++ b/transport/snmp/src/main/resources/tb-snmp-transport.yml @@ -96,7 +96,7 @@ redis: password: "${REDIS_PASSWORD:}" ssl: # Enable/disable secure connection - enabled: "${REDIS_SSL_ENABLED:false}" + enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) @@ -105,9 +105,9 @@ redis: pem: # Path redis server (CA) certificate cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file + # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # Keystore server credentials keystore: From c3e8c62ffcc51662f91e67f736e76f537a8270f2 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 23 Jan 2024 12:36:20 +0100 Subject: [PATCH 155/397] RPC deleteOutdatedRpcByTenantId simple native query. the test added --- .../service/ttl/rpc/RpcCleanUpService.java | 2 +- .../thingsboard/server/dao/rpc/RpcDao.java | 3 +- .../server/dao/sql/rpc/JpaRpcDao.java | 4 +- .../server/dao/sql/rpc/RpcRepository.java | 6 +- .../server/dao/sql/rpc/JpaRpcDaoTest.java | 59 +++++++++++++++++++ 5 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 dao/src/test/java/org/thingsboard/server/dao/sql/rpc/JpaRpcDaoTest.java diff --git a/application/src/main/java/org/thingsboard/server/service/ttl/rpc/RpcCleanUpService.java b/application/src/main/java/org/thingsboard/server/service/ttl/rpc/RpcCleanUpService.java index c8683972d9..57ba35628c 100644 --- a/application/src/main/java/org/thingsboard/server/service/ttl/rpc/RpcCleanUpService.java +++ b/application/src/main/java/org/thingsboard/server/service/ttl/rpc/RpcCleanUpService.java @@ -68,7 +68,7 @@ public class RpcCleanUpService { long ttl = TimeUnit.DAYS.toMillis(tenantProfileConfiguration.get().getRpcTtlDays()); long expirationTime = System.currentTimeMillis() - ttl; - long totalRemoved = rpcDao.deleteOutdatedRpcByTenantId(tenantId, expirationTime); + int totalRemoved = rpcDao.deleteOutdatedRpcByTenantId(tenantId, expirationTime); if (totalRemoved > 0) { log.info("Removed {} outdated rpc(s) for tenant {} older than {}", totalRemoved, tenantId, new Date(expirationTime)); diff --git a/dao/src/main/java/org/thingsboard/server/dao/rpc/RpcDao.java b/dao/src/main/java/org/thingsboard/server/dao/rpc/RpcDao.java index 79b73c69aa..d2e867e763 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rpc/RpcDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rpc/RpcDao.java @@ -30,5 +30,6 @@ public interface RpcDao extends Dao { PageData findAllRpcByTenantId(TenantId tenantId, PageLink pageLink); - Long deleteOutdatedRpcByTenantId(TenantId tenantId, Long expirationTime); + int deleteOutdatedRpcByTenantId(TenantId tenantId, Long expirationTime); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rpc/JpaRpcDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rpc/JpaRpcDao.java index 2c16db4d34..e1939a595c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/rpc/JpaRpcDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rpc/JpaRpcDao.java @@ -19,6 +19,7 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; @@ -67,8 +68,9 @@ public class JpaRpcDao extends JpaAbstractDao implements RpcDao return DaoUtil.toPageData(rpcRepository.findAllByTenantId(tenantId.getId(), DaoUtil.toPageable(pageLink))); } + @Transactional @Override - public Long deleteOutdatedRpcByTenantId(TenantId tenantId, Long expirationTime) { + public int deleteOutdatedRpcByTenantId(TenantId tenantId, Long expirationTime) { return rpcRepository.deleteOutdatedRpcByTenantId(tenantId.getId(), expirationTime); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rpc/RpcRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rpc/RpcRepository.java index e04d000a65..fe7c95d249 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/rpc/RpcRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rpc/RpcRepository.java @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.sql.rpc; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.thingsboard.server.common.data.rpc.RpcStatus; @@ -32,7 +33,8 @@ public interface RpcRepository extends JpaRepository { Page findAllByTenantId(UUID tenantId, Pageable pageable); - @Query(value = "WITH deleted AS (DELETE FROM rpc WHERE (tenant_id = :tenantId AND created_time < :expirationTime) IS TRUE RETURNING *) SELECT count(*) FROM deleted", + @Modifying + @Query(value = "DELETE FROM rpc WHERE tenant_id = :tenantId AND created_time < :expirationTime", nativeQuery = true) - Long deleteOutdatedRpcByTenantId(@Param("tenantId") UUID tenantId, @Param("expirationTime") Long expirationTime); + int deleteOutdatedRpcByTenantId(@Param("tenantId") UUID tenantId, @Param("expirationTime") Long expirationTime); } diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/rpc/JpaRpcDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/rpc/JpaRpcDaoTest.java new file mode 100644 index 0000000000..d2889dfb3c --- /dev/null +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/rpc/JpaRpcDaoTest.java @@ -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. + */ +package org.thingsboard.server.dao.sql.rpc; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.rpc.Rpc; +import org.thingsboard.server.common.data.rpc.RpcStatus; +import org.thingsboard.server.dao.AbstractJpaDaoTest; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JpaRpcDaoTest extends AbstractJpaDaoTest { + + @Autowired + JpaRpcDao rpcDao; + + @Test + public void deleteOutdated() { + Rpc rpc = new Rpc(); + rpc.setTenantId(TenantId.SYS_TENANT_ID); + rpc.setDeviceId(new DeviceId(UUID.randomUUID())); + rpc.setStatus(RpcStatus.QUEUED); + rpc.setRequest(JacksonUtil.toJsonNode("{}")); + rpcDao.saveAndFlush(rpc.getTenantId(), rpc); + + rpc.setId(null); + rpcDao.saveAndFlush(rpc.getTenantId(), rpc); + + TenantId tenantId = TenantId.fromUUID(UUID.fromString("3d193a7a-774b-4c05-84d5-f7fdcf7a37cf")); + rpc.setId(null); + rpc.setTenantId(tenantId); + rpc.setDeviceId(new DeviceId(UUID.randomUUID())); + rpcDao.saveAndFlush(rpc.getTenantId(), rpc); + + assertThat(rpcDao.deleteOutdatedRpcByTenantId(TenantId.SYS_TENANT_ID, 0L)).isEqualTo(0); + assertThat(rpcDao.deleteOutdatedRpcByTenantId(TenantId.SYS_TENANT_ID, Long.MAX_VALUE)).isEqualTo(2); + assertThat(rpcDao.deleteOutdatedRpcByTenantId(tenantId, System.currentTimeMillis() + 1)).isEqualTo(1); + } + +} From f44c05f285ca463a7d0bd2b32b1261bd96424586 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 23 Jan 2024 16:33:48 +0200 Subject: [PATCH 156/397] Support for multiple mobile sessions --- .../main/data/upgrade/3.6.2/schema_update.sql | 2 - .../server/controller/UserController.java | 30 ++++++++----- .../MobileAppNotificationChannel.java | 41 ++++++++++-------- .../server/controller/AbstractWebTest.java | 4 ++ .../notification/NotificationApiTest.java | 31 +++++++++----- .../server/dao/user/UserService.java | 11 +++-- .../MobileSessionInfo.java} | 5 +-- .../common/data/mobile/UserMobileInfo.java | 27 ++++++++++++ .../server/dao/sql/user/JpaUserDao.java | 6 --- .../dao/sql/user/JpaUserSettingsDao.java | 8 ++++ .../server/dao/sql/user/UserRepository.java | 8 ---- .../dao/sql/user/UserSettingsRepository.java | 7 ++++ .../thingsboard/server/dao/user/UserDao.java | 2 - .../server/dao/user/UserServiceImpl.java | 42 ++++++++++++++----- .../server/dao/user/UserSettingsDao.java | 5 +++ .../resources/sql/schema-entities-idx.sql | 2 - 16 files changed, 158 insertions(+), 73 deletions(-) rename common/data/src/main/java/org/thingsboard/server/common/data/{UserMobileInfo.java => mobile/MobileSessionInfo.java} (86%) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/mobile/UserMobileInfo.java diff --git a/application/src/main/data/upgrade/3.6.2/schema_update.sql b/application/src/main/data/upgrade/3.6.2/schema_update.sql index 9fb7921d0b..00d334b17d 100644 --- a/application/src/main/data/upgrade/3.6.2/schema_update.sql +++ b/application/src/main/data/upgrade/3.6.2/schema_update.sql @@ -33,5 +33,3 @@ $$ END IF; END; $$; - -CREATE INDEX IF NOT EXISTS idx_user_settings_mobile_fcm_token ON user_settings ((settings ->> 'fcmToken')) WHERE type = 'MOBILE'; diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 0269f6ec6f..a08e5e4bf7 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -26,11 +26,13 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -42,7 +44,6 @@ import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.UserEmailInfo; -import org.thingsboard.server.common.data.UserMobileInfo; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; @@ -51,6 +52,7 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.mobile.MobileSessionInfo; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.query.EntityDataPageLink; @@ -83,7 +85,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; @@ -120,6 +121,7 @@ public class UserController extends BaseController { public static final String PATHS = "paths"; public static final String YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION = "You don't have permission to perform this operation!"; public static final String ACTIVATE_URL_PATTERN = "%s/api/noauth/activate?activateToken=%s"; + public static final String MOBILE_TOKEN_HEADER = "X-Mobile-Token"; @Value("${security.user_token_access_enabled}") private boolean userTokenAccessEnabled; @@ -588,17 +590,25 @@ public class UserController extends BaseController { } @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - @GetMapping("/user/mobile/info") - public UserMobileInfo getMobileInfo(@AuthenticationPrincipal SecurityUser securityUser) { - return Optional.ofNullable(userService.findMobileInfo(securityUser.getTenantId(), securityUser.getId())) - .orElseGet(UserMobileInfo::new); + @GetMapping("/user/mobile/session") + public MobileSessionInfo getMobileSession(@RequestHeader(MOBILE_TOKEN_HEADER) String mobileToken, + @AuthenticationPrincipal SecurityUser user) { + return userService.findMobileSession(user.getTenantId(), user.getId(), mobileToken); } @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - @PostMapping("/user/mobile/info") - public void saveMobileInfo(@RequestBody UserMobileInfo mobileInfo, - @AuthenticationPrincipal SecurityUser securityUser) { - userService.saveMobileInfo(securityUser.getTenantId(), securityUser.getId(), mobileInfo); + @PostMapping("/user/mobile/session") + public void saveMobileSession(@RequestBody MobileSessionInfo sessionInfo, + @RequestHeader(MOBILE_TOKEN_HEADER) String mobileToken, + @AuthenticationPrincipal SecurityUser user) { + userService.saveMobileSession(user.getTenantId(), user.getId(), mobileToken, sessionInfo); + } + + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") + @DeleteMapping("/user/mobile/session") + public void removeMobileSession(@RequestHeader(MOBILE_TOKEN_HEADER) String mobileToken, + @AuthenticationPrincipal SecurityUser user) { + userService.removeMobileSession(user.getTenantId(), mobileToken); } private void checkNotReserved(String strType, UserSettingsType type) throws ThingsboardException { diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java index 0d9f8044cf..a1de832d14 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java @@ -18,10 +18,10 @@ package org.thingsboard.server.service.notification.channels; import com.google.firebase.messaging.FirebaseMessagingException; import com.google.firebase.messaging.MessagingErrorCode; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.rule.engine.api.notification.FirebaseService; import org.thingsboard.server.common.data.User; -import org.thingsboard.server.common.data.UserMobileInfo; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.settings.MobileAppNotificationDeliveryMethodConfig; @@ -31,10 +31,12 @@ import org.thingsboard.server.dao.notification.NotificationSettingsService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.service.notification.NotificationProcessingContext; -import java.util.Optional; +import java.util.HashSet; +import java.util.Set; @Component @RequiredArgsConstructor +@Slf4j public class MobileAppNotificationChannel implements NotificationChannel { private final FirebaseService firebaseService; @@ -43,24 +45,29 @@ public class MobileAppNotificationChannel implements NotificationChannel new IllegalArgumentException("User doesn't use the mobile app")); + var mobileSessions = userService.findMobileSessions(recipient.getTenantId(), recipient.getId()); + if (mobileSessions.isEmpty()) { + throw new IllegalArgumentException("User doesn't use the mobile app"); + } MobileAppNotificationDeliveryMethodConfig config = ctx.getDeliveryMethodConfig(NotificationDeliveryMethod.MOBILE_APP); - try { - firebaseService.sendMessage(ctx.getTenantId(), config.getFirebaseServiceAccountCredentials(), - fcmToken, processedTemplate.getSubject(), processedTemplate.getBody()); - } catch (FirebaseMessagingException e) { - MessagingErrorCode errorCode = e.getMessagingErrorCode(); - if (errorCode == MessagingErrorCode.UNREGISTERED || errorCode == MessagingErrorCode.INVALID_ARGUMENT) { - // the token is no longer valid - mobileInfo.setFcmToken(null); - userService.saveMobileInfo(recipient.getTenantId(), recipient.getId(), mobileInfo); - throw new IllegalArgumentException("User doesn't use the mobile app"); + String credentials = config.getFirebaseServiceAccountCredentials(); + Set validTokens = new HashSet<>(mobileSessions.keySet()); + for (String token : mobileSessions.keySet()) { + try { + firebaseService.sendMessage(ctx.getTenantId(), credentials, token, processedTemplate.getSubject(), processedTemplate.getBody()); + } catch (FirebaseMessagingException e) { + MessagingErrorCode errorCode = e.getMessagingErrorCode(); + if (errorCode == MessagingErrorCode.UNREGISTERED || errorCode == MessagingErrorCode.INVALID_ARGUMENT) { + validTokens.remove(token); + userService.removeMobileSession(recipient.getTenantId(), token); + continue; + } + throw new RuntimeException("Failed to send message via FCM: " + e.getMessage(), e); } - throw new RuntimeException("Failed to send message via FCM: " + e.getMessage(), e); + } + if (validTokens.isEmpty()) { + throw new IllegalArgumentException("User doesn't use the mobile app"); } } diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index 065e75d3e8..63c974fa96 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -189,6 +189,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { protected String token; protected String refreshToken; + protected String mobileToken; protected String username; protected TenantId tenantId; @@ -573,6 +574,9 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { if (this.token != null) { request.header(ThingsboardSecurityConfiguration.JWT_TOKEN_HEADER_PARAM, "Bearer " + this.token); } + if (this.mobileToken != null) { + request.header(UserController.MOBILE_TOKEN_HEADER, this.mobileToken); + } } protected DeviceProfile createDeviceProfile(String name) { diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java index be43e8dc08..d5a089dc82 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java @@ -31,13 +31,13 @@ import org.thingsboard.rule.engine.api.NotificationCenter; import org.thingsboard.rule.engine.api.notification.FirebaseService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; -import org.thingsboard.server.common.data.UserMobileInfo; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.NotificationRuleId; import org.thingsboard.server.common.data.id.NotificationTargetId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.mobile.MobileSessionInfo; import org.thingsboard.server.common.data.notification.Notification; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; import org.thingsboard.server.common.data.notification.NotificationRequest; @@ -93,6 +93,7 @@ import static org.assertj.core.api.InstanceOfAssertFactories.type; import static org.awaitility.Awaitility.await; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.timeout; @@ -109,8 +110,6 @@ public class NotificationApiTest extends AbstractNotificationApiTest { @Autowired private NotificationDao notificationDao; @Autowired - private DbCallbackExecutorService executor; - @Autowired private MicrosoftTeamsNotificationChannel microsoftTeamsNotificationChannel; @MockBean private FirebaseService firebaseService; @@ -726,14 +725,14 @@ public class NotificationApiTest extends AbstractNotificationApiTest { saveNotificationSettings(config); loginCustomerUser(); - UserMobileInfo customerMobileInfo = new UserMobileInfo(); - customerMobileInfo.setFcmToken("customerFcmToken"); - doPost("/api/user/mobile/info", customerMobileInfo).andExpect(status().isOk()); + mobileToken = "customerFcmToken"; + doPost("/api/user/mobile/session", new MobileSessionInfo()).andExpect(status().isOk()); loginTenantAdmin(); - UserMobileInfo tenantMobileInfo = new UserMobileInfo(); - tenantMobileInfo.setFcmToken("tenantFcmToken"); - doPost("/api/user/mobile/info", tenantMobileInfo).andExpect(status().isOk()); + mobileToken = "tenantFcmToken1"; + doPost("/api/user/mobile/session", new MobileSessionInfo()).andExpect(status().isOk()); + mobileToken = "tenantFcmToken2"; + doPost("/api/user/mobile/session", new MobileSessionInfo()).andExpect(status().isOk()); loginDifferentCustomer(); // with no mobile info @@ -748,7 +747,19 @@ public class NotificationApiTest extends AbstractNotificationApiTest { .contains("doesn't use the mobile app"); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("tenantFcmToken"), eq("Title"), eq("Message")); + eq("tenantFcmToken1"), eq("Title"), eq("Message")); + verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), + eq("tenantFcmToken2"), eq("Title"), eq("Message")); + verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), + eq("customerFcmToken"), eq("Title"), eq("Message")); + verifyNoMoreInteractions(firebaseService); + clearInvocations(firebaseService); + + doDelete("/api/user/mobile/session").andExpect(status().isOk()); + request = submitNotificationRequest(List.of(target.getId()), template.getId(), 0); + awaitNotificationRequest(request.getId()); + verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), + eq("tenantFcmToken1"), eq("Title"), eq("Message")); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), eq("customerFcmToken"), eq("Title"), eq("Message")); verifyNoMoreInteractions(firebaseService); diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java index 764f59d48b..f137bcc334 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.user; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.User; -import org.thingsboard.server.common.data.UserMobileInfo; +import org.thingsboard.server.common.data.mobile.MobileSessionInfo; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; @@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.dao.entity.EntityDaoService; import java.util.List; +import java.util.Map; public interface UserService extends EntityDaoService { @@ -90,8 +91,12 @@ public interface UserService extends EntityDaoService { void setLastLoginTs(TenantId tenantId, UserId userId); - void saveMobileInfo(TenantId tenantId, UserId userId, UserMobileInfo mobileInfo); + void saveMobileSession(TenantId tenantId, UserId userId, String mobileToken, MobileSessionInfo sessionInfo); - UserMobileInfo findMobileInfo(TenantId tenantId, UserId userId); + Map findMobileSessions(TenantId tenantId, UserId userId); + + MobileSessionInfo findMobileSession(TenantId tenantId, UserId userId, String mobileToken); + + void removeMobileSession(TenantId tenantId, String mobileToken); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/UserMobileInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileSessionInfo.java similarity index 86% rename from common/data/src/main/java/org/thingsboard/server/common/data/UserMobileInfo.java rename to common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileSessionInfo.java index 90680e1fff..721274f33a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/UserMobileInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/mobile/MobileSessionInfo.java @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.data; +package org.thingsboard.server.common.data.mobile; import lombok.Data; @Data -public class UserMobileInfo { - private String fcmToken; +public class MobileSessionInfo { private long fcmTokenTimestamp; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/mobile/UserMobileInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/mobile/UserMobileInfo.java new file mode 100644 index 0000000000..21f72dd4db --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/mobile/UserMobileInfo.java @@ -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. + */ +package org.thingsboard.server.common.data.mobile; + +import lombok.Data; + +import java.util.Map; + +@Data +public class UserMobileInfo { + + private Map sessions; + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java index 8352df0323..7749dbff29 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java @@ -33,7 +33,6 @@ import org.thingsboard.server.dao.user.UserDao; import org.thingsboard.server.dao.util.SqlDao; import java.util.List; -import java.util.Objects; import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; @@ -135,11 +134,6 @@ public class JpaUserDao extends JpaAbstractDao implements User DaoUtil.toPageable(pageLink))); } - @Override - public void unassignFcmToken(TenantId tenantId, String fcmToken) { - userRepository.unassignFcmToken(fcmToken); - } - @Override public Long countByTenantId(TenantId tenantId) { return userRepository.countByTenantId(tenantId.getId()); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDao.java index 1feabaacb5..52a78c41fe 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserSettingsDao.java @@ -21,12 +21,15 @@ import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.settings.UserSettings; import org.thingsboard.server.common.data.settings.UserSettingsCompositeKey; +import org.thingsboard.server.common.data.settings.UserSettingsType; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.model.sql.UserSettingsEntity; import org.thingsboard.server.dao.sql.JpaAbstractDaoListeningExecutorService; import org.thingsboard.server.dao.user.UserSettingsDao; import org.thingsboard.server.dao.util.SqlDao; +import java.util.List; + @Slf4j @Component @SqlDao @@ -50,4 +53,9 @@ public class JpaUserSettingsDao extends JpaAbstractDaoListeningExecutorService i userSettingsRepository.deleteById(id); } + @Override + public List findByTypeAndPath(TenantId tenantId, UserSettingsType type, String... path) { + return DaoUtil.convertDataList(userSettingsRepository.findByTypeAndPathExisting(type.name(), path)); + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java index 3419cd6340..79b0a00308 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java @@ -18,10 +18,8 @@ package org.thingsboard.server.dao.sql.user; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.model.sql.UserEntity; @@ -73,10 +71,4 @@ public interface UserRepository extends JpaRepository { Long countByTenantId(UUID tenantId); - @Query(value = "UPDATE user_settings SET settings = settings - 'fcmToken' " + - "WHERE type = 'MOBILE' AND (settings ->> 'fcmToken') = :fcmToken", nativeQuery = true) - @Modifying - @Transactional - void unassignFcmToken(@Param("fcmToken") String fcmToken); - } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserSettingsRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserSettingsRepository.java index cb81675a80..7f50b5ad5b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserSettingsRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserSettingsRepository.java @@ -16,9 +16,16 @@ package org.thingsboard.server.dao.sql.user; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.thingsboard.server.common.data.settings.UserSettingsCompositeKey; import org.thingsboard.server.dao.model.sql.UserSettingsEntity; +import java.util.List; + public interface UserSettingsRepository extends JpaRepository { + @Query(value = "SELECT * FROM user_settings WHERE type = :type AND (settings #> :path) IS NOT NULL", nativeQuery = true) + List findByTypeAndPathExisting(@Param("type") String type, @Param("path") String[] path); + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java index 59525174e0..42add1bbe2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java @@ -101,6 +101,4 @@ public interface UserDao extends Dao, TenantEntityDao { PageData findByAuthorityAndTenantProfilesIds(Authority authority, List tenantProfilesIds, PageLink pageLink); - void unassignFcmToken(TenantId tenantId, String fcmToken); - } diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java index 01b10863f9..4f662daba3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java @@ -21,7 +21,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.ListenableFuture; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.authentication.DisabledException; @@ -31,7 +30,6 @@ import org.springframework.transaction.annotation.Transactional; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; -import org.thingsboard.server.common.data.UserMobileInfo; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; @@ -40,6 +38,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.id.UserCredentialsId; import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.mobile.MobileSessionInfo; +import org.thingsboard.server.common.data.mobile.UserMobileInfo; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; @@ -56,6 +56,7 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -90,6 +91,7 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic private final UserCredentialsDao userCredentialsDao; private final UserAuthSettingsDao userAuthSettingsDao; private final UserSettingsService userSettingsService; + private final UserSettingsDao userSettingsDao; private final DataValidator userValidator; private final DataValidator userCredentialsValidator; private final ApplicationEventPublisher eventPublisher; @@ -397,19 +399,39 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic } @Override - public void saveMobileInfo(TenantId tenantId, UserId userId, UserMobileInfo mobileInfo) { - if (StringUtils.isNotEmpty(mobileInfo.getFcmToken())) { - // unassigning fcm token from other users, in case we didn't clean up it on log out or mobile app uninstall - userDao.unassignFcmToken(tenantId, mobileInfo.getFcmToken()); - } + public void saveMobileSession(TenantId tenantId, UserId userId, String mobileToken, MobileSessionInfo sessionInfo) { + removeMobileSession(tenantId, mobileToken); // unassigning fcm token from other users, in case we didn't clean up it on log out or mobile app uninstall + + UserMobileInfo mobileInfo = findMobileInfo(tenantId, userId).orElseGet(() -> { + UserMobileInfo newMobileInfo = new UserMobileInfo(); + newMobileInfo.setSessions(new HashMap<>()); + return newMobileInfo; + }); + mobileInfo.getSessions().put(mobileToken, sessionInfo); userSettingsService.updateUserSettings(tenantId, userId, UserSettingsType.MOBILE, JacksonUtil.valueToTree(mobileInfo)); } @Override - public UserMobileInfo findMobileInfo(TenantId tenantId, UserId userId) { + public Map findMobileSessions(TenantId tenantId, UserId userId) { + return findMobileInfo(tenantId, userId).map(UserMobileInfo::getSessions).orElse(Collections.emptyMap()); + } + + @Override + public MobileSessionInfo findMobileSession(TenantId tenantId, UserId userId, String mobileToken) { + return findMobileInfo(tenantId, userId).map(mobileInfo -> mobileInfo.getSessions().get(mobileToken)).orElse(null); + } + + @Override + public void removeMobileSession(TenantId tenantId, String mobileToken) { + for (UserSettings userSettings : userSettingsDao.findByTypeAndPath(tenantId, UserSettingsType.MOBILE, "sessions", mobileToken)) { + ((ObjectNode) userSettings.getSettings().get("sessions")).remove(mobileToken); + userSettingsService.saveUserSettings(tenantId, userSettings); + } + } + + private Optional findMobileInfo(TenantId tenantId, UserId userId) { return Optional.ofNullable(userSettingsService.findUserSettings(tenantId, userId, UserSettingsType.MOBILE)) - .map(UserSettings::getSettings).map(settings -> JacksonUtil.treeToValue(settings, UserMobileInfo.class)) - .orElse(null); + .map(UserSettings::getSettings).map(settings -> JacksonUtil.treeToValue(settings, UserMobileInfo.class)); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsDao.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsDao.java index f2e5474c58..23734118a9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserSettingsDao.java @@ -18,6 +18,9 @@ package org.thingsboard.server.dao.user; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.settings.UserSettings; import org.thingsboard.server.common.data.settings.UserSettingsCompositeKey; +import org.thingsboard.server.common.data.settings.UserSettingsType; + +import java.util.List; public interface UserSettingsDao { @@ -27,4 +30,6 @@ public interface UserSettingsDao { void removeById(TenantId tenantId, UserSettingsCompositeKey key); + List findByTypeAndPath(TenantId tenantId, UserSettingsType type, String... path); + } diff --git a/dao/src/main/resources/sql/schema-entities-idx.sql b/dao/src/main/resources/sql/schema-entities-idx.sql index 29adde3c8c..a177c1325f 100644 --- a/dao/src/main/resources/sql/schema-entities-idx.sql +++ b/dao/src/main/resources/sql/schema-entities-idx.sql @@ -127,5 +127,3 @@ CREATE INDEX IF NOT EXISTS idx_resource_etag ON resource(tenant_id, etag); CREATE INDEX IF NOT EXISTS idx_resource_etag ON resource(tenant_id, etag); CREATE INDEX IF NOT EXISTS idx_resource_type_public_resource_key ON resource(resource_type, public_resource_key); - -CREATE INDEX IF NOT EXISTS idx_user_settings_mobile_fcm_token ON user_settings ((settings ->> 'fcmToken')) WHERE type = 'MOBILE'; From ad98dd0db17afaf1bd8a3485fa155a473cab929f Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 23 Jan 2024 16:34:41 +0200 Subject: [PATCH 157/397] Fix SQL error messages --- .../server/controller/BaseController.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index f36f63f069..8e0e958262 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -16,14 +16,16 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.MoreExecutors; import lombok.Getter; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.postgresql.util.PSQLException; +import org.postgresql.util.ServerErrorMessage; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.dao.DataAccessException; import org.springframework.http.MediaType; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -46,7 +48,6 @@ import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.OtaPackage; import org.thingsboard.server.common.data.OtaPackageInfo; -import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TbResourceInfo; import org.thingsboard.server.common.data.Tenant; @@ -376,6 +377,14 @@ public abstract class BaseController { return new ThingsboardException("Unable to send mail: " + exception.getMessage(), ThingsboardErrorCode.GENERAL); } else if (exception instanceof AsyncRequestTimeoutException) { return new ThingsboardException("Request timeout", ThingsboardErrorCode.GENERAL); + } else if (exception instanceof DataAccessException) { + Throwable rootCause = ExceptionUtils.getRootCause(exception); + if (rootCause instanceof PSQLException) { + return new ThingsboardException(Optional.ofNullable(((PSQLException) rootCause).getServerErrorMessage()) + .map(ServerErrorMessage::getMessage).orElse(rootCause.getMessage()), ThingsboardErrorCode.GENERAL); + } else { + return new ThingsboardException(rootCause, ThingsboardErrorCode.GENERAL); + } } else { return new ThingsboardException(exception.getMessage(), exception, ThingsboardErrorCode.GENERAL); } From 053bcc0abe9b7798111548ea414ba850f2f8a78c Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 23 Jan 2024 12:36:40 +0100 Subject: [PATCH 158/397] Log Hibernate SQL queries in the dao test scope (commented) --- dao/src/test/resources/logback.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dao/src/test/resources/logback.xml b/dao/src/test/resources/logback.xml index 61397ec6f1..5e293b2982 100644 --- a/dao/src/test/resources/logback.xml +++ b/dao/src/test/resources/logback.xml @@ -10,6 +10,9 @@ + + + From c9d97553b8761c8a4a26822958c21c81364888b1 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 24 Jan 2024 11:10:17 +0200 Subject: [PATCH 159/397] Update license headers with 2024 year. --- .../server/service/queue/DefaultTbCoreConsumerServiceTest.java | 2 +- .../thingsboard/server/queue/common/SimpleTbQueueCallback.java | 2 +- .../org/thingsboard/rule/engine/action/TbDeviceStateNode.java | 2 +- .../rule/engine/action/TbDeviceStateNodeConfiguration.java | 2 +- .../thingsboard/rule/engine/action/TbDeviceStateNodeTest.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerServiceTest.java b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerServiceTest.java index 3ac86dac0c..fd7e2077d4 100644 --- a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerServiceTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/common/SimpleTbQueueCallback.java b/common/queue/src/main/java/org/thingsboard/server/queue/common/SimpleTbQueueCallback.java index 805511a603..5f86060d48 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/common/SimpleTbQueueCallback.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/common/SimpleTbQueueCallback.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. 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 c3593d6cc7..63ebf09b9c 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 @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeConfiguration.java index c89fcb076f..c23338fcd1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeConfiguration.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java index cb81b4d2e4..246e5b3459 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From e275678c22e4ba89eaca353117c140150fbdb016 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 24 Jan 2024 12:55:09 +0200 Subject: [PATCH 160/397] Add check for negative and outdated inactivity event timestamp. --- .../state/DefaultDeviceStateService.java | 14 +++++- .../state/DefaultDeviceStateServiceTest.java | 49 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java index 458412b437..ee7b4a7e72 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java @@ -297,8 +297,20 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService givenOutdatedLastInactivityTime_whenOnDeviceInactivity_thenSkipsThisEvent() { + return Stream.of( + Arguments.of(0, 0), + Arguments.of(0, 100), + Arguments.of(50, 100), + Arguments.of(99, 100), + Arguments.of(100, 100) + ); + } + @Test public void givenDeviceBelongsToMyPartition_whenOnDeviceInactivity_thenReportsInactivity() { // GIVEN From ab21a1395b9554178dda383107231dbf75055ae3 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 24 Jan 2024 13:06:40 +0200 Subject: [PATCH 161/397] Remove unnecessary times(1) in test verifications --- .../state/DefaultDeviceStateServiceTest.java | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java b/application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java index 816043c4d4..c924e6d93c 100644 --- a/application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java @@ -76,7 +76,6 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.thingsboard.server.common.data.DataConstants.SERVER_SCOPE; @@ -135,7 +134,7 @@ public class DefaultDeviceStateServiceTest { service.onDeviceInactivity(tenantId, deviceId, System.currentTimeMillis()); // THEN - then(service).should(times(1)).cleanDeviceStateIfBelongsToExternalPartition(tenantId, deviceId); + then(service).should().cleanDeviceStateIfBelongsToExternalPartition(tenantId, deviceId); then(service).should(never()).fetchDeviceStateDataUsingSeparateRequests(deviceId); then(clusterService).shouldHaveNoInteractions(); then(notificationRuleProcessor).shouldHaveNoInteractions(); @@ -209,24 +208,24 @@ public class DefaultDeviceStateServiceTest { service.onDeviceInactivity(tenantId, deviceId, lastInactivityTime); // THEN - then(telemetrySubscriptionService).should(times(1)).saveAttrAndNotify( + then(telemetrySubscriptionService).should().saveAttrAndNotify( eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), eq(INACTIVITY_ALARM_TIME), eq(lastInactivityTime), any() ); - then(telemetrySubscriptionService).should(times(1)).saveAttrAndNotify( + then(telemetrySubscriptionService).should().saveAttrAndNotify( eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), eq(ACTIVITY_STATE), eq(false), any() ); var msgCaptor = ArgumentCaptor.forClass(TbMsg.class); - then(clusterService).should(times(1)) + then(clusterService).should() .pushMsgToRuleEngine(eq(tenantId), eq(deviceId), msgCaptor.capture(), any()); var actualMsg = msgCaptor.getValue(); assertThat(actualMsg.getType()).isEqualTo(TbMsgType.INACTIVITY_EVENT.name()); assertThat(actualMsg.getOriginator()).isEqualTo(deviceId); var notificationCaptor = ArgumentCaptor.forClass(DeviceActivityTrigger.class); - then(notificationRuleProcessor).should(times(1)).process(notificationCaptor.capture()); + then(notificationRuleProcessor).should().process(notificationCaptor.capture()); var actualNotification = notificationCaptor.getValue(); assertThat(actualNotification.getTenantId()).isEqualTo(tenantId); assertThat(actualNotification.getDeviceId()).isEqualTo(deviceId); @@ -249,24 +248,24 @@ public class DefaultDeviceStateServiceTest { service.updateInactivityStateIfExpired(System.currentTimeMillis(), deviceId, deviceStateData); // THEN - then(telemetrySubscriptionService).should(times(1)).saveAttrAndNotify( + then(telemetrySubscriptionService).should().saveAttrAndNotify( eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), eq(INACTIVITY_ALARM_TIME), anyLong(), any() ); - then(telemetrySubscriptionService).should(times(1)).saveAttrAndNotify( + then(telemetrySubscriptionService).should().saveAttrAndNotify( eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), eq(ACTIVITY_STATE), eq(false), any() ); var msgCaptor = ArgumentCaptor.forClass(TbMsg.class); - then(clusterService).should(times(1)) + then(clusterService).should() .pushMsgToRuleEngine(eq(tenantId), eq(deviceId), msgCaptor.capture(), any()); var actualMsg = msgCaptor.getValue(); assertThat(actualMsg.getType()).isEqualTo(TbMsgType.INACTIVITY_EVENT.name()); assertThat(actualMsg.getOriginator()).isEqualTo(deviceId); var notificationCaptor = ArgumentCaptor.forClass(DeviceActivityTrigger.class); - then(notificationRuleProcessor).should(times(1)).process(notificationCaptor.capture()); + then(notificationRuleProcessor).should().process(notificationCaptor.capture()); var actualNotification = notificationCaptor.getValue(); assertThat(actualNotification.getTenantId()).isEqualTo(tenantId); assertThat(actualNotification.getDeviceId()).isEqualTo(deviceId); @@ -287,7 +286,7 @@ public class DefaultDeviceStateServiceTest { willReturn(deviceStateDataMock).given(service).fetchDeviceStateDataUsingSeparateRequests(deviceId); DeviceStateData deviceStateData = service.getOrFetchDeviceStateData(deviceId); assertThat(deviceStateData).isEqualTo(deviceStateDataMock); - verify(service, times(1)).fetchDeviceStateDataUsingSeparateRequests(deviceId); + verify(service).fetchDeviceStateDataUsingSeparateRequests(deviceId); } @Test @@ -513,7 +512,7 @@ public class DefaultDeviceStateServiceTest { } private void activityVerify(boolean isActive) { - verify(telemetrySubscriptionService, times(1)).saveAttrAndNotify(any(), eq(deviceId), any(), eq(ACTIVITY_STATE), eq(isActive), any()); + verify(telemetrySubscriptionService).saveAttrAndNotify(any(), eq(deviceId), any(), eq(ACTIVITY_STATE), eq(isActive), any()); } @Test @@ -869,7 +868,7 @@ public class DefaultDeviceStateServiceTest { } } - then(service).should(times(1)).fetchDeviceStateDataUsingSeparateRequests(deviceId); + then(service).should().fetchDeviceStateDataUsingSeparateRequests(deviceId); } } From dfe23510799e4b639a8c46a5a8536af48a0fbc03 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 24 Jan 2024 13:11:32 +0200 Subject: [PATCH 162/397] yml parameter description update --- application/src/main/resources/thingsboard.yml | 2 +- transport/coap/src/main/resources/tb-coap-transport.yml | 2 +- transport/http/src/main/resources/tb-http-transport.yml | 2 +- transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml | 2 +- transport/mqtt/src/main/resources/tb-mqtt-transport.yml | 2 +- transport/snmp/src/main/resources/tb-snmp-transport.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 18565f463e..38cfdd64a0 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -645,7 +645,7 @@ redis: enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: - # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) + # Server credentials type (pem - pem certificate file; keystore - java keystore) type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" # PEM server credentials pem: diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index 43a84b3d5a..78ca89851d 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -99,7 +99,7 @@ redis: enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: - # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) + # Server credentials type (pem - pem certificate file; keystore - java keystore) type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" # PEM server credentials pem: diff --git a/transport/http/src/main/resources/tb-http-transport.yml b/transport/http/src/main/resources/tb-http-transport.yml index e226319c20..04a9c9417f 100644 --- a/transport/http/src/main/resources/tb-http-transport.yml +++ b/transport/http/src/main/resources/tb-http-transport.yml @@ -132,7 +132,7 @@ redis: enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: - # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) + # Server credentials type (pem - pem certificate file; keystore - java keystore) type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" # PEM server credentials pem: diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index 93a553eea5..c079f690ed 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -99,7 +99,7 @@ redis: enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: - # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) + # Server credentials type (pem - pem certificate file; keystore - java keystore) type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" # PEM server credentials pem: diff --git a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml index e2c65a4a63..430b5bfed5 100644 --- a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml +++ b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml @@ -100,7 +100,7 @@ redis: enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: - # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) + # Server credentials type (pem - pem certificate file; keystore - java keystore) type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" # PEM server credentials pem: diff --git a/transport/snmp/src/main/resources/tb-snmp-transport.yml b/transport/snmp/src/main/resources/tb-snmp-transport.yml index db20b596f0..68b69bb03a 100644 --- a/transport/snmp/src/main/resources/tb-snmp-transport.yml +++ b/transport/snmp/src/main/resources/tb-snmp-transport.yml @@ -99,7 +99,7 @@ redis: enabled: "${TB_REDIS_SSL_ENABLED:false}" # Server SSL credentials credentials: - # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) + # Server credentials type (pem - pem certificate file; keystore - java keystore) type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" # PEM server credentials pem: From 1822703730ee2bace9aed2ebc907df8e79dea4c2 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 24 Jan 2024 13:15:33 +0200 Subject: [PATCH 163/397] Add default overloads with current time millis for onDeviceConnect() and onDeviceDisconnect(). --- .../server/actors/device/DeviceActorMessageProcessor.java | 4 ++-- .../server/service/state/DeviceStateService.java | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index c5625ee8ad..58bd82abb3 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -490,11 +490,11 @@ public class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcesso } private void reportSessionOpen() { - systemContext.getDeviceStateService().onDeviceConnect(tenantId, deviceId, System.currentTimeMillis()); + systemContext.getDeviceStateService().onDeviceConnect(tenantId, deviceId); } private void reportSessionClose() { - systemContext.getDeviceStateService().onDeviceDisconnect(tenantId, deviceId, System.currentTimeMillis()); + systemContext.getDeviceStateService().onDeviceDisconnect(tenantId, deviceId); } private void handleGetAttributesRequest(SessionInfoProto sessionInfo, GetAttributeRequestMsg request) { diff --git a/application/src/main/java/org/thingsboard/server/service/state/DeviceStateService.java b/application/src/main/java/org/thingsboard/server/service/state/DeviceStateService.java index 85d5645e1e..3ab5d29194 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DeviceStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DeviceStateService.java @@ -29,10 +29,18 @@ public interface DeviceStateService extends ApplicationListener Date: Wed, 24 Jan 2024 13:29:08 +0200 Subject: [PATCH 164/397] Refactor device state node test. --- .../engine/action/TbDeviceStateNodeTest.java | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java index 246e5b3459..2882493f84 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java @@ -88,15 +88,11 @@ public class TbDeviceStateNodeTest { @BeforeEach public void setUp() { node = new TbDeviceStateNode(); - config = new TbDeviceStateNodeConfiguration(); + config = new TbDeviceStateNodeConfiguration().defaultConfiguration(); } @Test public void givenDefaultConfiguration_whenInvoked_thenCorrectValuesAreSet() { - // GIVEN-WHEN - config = config.defaultConfiguration(); - - // THEN assertThat(config.getEvent()).isEqualTo(TbMsgType.ACTIVITY_EVENT); assertThat(TbDeviceStateNode.SUPPORTED_EVENTS).isEqualTo(Set.of( TbMsgType.CONNECT_EVENT, TbMsgType.ACTIVITY_EVENT, @@ -135,15 +131,15 @@ public class TbDeviceStateNodeTest { public void givenNonDeviceOriginator_whenOnMsg_thenTellsSuccessAndNoActivityActionsTriggered() { // GIVEN var asset = new AssetId(UUID.randomUUID()); - var msg = TbMsg.newMsg(TbMsgType.ENTITY_CREATED, asset, new TbMsgMetaData(), "{}"); + var msg = TbMsg.newMsg(TbMsgType.ENTITY_CREATED, asset, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); given(ctxMock.isLocalEntity(asset)).willReturn(true); // WHEN node.onMsg(ctxMock, msg); // THEN - then(ctxMock).should(times(1)).isLocalEntity(asset); - then(ctxMock).should(times(1)).tellSuccess(msg); + then(ctxMock).should().isLocalEntity(asset); + then(ctxMock).should().tellSuccess(msg); then(ctxMock).shouldHaveNoMoreInteractions(); } @@ -158,18 +154,13 @@ public class TbDeviceStateNodeTest { node.onMsg(ctxMock, msg); // THEN - then(ctxMock).should(times(1)).isLocalEntity(DEVICE_ID); - then(ctxMock).should().getTenantId(); - then(ctxMock).should().getSelfId(); - then(ctxMock).should(times(1)).ack(msg); + then(ctxMock).should().ack(msg); then(ctxMock).shouldHaveNoMoreInteractions(); } @ParameterizedTest @MethodSource("provideSupportedEventsAndExpectedMessages") - public void givenSupportedEvent_whenOnMsg_thenCorrectMsgIsSent( - TbMsgType event, TransportProtos.ToCoreMsg expectedToCoreMsg - ) { + public void givenSupportedEvent_whenOnMsg_thenCorrectMsgIsSent(TbMsgType event, TransportProtos.ToCoreMsg expectedToCoreMsg) { // GIVEN config.setEvent(event); var nodeConfig = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); @@ -188,17 +179,16 @@ public class TbDeviceStateNodeTest { // THEN var protoCaptor = ArgumentCaptor.forClass(TransportProtos.ToCoreMsg.class); var callbackCaptor = ArgumentCaptor.forClass(TbQueueCallback.class); - then(tbClusterServiceMock).should(times(1)) - .pushMsgToCore(eq(TENANT_ID), eq(DEVICE_ID), protoCaptor.capture(), callbackCaptor.capture()); + then(tbClusterServiceMock).should().pushMsgToCore(eq(TENANT_ID), eq(DEVICE_ID), protoCaptor.capture(), callbackCaptor.capture()); TbQueueCallback actualCallback = callbackCaptor.getValue(); actualCallback.onSuccess(null); - then(ctxMock).should(times(1)).tellSuccess(msg); + then(ctxMock).should().tellSuccess(msg); var throwable = new Throwable(); actualCallback.onFailure(throwable); - then(ctxMock).should(times(1)).tellFailure(msg, throwable); + then(ctxMock).should().tellFailure(msg, throwable); assertThat(expectedToCoreMsg).isEqualTo(protoCaptor.getValue()); From 653ea4a80097c4ea3b7bce05f96d09f873003091 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 24 Jan 2024 15:07:42 +0200 Subject: [PATCH 165/397] Add check for negative and outdated disconnect event timestamp. --- .../state/DefaultDeviceStateService.java | 16 +++- .../state/DefaultDeviceStateServiceTest.java | 90 ++++++++++++++++++- 2 files changed, 101 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java index ee7b4a7e72..941ffef8fa 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java @@ -271,8 +271,19 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService givenOutdatedLastInactivityTime_whenOnDeviceInactivity_thenSkipsThisEvent() { + private static Stream provideOutdatedTimestamps() { return Stream.of( Arguments.of(0, 0), Arguments.of(0, 100), From d0530e63615f3efe5e42eccd1883666d19547f34 Mon Sep 17 00:00:00 2001 From: Ivan Raznatovskyi Date: Wed, 24 Jan 2024 15:52:46 +0200 Subject: [PATCH 166/397] Updated default value for params field and fixed patching value --- .../lib/gateway/gateway-service-rpc-connector.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts index 391fa190fe..69b785d133 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts @@ -279,7 +279,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue default: formGroup = this.fb.group({ command: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], - params: ['{}', [jsonRequired]], + params: [{}, [jsonRequired]], }) } return formGroup; @@ -359,7 +359,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, ControlValue }).afterClosed().subscribe( (res) => { if (res) { - this.commandForm.get('params').setValue(JSON.stringify(res)); + this.commandForm.get('params').setValue(res); } } ); From c81d9438540905133ab8568af4bd361411a15990 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 24 Jan 2024 16:11:19 +0200 Subject: [PATCH 167/397] Add check for negative and outdated connect event timestamp. --- .../state/DefaultDeviceStateService.java | 13 ++- .../state/DefaultDeviceStateServiceTest.java | 88 +++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java index 941ffef8fa..b400b4f65a 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java @@ -226,8 +226,19 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService Date: Wed, 24 Jan 2024 16:25:26 +0200 Subject: [PATCH 168/397] Remove excessive brackets in switch-case --- .../rule/engine/action/TbDeviceStateNode.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) 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 63ebf09b9c..ccc252c912 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 @@ -93,25 +93,20 @@ public class TbDeviceStateNode implements TbNode { return; } switch (event) { - case CONNECT_EVENT: { + case CONNECT_EVENT: sendDeviceConnectMsg(ctx, msg); break; - } - case ACTIVITY_EVENT: { + case ACTIVITY_EVENT: sendDeviceActivityMsg(ctx, msg); break; - } - case DISCONNECT_EVENT: { + case DISCONNECT_EVENT: sendDeviceDisconnectMsg(ctx, msg); break; - } - case INACTIVITY_EVENT: { + case INACTIVITY_EVENT: sendDeviceInactivityMsg(ctx, msg); break; - } - default: { + default: ctx.tellFailure(msg, new IllegalStateException("Configured event [" + event + "] is not supported!")); - } } } From 5e846116a885c655bb471776153f843c7f419a34 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 24 Jan 2024 17:27:10 +0200 Subject: [PATCH 169/397] Use consumer instead of runnable in SimpleTbQueueCallback --- .../actors/ruleChain/DefaultTbContext.java | 40 ++++++++++++------- .../queue/common/SimpleTbQueueCallback.java | 6 +-- .../rule/engine/action/TbDeviceStateNode.java | 2 +- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java index baae03761b..1e7d5d24e9 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java @@ -214,13 +214,19 @@ class DefaultTbContext implements TbContext { if (nodeCtx.getSelf().isDebugMode()) { mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), tbMsg, "To Root Rule Chain"); } - mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg, new SimpleTbQueueCallback(onSuccess, t -> { - if (onFailure != null) { - onFailure.accept(t); - } else { - log.debug("[{}] Failed to put item into queue!", nodeCtx.getTenantId().getId(), t); - } - })); + mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg, new SimpleTbQueueCallback( + metadata -> { + if (onSuccess != null) { + onSuccess.run(); + } + }, + t -> { + if (onFailure != null) { + onFailure.accept(t); + } else { + log.debug("[{}] Failed to put item into queue!", nodeCtx.getTenantId().getId(), t); + } + })); } @Override @@ -306,13 +312,19 @@ class DefaultTbContext implements TbContext { relationTypes.forEach(relationType -> mainCtx.persistDebugOutput(nodeCtx.getTenantId(), nodeCtx.getSelf().getId(), tbMsg, relationType, null, failureMessage)); } - mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg.build(), new SimpleTbQueueCallback(onSuccess, t -> { - if (onFailure != null) { - onFailure.accept(t); - } else { - log.debug("[{}] Failed to put item into queue!", nodeCtx.getTenantId().getId(), t); - } - })); + mainCtx.getClusterService().pushMsgToRuleEngine(tpi, tbMsg.getId(), msg.build(), new SimpleTbQueueCallback( + metadata -> { + if (onSuccess != null) { + onSuccess.run(); + } + }, + t -> { + if (onFailure != null) { + onFailure.accept(t); + } else { + log.debug("[{}] Failed to put item into queue!", nodeCtx.getTenantId().getId(), t); + } + })); } @Override diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/common/SimpleTbQueueCallback.java b/common/queue/src/main/java/org/thingsboard/server/queue/common/SimpleTbQueueCallback.java index 5f86060d48..d153998ab4 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/common/SimpleTbQueueCallback.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/common/SimpleTbQueueCallback.java @@ -22,10 +22,10 @@ import java.util.function.Consumer; public class SimpleTbQueueCallback implements TbQueueCallback { - private final Runnable onSuccess; + private final Consumer onSuccess; private final Consumer onFailure; - public SimpleTbQueueCallback(Runnable onSuccess, Consumer onFailure) { + public SimpleTbQueueCallback(Consumer onSuccess, Consumer onFailure) { this.onSuccess = onSuccess; this.onFailure = onFailure; } @@ -33,7 +33,7 @@ public class SimpleTbQueueCallback implements TbQueueCallback { @Override public void onSuccess(TbQueueMsgMetadata metadata) { if (onSuccess != null) { - onSuccess.run(); + onSuccess.accept(metadata); } } 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 ccc252c912..65d7e0979e 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 @@ -183,7 +183,7 @@ public class TbDeviceStateNode implements TbNode { } private TbQueueCallback getMsgEnqueuedCallback(TbContext ctx, TbMsg msg) { - return new SimpleTbQueueCallback(() -> ctx.tellSuccess(msg), t -> ctx.tellFailure(msg, t)); + return new SimpleTbQueueCallback(metadata -> ctx.tellSuccess(msg), t -> ctx.tellFailure(msg, t)); } } From c65a9c2e0d559bc114d4b366b86af79a64d1c85d Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 24 Jan 2024 17:58:24 +0200 Subject: [PATCH 170/397] Remove unnecessary originator locality check --- .../rule/engine/action/TbDeviceStateNode.java | 9 +-------- .../engine/action/TbDeviceStateNodeTest.java | 18 ------------------ 2 files changed, 1 insertion(+), 26 deletions(-) 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 65d7e0979e..f28a3e4467 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 @@ -81,14 +81,7 @@ public class TbDeviceStateNode implements TbNode { @Override public void onMsg(TbContext ctx, TbMsg msg) { - var originator = msg.getOriginator(); - if (!ctx.isLocalEntity(originator)) { - log.warn("[{}][{}] Received message from non-local entity [{}]!", - ctx.getTenantId().getId(), ctx.getSelfId().getId(), originator.getId()); - ctx.ack(msg); - return; - } - if (!EntityType.DEVICE.equals(originator.getEntityType())) { + if (!EntityType.DEVICE.equals(msg.getOriginator().getEntityType())) { ctx.tellSuccess(msg); return; } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java index 2882493f84..988d8911a4 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java @@ -132,32 +132,15 @@ public class TbDeviceStateNodeTest { // GIVEN var asset = new AssetId(UUID.randomUUID()); var msg = TbMsg.newMsg(TbMsgType.ENTITY_CREATED, asset, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); - given(ctxMock.isLocalEntity(asset)).willReturn(true); // WHEN node.onMsg(ctxMock, msg); // THEN - then(ctxMock).should().isLocalEntity(asset); then(ctxMock).should().tellSuccess(msg); then(ctxMock).shouldHaveNoMoreInteractions(); } - @Test - public void givenNonLocalOriginator_whenOnMsg_thenTellsSuccessAndNoActivityActionsTriggered() { - // GIVEN - given(ctxMock.isLocalEntity(msg.getOriginator())).willReturn(false); - given(ctxMock.getSelfId()).willReturn(new RuleNodeId(UUID.randomUUID())); - given(ctxMock.getTenantId()).willReturn(TENANT_ID); - - // WHEN - node.onMsg(ctxMock, msg); - - // THEN - then(ctxMock).should().ack(msg); - then(ctxMock).shouldHaveNoMoreInteractions(); - } - @ParameterizedTest @MethodSource("provideSupportedEventsAndExpectedMessages") public void givenSupportedEvent_whenOnMsg_thenCorrectMsgIsSent(TbMsgType event, TransportProtos.ToCoreMsg expectedToCoreMsg) { @@ -171,7 +154,6 @@ public class TbDeviceStateNodeTest { } given(ctxMock.getTenantId()).willReturn(TENANT_ID); given(ctxMock.getClusterService()).willReturn(tbClusterServiceMock); - given(ctxMock.isLocalEntity(msg.getOriginator())).willReturn(true); // WHEN node.onMsg(ctxMock, msg); From d7a24648ff7ad463461552e317f67305c1460224 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 25 Jan 2024 12:11:53 +0200 Subject: [PATCH 171/397] Add stats for connect, disconnect and inactivity events --- .../queue/DefaultTbCoreConsumerService.java | 9 +++++++ .../service/queue/TbCoreConsumerStats.java | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index 3a0e0e76d8..41f7cc012c 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -660,6 +660,9 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService Date: Wed, 24 Jan 2024 11:28:28 +0100 Subject: [PATCH 172/397] Support DTLS Connection ID with configuration --- .../src/main/resources/thingsboard.yml | 2 + .../LwM2MTransportBootstrapService.java | 2 + .../config/LwM2MTransportServerConfig.java | 4 + .../server/DefaultLwM2mTransportService.java | 2 + .../LwM2MTransportBootstrapServiceTest.java | 105 +++++++++++++++++ .../LwM2MTransportServerConfigTest.java | 61 ++++++++++ .../DefaultLwM2mTransportServiceTest.java | 109 ++++++++++++++++++ .../src/main/resources/tb-lwm2m-transport.yml | 2 + 8 files changed, 287 insertions(+) create mode 100644 common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java create mode 100644 common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfigTest.java create mode 100644 common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportServiceTest.java diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 936f30af60..395eefeb45 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1044,6 +1044,8 @@ transport: dtls: # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}" + # "" disables connection id support, 0 enables support but not for incoming traffic, any value greater than 0 set the connection id size in bytes + connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:6}" server: # LwM2M Server ID id: "${LWM2M_SERVER_ID:123}" diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java index 4bdcbcf645..a9166b0bf1 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java @@ -38,6 +38,7 @@ import javax.annotation.PreDestroy; import java.security.cert.X509Certificate; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CURVES_ONLY; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMISSION_TIMEOUT; @@ -95,6 +96,7 @@ public class LwM2MTransportBootstrapService { dtlsConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, serverConfig.isRecommendedSupportedGroups()); dtlsConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, serverConfig.isRecommendedCiphers()); dtlsConfig.set(DTLS_RETRANSMISSION_TIMEOUT, serverConfig.getDtlsRetransmissionTimeout(), MILLISECONDS); + dtlsConfig.set(DTLS_CONNECTION_ID_LENGTH, serverConfig.getDtlsConnectionIdLength()); dtlsConfig.set(DTLS_ROLE, SERVER_ONLY); setServerWithCredentials(builder, dtlsConfig); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java index 0ccf6e1969..dc2e9f6d45 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java @@ -41,6 +41,10 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.dtls.retransmission_timeout:9000}") private int dtlsRetransmissionTimeout; + @Getter + @Value("${transport.lwm2m.dtls.connection_id_length:6}") + private Integer dtlsConnectionIdLength; + @Getter @Value("${transport.lwm2m.timeout:}") private Long timeout; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index 4037251572..7d54e97cde 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -43,6 +43,7 @@ import javax.annotation.PreDestroy; import java.security.cert.X509Certificate; import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CURVES_ONLY; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMISSION_TIMEOUT; @@ -139,6 +140,7 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { dtlsConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, config.isRecommendedSupportedGroups()); dtlsConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, config.isRecommendedCiphers()); dtlsConfig.set(DTLS_RETRANSMISSION_TIMEOUT, config.getDtlsRetransmissionTimeout(), MILLISECONDS); + dtlsConfig.set(DTLS_CONNECTION_ID_LENGTH, config.getDtlsConnectionIdLength()); dtlsConfig.set(DTLS_ROLE, SERVER_ONLY); /* Create credentials */ diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java new file mode 100644 index 0000000000..23293c7b7a --- /dev/null +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java @@ -0,0 +1,105 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.bootstrap; + +import org.eclipse.californium.core.network.CoapEndpoint; +import org.eclipse.californium.scandium.config.DtlsConnectorConfig; +import org.eclipse.leshan.server.californium.LeshanServer; +import org.eclipse.leshan.server.californium.bootstrap.LeshanBootstrapServer; +import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.util.ReflectionTestUtils; +import org.thingsboard.server.cache.ota.OtaPackageDataCache; +import org.thingsboard.server.common.transport.TransportService; +import org.thingsboard.server.transport.lwm2m.bootstrap.secure.TbLwM2MDtlsBootstrapCertificateVerifier; +import org.thingsboard.server.transport.lwm2m.bootstrap.store.LwM2MBootstrapSecurityStore; +import org.thingsboard.server.transport.lwm2m.bootstrap.store.LwM2MInMemoryBootstrapConfigStore; +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportBootstrapConfig; +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer; +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MDtlsCertificateVerifier; +import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore; +import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.when; + +@ExtendWith(MockitoExtension.class) +public class LwM2MTransportBootstrapServiceTest { + + @Mock + private LwM2MTransportServerConfig serverConfig; + @Mock + private LwM2MTransportBootstrapConfig bootstrapConfig; + @Mock + private LwM2MBootstrapSecurityStore lwM2MBootstrapSecurityStore; + @Mock + private LwM2MInMemoryBootstrapConfigStore lwM2MInMemoryBootstrapConfigStore; + @Mock + private TransportService transportService; + @Mock + private TbLwM2MDtlsBootstrapCertificateVerifier certificateVerifier; + + + @Test + public void getLHServer_creates_ConnectionIdGenerator_when_connection_id_length_not_null(){ + final Integer CONNECTION_ID_LENGTH = 6; + when(serverConfig.getDtlsConnectionIdLength()).thenReturn(CONNECTION_ID_LENGTH); + var lwM2MBootstrapService = createLwM2MBootstrapService(); + + var server = lwM2MBootstrapService.getLhBootstrapServer(); + var securedEndpoint = (CoapEndpoint) ReflectionTestUtils.getField(server, "securedEndpoint"); + assertThat(securedEndpoint).isNotNull(); + + var config = (DtlsConnectorConfig) ReflectionTestUtils.getField(securedEndpoint.getConnector(), "config"); + assertThat(config).isNotNull(); + assertThat(config.getConnectionIdGenerator()).isNotNull(); + assertThat((Integer) ReflectionTestUtils.getField(config.getConnectionIdGenerator(), "connectionIdLength")) + .isEqualTo(CONNECTION_ID_LENGTH); + } + + @Test + public void getLHServer_creates_no_ConnectionIdGenerator_when_connection_id_length_is_null(){ + when(serverConfig.getDtlsConnectionIdLength()).thenReturn(null); + var lwM2MBootstrapService = createLwM2MBootstrapService(); + + var server = lwM2MBootstrapService.getLhBootstrapServer(); + var securedEndpoint = (CoapEndpoint) ReflectionTestUtils.getField(server, "securedEndpoint"); + assertThat(securedEndpoint).isNotNull(); + + var config = (DtlsConnectorConfig) ReflectionTestUtils.getField(securedEndpoint.getConnector(), "config"); + assertThat(config).isNotNull(); + assertThat(config.getConnectionIdGenerator()).isNull(); + } + + private LwM2MTransportBootstrapService createLwM2MBootstrapService() { + setDefaultConfigVariables(); + return new LwM2MTransportBootstrapService(serverConfig, bootstrapConfig, lwM2MBootstrapSecurityStore, + lwM2MInMemoryBootstrapConfigStore, transportService, certificateVerifier); + } + + private void setDefaultConfigVariables(){ + when(bootstrapConfig.getPort()).thenReturn(5683); + when(bootstrapConfig.getSecurePort()).thenReturn(5684); + when(serverConfig.isRecommendedCiphers()).thenReturn(false); + when(serverConfig.getDtlsRetransmissionTimeout()).thenReturn(9000); + } + + +} \ No newline at end of file diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfigTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfigTest.java new file mode 100644 index 0000000000..7e657dd932 --- /dev/null +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfigTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.config; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootContextLoader; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.thingsboard.server.common.transport.config.ssl.SslCredentialsConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(SpringExtension.class) +@EnableConfigurationProperties(value = LwM2MTransportServerConfig.class) +@ContextConfiguration(classes = {LwM2MTransportServerConfig.class}, loader = SpringBootContextLoader.class) +@TestPropertySource(properties = { + "transport.sessions.report_timeout=10", + "transport.lwm2m.security.recommended_ciphers=true", + "transport.lwm2m.security.recommended_supported_groups=true", + "transport.lwm2m.downlink_pool_size=10", + "transport.lwm2m.uplink_pool_size=10", + "transport.lwm2m.ota_pool_size=10", + "transport.lwm2m.clean_period_in_sec=2", + "transport.lwm2m.dtls.connection_id_length=" + +}) +class LwM2MTransportServerConfigTest { + + @MockBean(name = "lwm2mServerCredentials") + private SslCredentialsConfig credentialsConfig; + + @MockBean(name = "lwm2mTrustCredentials") + private SslCredentialsConfig trustCredentialsConfig; + + @Autowired + private LwM2MTransportServerConfig serverConfig; + + @Test + void getDtlsConnectionIdLength_return_null_is_property_is_empty() { + // note: transport.lwm2m.dtls.connect_id_length is set in TestPropertySource + assertThat(serverConfig.getDtlsConnectionIdLength()).isNull(); + } +} \ No newline at end of file diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportServiceTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportServiceTest.java new file mode 100644 index 0000000000..92f60ebb8e --- /dev/null +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportServiceTest.java @@ -0,0 +1,109 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.server; + +import org.eclipse.californium.core.network.CoapEndpoint; +import org.eclipse.californium.scandium.config.DtlsConnectorConfig; +import org.eclipse.leshan.server.californium.LeshanServer; +import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.util.ReflectionTestUtils; +import org.thingsboard.server.cache.ota.OtaPackageDataCache; +import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MAuthorizer; +import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MDtlsCertificateVerifier; +import org.thingsboard.server.transport.lwm2m.server.store.TbSecurityStore; +import org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mUplinkMsgHandler; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.when; + +@ExtendWith(MockitoExtension.class) +public class DefaultLwM2mTransportServiceTest { + + @Mock + private LwM2mTransportContext context; + + @Mock + private LwM2MTransportServerConfig config; + @Mock + private OtaPackageDataCache otaPackageDataCache; + @Mock + private LwM2mUplinkMsgHandler handler; + @Mock + private CaliforniumRegistrationStore registrationStore; + @Mock + private TbSecurityStore securityStore; + @Mock + private TbLwM2MDtlsCertificateVerifier certificateVerifier; + @Mock + private TbLwM2MAuthorizer authorizer; + @Mock + private LwM2mVersionedModelProvider modelProvider; + + + @Test + public void getLHServer_creates_ConnectionIdGenerator_when_connection_id_length_not_null(){ + final Integer CONNECTION_ID_LENGTH = 6; + when(config.getDtlsConnectionIdLength()).thenReturn(CONNECTION_ID_LENGTH); + var lwm2mService = createLwM2MService(); + + LeshanServer server = ReflectionTestUtils.invokeMethod(lwm2mService, "getLhServer"); + + assertThat(server).isNotNull(); + var securedEndpoint = (CoapEndpoint) ReflectionTestUtils.getField(server, "securedEndpoint"); + assertThat(securedEndpoint).isNotNull(); + + var config = (DtlsConnectorConfig) ReflectionTestUtils.getField(securedEndpoint.getConnector(), "config"); + assertThat(config).isNotNull(); + assertThat(config.getConnectionIdGenerator()).isNotNull(); + assertThat((Integer) ReflectionTestUtils.getField(config.getConnectionIdGenerator(), "connectionIdLength")) + .isEqualTo(CONNECTION_ID_LENGTH); + } + + @Test + public void getLHServer_creates_no_ConnectionIdGenerator_when_connection_id_length_is_null(){ + when(config.getDtlsConnectionIdLength()).thenReturn(null); + var lwm2mService = createLwM2MService(); + + LeshanServer server = ReflectionTestUtils.invokeMethod(lwm2mService, "getLhServer"); + + assertThat(server).isNotNull(); + var securedEndpoint = (CoapEndpoint) ReflectionTestUtils.getField(server, "securedEndpoint"); + assertThat(securedEndpoint).isNotNull(); + var config = (DtlsConnectorConfig) ReflectionTestUtils.getField(securedEndpoint.getConnector(), "config"); + assertThat(config).isNotNull(); + assertThat(config.getConnectionIdGenerator()).isNull(); + } + + private DefaultLwM2mTransportService createLwM2MService() { + setDefaultConfigVariables(); + return new DefaultLwM2mTransportService(context, config, otaPackageDataCache, handler, registrationStore, + securityStore, certificateVerifier, authorizer, modelProvider); + } + + private void setDefaultConfigVariables(){ + when(config.getPort()).thenReturn(5683); + when(config.getSecurePort()).thenReturn(5684); + when(config.isRecommendedCiphers()).thenReturn(false); + when(config.getDtlsRetransmissionTimeout()).thenReturn(9000); + } + + +} \ No newline at end of file diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index 688392d264..b6dc7248ab 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -155,6 +155,8 @@ transport: dtls: # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}" + # "" disables connection id support, 0 enables support but not for incoming traffic, any value greater than 0 set the connection id size in bytes + connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:6}" server: # LwM2M Server ID id: "${LWM2M_SERVER_ID:123}" From 3c460d79c3e6a468131c35b6738a597cfbb538df Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Fri, 26 Jan 2024 13:37:08 +0200 Subject: [PATCH 173/397] Refactor core consumer tests: add test for device state message forwarding, split all-in-one tests into more but simpler test cases --- .../queue/DefaultTbCoreConsumerService.java | 2 +- .../DefaultTbCoreConsumerServiceTest.java | 350 +++++++++++++++--- 2 files changed, 290 insertions(+), 62 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index 41f7cc012c..5c93351d0a 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -652,7 +652,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService Date: Fri, 26 Jan 2024 16:15:11 +0200 Subject: [PATCH 174/397] Add optimization using separate service which routes activity actions to device state service directly, when running in monolith. Refactor rule node tests --- .../server/actors/ActorSystemContext.java | 5 + .../actors/ruleChain/DefaultTbContext.java | 6 + ...ClusteredRuleEngineDeviceStateManager.java | 110 +++++++++++++ .../LocalRuleEngineDeviceStateManager.java | 85 ++++++++++ ...teredRuleEngineDeviceStateManagerTest.java | 150 ++++++++++++++++++ ...LocalRuleEngineDeviceStateManagerTest.java | 131 +++++++++++++++ .../thingsboard/server/common/msg/TbMsg.java | 2 +- .../api/RuleEngineDeviceStateManager.java | 32 ++++ .../rule/engine/api/TbContext.java | 2 + .../rule/engine/action/TbDeviceStateNode.java | 106 +++---------- .../engine/action/TbDeviceStateNodeTest.java | 108 ++++++------- 11 files changed, 592 insertions(+), 145 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/service/state/ClusteredRuleEngineDeviceStateManager.java create mode 100644 application/src/main/java/org/thingsboard/server/service/state/LocalRuleEngineDeviceStateManager.java create mode 100644 application/src/test/java/org/thingsboard/server/service/state/ClusteredRuleEngineDeviceStateManagerTest.java create mode 100644 application/src/test/java/org/thingsboard/server/service/state/LocalRuleEngineDeviceStateManagerTest.java create mode 100644 rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineDeviceStateManager.java diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index 31d9e477ac..6082c3f9f0 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -31,6 +31,7 @@ import org.springframework.stereotype.Component; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.rule.engine.api.NotificationCenter; +import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; import org.thingsboard.rule.engine.api.SmsService; import org.thingsboard.rule.engine.api.slack.SlackService; import org.thingsboard.rule.engine.api.sms.SmsSenderFactory; @@ -203,6 +204,10 @@ public class ActorSystemContext { @Getter private DeviceCredentialsService deviceCredentialsService; + @Autowired + @Getter + private RuleEngineDeviceStateManager deviceStateManager; + @Autowired @Getter private TbTenantProfileCache tenantProfileCache; diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java index 1e7d5d24e9..b97201005c 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java @@ -28,6 +28,7 @@ import org.thingsboard.rule.engine.api.RuleEngineAlarmService; import org.thingsboard.rule.engine.api.RuleEngineApiUsageStateService; import org.thingsboard.rule.engine.api.RuleEngineAssetProfileCache; import org.thingsboard.rule.engine.api.RuleEngineDeviceProfileCache; +import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; import org.thingsboard.rule.engine.api.RuleEngineRpcService; import org.thingsboard.rule.engine.api.RuleEngineTelemetryService; import org.thingsboard.rule.engine.api.ScriptEngine; @@ -683,6 +684,11 @@ class DefaultTbContext implements TbContext { return mainCtx.getDeviceCredentialsService(); } + @Override + public RuleEngineDeviceStateManager getDeviceStateManager() { + return mainCtx.getDeviceStateManager(); + } + @Override public TbClusterService getClusterService() { return mainCtx.getClusterService(); diff --git a/application/src/main/java/org/thingsboard/server/service/state/ClusteredRuleEngineDeviceStateManager.java b/application/src/main/java/org/thingsboard/server/service/state/ClusteredRuleEngineDeviceStateManager.java new file mode 100644 index 0000000000..2a73d3f544 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/state/ClusteredRuleEngineDeviceStateManager.java @@ -0,0 +1,110 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.state; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; +import org.thingsboard.server.cluster.TbClusterService; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.msg.queue.TbCallback; +import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.queue.common.SimpleTbQueueCallback; +import org.thingsboard.server.queue.util.TbRuleEngineComponent; + +@Slf4j +@Service +@TbRuleEngineComponent +@RequiredArgsConstructor +public class ClusteredRuleEngineDeviceStateManager implements RuleEngineDeviceStateManager { + + private final TbClusterService clusterService; + + @Override + public void onDeviceConnect(TenantId tenantId, DeviceId deviceId, long connectTime, TbCallback callback) { + var tenantUuid = tenantId.getId(); + var deviceUuid = deviceId.getId(); + var deviceConnectMsg = TransportProtos.DeviceConnectProto.newBuilder() + .setTenantIdMSB(tenantUuid.getMostSignificantBits()) + .setTenantIdLSB(tenantUuid.getLeastSignificantBits()) + .setDeviceIdMSB(deviceUuid.getMostSignificantBits()) + .setDeviceIdLSB(deviceUuid.getLeastSignificantBits()) + .setLastConnectTime(connectTime) + .build(); + var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() + .setDeviceConnectMsg(deviceConnectMsg) + .build(); + log.trace("[{}][{}] Sending device connect message to core. Connect time: [{}].", tenantUuid, deviceUuid, connectTime); + clusterService.pushMsgToCore(tenantId, deviceId, toCoreMsg, new SimpleTbQueueCallback(__ -> callback.onSuccess(), callback::onFailure)); + } + + @Override + public void onDeviceActivity(TenantId tenantId, DeviceId deviceId, long activityTime, TbCallback callback) { + var tenantUuid = tenantId.getId(); + var deviceUuid = deviceId.getId(); + var deviceActivityMsg = TransportProtos.DeviceActivityProto.newBuilder() + .setTenantIdMSB(tenantUuid.getMostSignificantBits()) + .setTenantIdLSB(tenantUuid.getLeastSignificantBits()) + .setDeviceIdMSB(deviceUuid.getMostSignificantBits()) + .setDeviceIdLSB(deviceUuid.getLeastSignificantBits()) + .setLastActivityTime(activityTime) + .build(); + var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() + .setDeviceActivityMsg(deviceActivityMsg) + .build(); + log.trace("[{}][{}] Sending device activity message to core. Activity time: [{}].", tenantUuid, deviceUuid, activityTime); + clusterService.pushMsgToCore(tenantId, deviceId, toCoreMsg, new SimpleTbQueueCallback(__ -> callback.onSuccess(), callback::onFailure)); + } + + @Override + public void onDeviceDisconnect(TenantId tenantId, DeviceId deviceId, long disconnectTime, TbCallback callback) { + var tenantUuid = tenantId.getId(); + var deviceUuid = deviceId.getId(); + var deviceDisconnectMsg = TransportProtos.DeviceDisconnectProto.newBuilder() + .setTenantIdMSB(tenantUuid.getMostSignificantBits()) + .setTenantIdLSB(tenantUuid.getLeastSignificantBits()) + .setDeviceIdMSB(deviceUuid.getMostSignificantBits()) + .setDeviceIdLSB(deviceUuid.getLeastSignificantBits()) + .setLastDisconnectTime(disconnectTime) + .build(); + var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() + .setDeviceDisconnectMsg(deviceDisconnectMsg) + .build(); + log.trace("[{}][{}] Sending device disconnect message to core. Disconnect time: [{}].", tenantUuid, deviceUuid, disconnectTime); + clusterService.pushMsgToCore(tenantId, deviceId, toCoreMsg, new SimpleTbQueueCallback(__ -> callback.onSuccess(), callback::onFailure)); + } + + @Override + public void onDeviceInactivity(TenantId tenantId, DeviceId deviceId, long inactivityTime, TbCallback callback) { + var tenantUuid = tenantId.getId(); + var deviceUuid = deviceId.getId(); + var deviceInactivityMsg = TransportProtos.DeviceInactivityProto.newBuilder() + .setTenantIdMSB(tenantUuid.getMostSignificantBits()) + .setTenantIdLSB(tenantUuid.getLeastSignificantBits()) + .setDeviceIdMSB(deviceUuid.getMostSignificantBits()) + .setDeviceIdLSB(deviceUuid.getLeastSignificantBits()) + .setLastInactivityTime(inactivityTime) + .build(); + var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() + .setDeviceInactivityMsg(deviceInactivityMsg) + .build(); + log.trace("[{}][{}] Sending device inactivity message to core. Inactivity time: [{}].", tenantUuid, deviceUuid, inactivityTime); + clusterService.pushMsgToCore(tenantId, deviceId, toCoreMsg, new SimpleTbQueueCallback(__ -> callback.onSuccess(), callback::onFailure)); + } + +} diff --git a/application/src/main/java/org/thingsboard/server/service/state/LocalRuleEngineDeviceStateManager.java b/application/src/main/java/org/thingsboard/server/service/state/LocalRuleEngineDeviceStateManager.java new file mode 100644 index 0000000000..180aea9ecb --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/state/LocalRuleEngineDeviceStateManager.java @@ -0,0 +1,85 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.state; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.msg.queue.TbCallback; +import org.thingsboard.server.queue.util.TbCoreComponent; + +@Slf4j +@Service +@Primary +@TbCoreComponent +@RequiredArgsConstructor +public class LocalRuleEngineDeviceStateManager implements RuleEngineDeviceStateManager { + + private final DeviceStateService deviceStateService; + + @Override + public void onDeviceConnect(TenantId tenantId, DeviceId deviceId, long connectTime, TbCallback callback) { + try { + deviceStateService.onDeviceConnect(tenantId, deviceId, connectTime); + } catch (Exception e) { + log.error("[{}][{}] Failed to process device connect event. Connect time: [{}].", tenantId.getId(), deviceId.getId(), connectTime, e); + callback.onFailure(e); + return; + } + callback.onSuccess(); + } + + @Override + public void onDeviceActivity(TenantId tenantId, DeviceId deviceId, long activityTime, TbCallback callback) { + try { + deviceStateService.onDeviceActivity(tenantId, deviceId, activityTime); + } catch (Exception e) { + log.error("[{}][{}] Failed to process device activity event. Activity time: [{}].", tenantId.getId(), deviceId.getId(), activityTime, e); + callback.onFailure(e); + return; + } + callback.onSuccess(); + } + + @Override + public void onDeviceDisconnect(TenantId tenantId, DeviceId deviceId, long disconnectTime, TbCallback callback) { + try { + deviceStateService.onDeviceDisconnect(tenantId, deviceId, disconnectTime); + } catch (Exception e) { + log.error("[{}][{}] Failed to process device disconnect event. Disconnect time: [{}].", tenantId.getId(), deviceId.getId(), disconnectTime, e); + callback.onFailure(e); + return; + } + callback.onSuccess(); + } + + @Override + public void onDeviceInactivity(TenantId tenantId, DeviceId deviceId, long inactivityTime, TbCallback callback) { + try { + deviceStateService.onDeviceInactivity(tenantId, deviceId, inactivityTime); + } catch (Exception e) { + log.error("[{}][{}] Failed to process device inactivity event. Inactivity time: [{}].", tenantId.getId(), deviceId.getId(), inactivityTime, e); + callback.onFailure(e); + return; + } + callback.onSuccess(); + } + +} diff --git a/application/src/test/java/org/thingsboard/server/service/state/ClusteredRuleEngineDeviceStateManagerTest.java b/application/src/test/java/org/thingsboard/server/service/state/ClusteredRuleEngineDeviceStateManagerTest.java new file mode 100644 index 0000000000..e972b49347 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/service/state/ClusteredRuleEngineDeviceStateManagerTest.java @@ -0,0 +1,150 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.state; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.thingsboard.server.cluster.TbClusterService; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.msg.queue.TbCallback; +import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.queue.TbQueueCallback; +import org.thingsboard.server.queue.TbQueueMsgMetadata; + +import java.util.UUID; +import java.util.stream.Stream; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.then; + +@ExtendWith(MockitoExtension.class) +public class ClusteredRuleEngineDeviceStateManagerTest { + + @Mock + private static TbClusterService tbClusterServiceMock; + @Mock + private static TbCallback tbCallbackMock; + @Mock + private static TbQueueMsgMetadata metadataMock; + @Captor + private static ArgumentCaptor queueCallbackCaptor; + private static ClusteredRuleEngineDeviceStateManager deviceStateManager; + + private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("57ab2e6c-bc4c-11ee-a506-0242ac120002")); + private static final DeviceId DEVICE_ID = DeviceId.fromString("74a9053e-bc4c-11ee-a506-0242ac120002"); + private static final long EVENT_TS = System.currentTimeMillis(); + + @BeforeEach + public void setup() { + deviceStateManager = new ClusteredRuleEngineDeviceStateManager(tbClusterServiceMock); + } + + @ParameterizedTest + @MethodSource + public void givenProcessingSuccess_whenOnDeviceAction_thenCallsDeviceStateServiceAndOnSuccessCallback(Runnable onDeviceAction, Runnable actionVerification) { + // WHEN + onDeviceAction.run(); + + // THEN + actionVerification.run(); + + TbQueueCallback callback = queueCallbackCaptor.getValue(); + callback.onSuccess(metadataMock); + then(tbCallbackMock).should().onSuccess(); + + var runtimeException = new RuntimeException("Something bad happened!"); + callback.onFailure(runtimeException); + then(tbCallbackMock).should().onFailure(runtimeException); + } + + private static Stream givenProcessingSuccess_whenOnDeviceAction_thenCallsDeviceStateServiceAndOnSuccessCallback() { + return Stream.of( + Arguments.of( + (Runnable) () -> deviceStateManager.onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> { + var deviceConnectMsg = TransportProtos.DeviceConnectProto.newBuilder() + .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) + .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) + .setDeviceIdMSB(DEVICE_ID.getId().getMostSignificantBits()) + .setDeviceIdLSB(DEVICE_ID.getId().getLeastSignificantBits()) + .setLastConnectTime(EVENT_TS) + .build(); + var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() + .setDeviceConnectMsg(deviceConnectMsg) + .build(); + then(tbClusterServiceMock).should().pushMsgToCore(eq(TENANT_ID), eq(DEVICE_ID), eq(toCoreMsg), queueCallbackCaptor.capture()); + } + ), + Arguments.of( + (Runnable) () -> deviceStateManager.onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> { + var deviceActivityMsg = TransportProtos.DeviceActivityProto.newBuilder() + .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) + .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) + .setDeviceIdMSB(DEVICE_ID.getId().getMostSignificantBits()) + .setDeviceIdLSB(DEVICE_ID.getId().getLeastSignificantBits()) + .setLastActivityTime(EVENT_TS) + .build(); + var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() + .setDeviceActivityMsg(deviceActivityMsg) + .build(); + then(tbClusterServiceMock).should().pushMsgToCore(eq(TENANT_ID), eq(DEVICE_ID), eq(toCoreMsg), queueCallbackCaptor.capture()); + } + ), + Arguments.of( + (Runnable) () -> deviceStateManager.onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> { + var deviceDisconnectMsg = TransportProtos.DeviceDisconnectProto.newBuilder() + .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) + .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) + .setDeviceIdMSB(DEVICE_ID.getId().getMostSignificantBits()) + .setDeviceIdLSB(DEVICE_ID.getId().getLeastSignificantBits()) + .setLastDisconnectTime(EVENT_TS) + .build(); + var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() + .setDeviceDisconnectMsg(deviceDisconnectMsg) + .build(); + then(tbClusterServiceMock).should().pushMsgToCore(eq(TENANT_ID), eq(DEVICE_ID), eq(toCoreMsg), queueCallbackCaptor.capture()); + } + ), + Arguments.of( + (Runnable) () -> deviceStateManager.onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> { + var deviceInactivityMsg = TransportProtos.DeviceInactivityProto.newBuilder() + .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) + .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) + .setDeviceIdMSB(DEVICE_ID.getId().getMostSignificantBits()) + .setDeviceIdLSB(DEVICE_ID.getId().getLeastSignificantBits()) + .setLastInactivityTime(EVENT_TS) + .build(); + var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() + .setDeviceInactivityMsg(deviceInactivityMsg) + .build(); + then(tbClusterServiceMock).should().pushMsgToCore(eq(TENANT_ID), eq(DEVICE_ID), eq(toCoreMsg), queueCallbackCaptor.capture()); + } + ) + ); + } + +} diff --git a/application/src/test/java/org/thingsboard/server/service/state/LocalRuleEngineDeviceStateManagerTest.java b/application/src/test/java/org/thingsboard/server/service/state/LocalRuleEngineDeviceStateManagerTest.java new file mode 100644 index 0000000000..db4d71f995 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/service/state/LocalRuleEngineDeviceStateManagerTest.java @@ -0,0 +1,131 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.state; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.msg.queue.TbCallback; + +import java.util.UUID; +import java.util.stream.Stream; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; + +@ExtendWith(MockitoExtension.class) +public class LocalRuleEngineDeviceStateManagerTest { + + @Mock + private static DeviceStateService deviceStateServiceMock; + @Mock + private static TbCallback tbCallbackMock; + private static LocalRuleEngineDeviceStateManager deviceStateManager; + + private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.fromString("57ab2e6c-bc4c-11ee-a506-0242ac120002")); + private static final DeviceId DEVICE_ID = DeviceId.fromString("74a9053e-bc4c-11ee-a506-0242ac120002"); + private static final long EVENT_TS = System.currentTimeMillis(); + private static final RuntimeException RUNTIME_EXCEPTION = new RuntimeException("Something bad happened!"); + + @BeforeEach + public void setup() { + deviceStateManager = new LocalRuleEngineDeviceStateManager(deviceStateServiceMock); + } + + @ParameterizedTest + @MethodSource + public void givenProcessingSuccess_whenOnDeviceAction_thenCallsDeviceStateServiceAndOnSuccessCallback(Runnable onDeviceAction, Runnable actionVerification) { + // WHEN + onDeviceAction.run(); + + // THEN + actionVerification.run(); + then(tbCallbackMock).should().onSuccess(); + then(tbCallbackMock).should(never()).onFailure(any()); + } + + private static Stream givenProcessingSuccess_whenOnDeviceAction_thenCallsDeviceStateServiceAndOnSuccessCallback() { + return Stream.of( + Arguments.of( + (Runnable) () -> deviceStateManager.onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> then(deviceStateServiceMock).should().onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS) + ), + Arguments.of( + (Runnable) () -> deviceStateManager.onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> then(deviceStateServiceMock).should().onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS) + ), + Arguments.of( + (Runnable) () -> deviceStateManager.onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> then(deviceStateServiceMock).should().onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS) + ), + Arguments.of( + (Runnable) () -> deviceStateManager.onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> then(deviceStateServiceMock).should().onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS) + ) + ); + } + + @ParameterizedTest + @MethodSource + public void givenProcessingFailure_whenOnDeviceAction_thenCallsDeviceStateServiceAndOnFailureCallback( + Runnable exceptionThrowSetup, Runnable onDeviceAction, Runnable actionVerification + ) { + // GIVEN + exceptionThrowSetup.run(); + + // WHEN + onDeviceAction.run(); + + // THEN + actionVerification.run(); + then(tbCallbackMock).should(never()).onSuccess(); + then(tbCallbackMock).should().onFailure(RUNTIME_EXCEPTION); + } + + private static Stream givenProcessingFailure_whenOnDeviceAction_thenCallsDeviceStateServiceAndOnFailureCallback() { + return Stream.of( + Arguments.of( + (Runnable) () -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS), + (Runnable) () -> deviceStateManager.onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> then(deviceStateServiceMock).should().onDeviceConnect(TENANT_ID, DEVICE_ID, EVENT_TS) + ), + Arguments.of( + (Runnable) () -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS), + (Runnable) () -> deviceStateManager.onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> then(deviceStateServiceMock).should().onDeviceActivity(TENANT_ID, DEVICE_ID, EVENT_TS) + ), + Arguments.of( + (Runnable) () -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS), + (Runnable) () -> deviceStateManager.onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> then(deviceStateServiceMock).should().onDeviceDisconnect(TENANT_ID, DEVICE_ID, EVENT_TS) + ), + Arguments.of( + (Runnable) () -> doThrow(RUNTIME_EXCEPTION).when(deviceStateServiceMock).onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS), + (Runnable) () -> deviceStateManager.onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS, tbCallbackMock), + (Runnable) () -> then(deviceStateServiceMock).should().onDeviceInactivity(TENANT_ID, DEVICE_ID, EVENT_TS) + ) + ); + } + +} diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java index 1e06d75b15..d81393cf25 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java @@ -335,7 +335,7 @@ public final class TbMsg implements Serializable { this.originator = originator; if (customerId == null || customerId.isNullUid()) { if (originator != null && originator.getEntityType() == EntityType.CUSTOMER) { - this.customerId = (CustomerId) originator; + this.customerId = new CustomerId(originator.getId()); } else { this.customerId = null; } diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineDeviceStateManager.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineDeviceStateManager.java new file mode 100644 index 0000000000..82c2916408 --- /dev/null +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineDeviceStateManager.java @@ -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. + */ +package org.thingsboard.rule.engine.api; + +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.msg.queue.TbCallback; + +public interface RuleEngineDeviceStateManager { + + void onDeviceConnect(TenantId tenantId, DeviceId deviceId, long connectTime, TbCallback callback); + + void onDeviceActivity(TenantId tenantId, DeviceId deviceId, long activityTime, TbCallback callback); + + void onDeviceDisconnect(TenantId tenantId, DeviceId deviceId, long disconnectTime, TbCallback callback); + + void onDeviceInactivity(TenantId tenantId, DeviceId deviceId, long inactivityTime, TbCallback callback); + +} diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java index 59f5b128a7..32fb81ccd9 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java @@ -280,6 +280,8 @@ public interface TbContext { DeviceCredentialsService getDeviceCredentialsService(); + RuleEngineDeviceStateManager getDeviceStateManager(); + TbClusterService getClusterService(); DashboardService getDashboardService(); 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 f28a3e4467..7168ad3c0f 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 @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.action; import lombok.extern.slf4j.Slf4j; +import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; @@ -23,12 +24,12 @@ import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; -import org.thingsboard.server.gen.transport.TransportProtos; -import org.thingsboard.server.queue.TbQueueCallback; -import org.thingsboard.server.queue.common.SimpleTbQueueCallback; +import org.thingsboard.server.common.msg.queue.TbCallback; import java.util.EnumSet; import java.util.Set; @@ -61,7 +62,7 @@ import java.util.Set; ) public class TbDeviceStateNode implements TbNode { - static final Set SUPPORTED_EVENTS = EnumSet.of( + private static final Set SUPPORTED_EVENTS = EnumSet.of( TbMsgType.CONNECT_EVENT, TbMsgType.ACTIVITY_EVENT, TbMsgType.DISCONNECT_EVENT, TbMsgType.INACTIVITY_EVENT ); @@ -85,98 +86,41 @@ public class TbDeviceStateNode implements TbNode { ctx.tellSuccess(msg); return; } + + TenantId tenantId = ctx.getTenantId(); + DeviceId deviceId = (DeviceId) msg.getOriginator(); + RuleEngineDeviceStateManager deviceStateManager = ctx.getDeviceStateManager(); + switch (event) { case CONNECT_EVENT: - sendDeviceConnectMsg(ctx, msg); + deviceStateManager.onDeviceConnect(tenantId, deviceId, msg.getMetaDataTs(), getMsgEnqueuedCallback(ctx, msg)); break; case ACTIVITY_EVENT: - sendDeviceActivityMsg(ctx, msg); + deviceStateManager.onDeviceActivity(tenantId, deviceId, msg.getMetaDataTs(), getMsgEnqueuedCallback(ctx, msg)); break; case DISCONNECT_EVENT: - sendDeviceDisconnectMsg(ctx, msg); + deviceStateManager.onDeviceDisconnect(tenantId, deviceId, msg.getMetaDataTs(), getMsgEnqueuedCallback(ctx, msg)); break; case INACTIVITY_EVENT: - sendDeviceInactivityMsg(ctx, msg); + deviceStateManager.onDeviceInactivity(tenantId, deviceId, msg.getMetaDataTs(), getMsgEnqueuedCallback(ctx, msg)); break; default: ctx.tellFailure(msg, new IllegalStateException("Configured event [" + event + "] is not supported!")); } } - private void sendDeviceConnectMsg(TbContext ctx, TbMsg msg) { - var tenantUuid = ctx.getTenantId().getId(); - var deviceUuid = msg.getOriginator().getId(); - var deviceConnectMsg = TransportProtos.DeviceConnectProto.newBuilder() - .setTenantIdMSB(tenantUuid.getMostSignificantBits()) - .setTenantIdLSB(tenantUuid.getLeastSignificantBits()) - .setDeviceIdMSB(deviceUuid.getMostSignificantBits()) - .setDeviceIdLSB(deviceUuid.getLeastSignificantBits()) - .setLastConnectTime(msg.getMetaDataTs()) - .build(); - var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() - .setDeviceConnectMsg(deviceConnectMsg) - .build(); - ctx.getClusterService().pushMsgToCore( - ctx.getTenantId(), msg.getOriginator(), toCoreMsg, getMsgEnqueuedCallback(ctx, msg) - ); - } - - private void sendDeviceActivityMsg(TbContext ctx, TbMsg msg) { - var tenantUuid = ctx.getTenantId().getId(); - var deviceUuid = msg.getOriginator().getId(); - var deviceActivityMsg = TransportProtos.DeviceActivityProto.newBuilder() - .setTenantIdMSB(tenantUuid.getMostSignificantBits()) - .setTenantIdLSB(tenantUuid.getLeastSignificantBits()) - .setDeviceIdMSB(deviceUuid.getMostSignificantBits()) - .setDeviceIdLSB(deviceUuid.getLeastSignificantBits()) - .setLastActivityTime(msg.getMetaDataTs()) - .build(); - var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() - .setDeviceActivityMsg(deviceActivityMsg) - .build(); - ctx.getClusterService().pushMsgToCore( - ctx.getTenantId(), msg.getOriginator(), toCoreMsg, getMsgEnqueuedCallback(ctx, msg) - ); - } - - private void sendDeviceDisconnectMsg(TbContext ctx, TbMsg msg) { - var tenantUuid = ctx.getTenantId().getId(); - var deviceUuid = msg.getOriginator().getId(); - var deviceDisconnectMsg = TransportProtos.DeviceDisconnectProto.newBuilder() - .setTenantIdMSB(tenantUuid.getMostSignificantBits()) - .setTenantIdLSB(tenantUuid.getLeastSignificantBits()) - .setDeviceIdMSB(deviceUuid.getMostSignificantBits()) - .setDeviceIdLSB(deviceUuid.getLeastSignificantBits()) - .setLastDisconnectTime(msg.getMetaDataTs()) - .build(); - var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() - .setDeviceDisconnectMsg(deviceDisconnectMsg) - .build(); - ctx.getClusterService().pushMsgToCore( - ctx.getTenantId(), msg.getOriginator(), toCoreMsg, getMsgEnqueuedCallback(ctx, msg) - ); - } - - private void sendDeviceInactivityMsg(TbContext ctx, TbMsg msg) { - var tenantUuid = ctx.getTenantId().getId(); - var deviceUuid = msg.getOriginator().getId(); - var deviceInactivityMsg = TransportProtos.DeviceInactivityProto.newBuilder() - .setTenantIdMSB(tenantUuid.getMostSignificantBits()) - .setTenantIdLSB(tenantUuid.getLeastSignificantBits()) - .setDeviceIdMSB(deviceUuid.getMostSignificantBits()) - .setDeviceIdLSB(deviceUuid.getLeastSignificantBits()) - .setLastInactivityTime(msg.getMetaDataTs()) - .build(); - var toCoreMsg = TransportProtos.ToCoreMsg.newBuilder() - .setDeviceInactivityMsg(deviceInactivityMsg) - .build(); - ctx.getClusterService().pushMsgToCore( - ctx.getTenantId(), msg.getOriginator(), toCoreMsg, getMsgEnqueuedCallback(ctx, msg) - ); - } + private TbCallback getMsgEnqueuedCallback(TbContext ctx, TbMsg msg) { + return new TbCallback() { + @Override + public void onSuccess() { + ctx.tellSuccess(msg); + } - private TbQueueCallback getMsgEnqueuedCallback(TbContext ctx, TbMsg msg) { - return new SimpleTbQueueCallback(metadata -> ctx.tellSuccess(msg), t -> ctx.tellFailure(msg, t)); + @Override + public void onFailure(Throwable t) { + ctx.tellFailure(msg, t); + } + }; } } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java index 988d8911a4..e967ec49b5 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java @@ -20,28 +20,28 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; -import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.id.AssetId; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; -import org.thingsboard.server.common.data.id.RuleNodeId; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; -import org.thingsboard.server.gen.transport.TransportProtos; -import org.thingsboard.server.queue.TbQueueCallback; +import org.thingsboard.server.common.msg.queue.TbCallback; -import java.util.Set; import java.util.UUID; import java.util.stream.Stream; @@ -51,7 +51,6 @@ import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.times; @ExtendWith(MockitoExtension.class) public class TbDeviceStateNodeTest { @@ -59,7 +58,9 @@ public class TbDeviceStateNodeTest { @Mock private TbContext ctxMock; @Mock - private TbClusterService tbClusterServiceMock; + private static RuleEngineDeviceStateManager deviceStateManagerMock; + @Captor + private static ArgumentCaptor callbackCaptor; private TbDeviceStateNode node; private TbDeviceStateNodeConfiguration config; @@ -94,10 +95,6 @@ public class TbDeviceStateNodeTest { @Test public void givenDefaultConfiguration_whenInvoked_thenCorrectValuesAreSet() { assertThat(config.getEvent()).isEqualTo(TbMsgType.ACTIVITY_EVENT); - assertThat(TbDeviceStateNode.SUPPORTED_EVENTS).isEqualTo(Set.of( - TbMsgType.CONNECT_EVENT, TbMsgType.ACTIVITY_EVENT, - TbMsgType.DISCONNECT_EVENT, TbMsgType.INACTIVITY_EVENT - )); } @Test @@ -113,10 +110,14 @@ public class TbDeviceStateNodeTest { .matches(e -> ((TbNodeException) e).isUnrecoverable()); } - @Test - public void givenUnsupportedEventInConfig_whenInit_thenThrowsUnrecoverableTbNodeException() { + @ParameterizedTest + @EnumSource( + value = TbMsgType.class, + names = {"CONNECT_EVENT", "ACTIVITY_EVENT", "DISCONNECT_EVENT", "INACTIVITY_EVENT"}, + mode = EnumSource.Mode.EXCLUDE + ) + public void givenUnsupportedEventInConfig_whenInit_thenThrowsUnrecoverableTbNodeException(TbMsgType unsupportedEvent) { // GIVEN - var unsupportedEvent = TbMsgType.TO_SERVER_RPC_REQUEST; config.setEvent(unsupportedEvent); var nodeConfig = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); @@ -127,11 +128,23 @@ public class TbDeviceStateNodeTest { .matches(e -> ((TbNodeException) e).isUnrecoverable()); } - @Test - public void givenNonDeviceOriginator_whenOnMsg_thenTellsSuccessAndNoActivityActionsTriggered() { + @ParameterizedTest + @EnumSource(value = EntityType.class, names = "DEVICE", mode = EnumSource.Mode.EXCLUDE) + public void givenNonDeviceOriginator_whenOnMsg_thenTellsSuccessAndNoActivityActionsTriggered(EntityType unsupportedType) { // GIVEN - var asset = new AssetId(UUID.randomUUID()); - var msg = TbMsg.newMsg(TbMsgType.ENTITY_CREATED, asset, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); + var nonDeviceOriginator = new EntityId() { + + @Override + public UUID getId() { + return UUID.randomUUID(); + } + + @Override + public EntityType getEntityType() { + return unsupportedType; + } + }; + var msg = TbMsg.newMsg(TbMsgType.ENTITY_CREATED, nonDeviceOriginator, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT); // WHEN node.onMsg(ctxMock, msg); @@ -142,10 +155,10 @@ public class TbDeviceStateNodeTest { } @ParameterizedTest - @MethodSource("provideSupportedEventsAndExpectedMessages") - public void givenSupportedEvent_whenOnMsg_thenCorrectMsgIsSent(TbMsgType event, TransportProtos.ToCoreMsg expectedToCoreMsg) { + @MethodSource + public void givenInactivityEventAndDeviceOriginator_whenOnMsg_thenOnDeviceInactivityIsCalledWithCorrectCallback(TbMsgType supportedEventType, Runnable actionVerification) { // GIVEN - config.setEvent(event); + config.setEvent(supportedEventType); var nodeConfig = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); try { node.init(ctxMock, nodeConfig); @@ -153,65 +166,34 @@ public class TbDeviceStateNodeTest { fail("Node failed to initialize!", e); } given(ctxMock.getTenantId()).willReturn(TENANT_ID); - given(ctxMock.getClusterService()).willReturn(tbClusterServiceMock); + given(ctxMock.getDeviceStateManager()).willReturn(deviceStateManagerMock); // WHEN node.onMsg(ctxMock, msg); // THEN - var protoCaptor = ArgumentCaptor.forClass(TransportProtos.ToCoreMsg.class); - var callbackCaptor = ArgumentCaptor.forClass(TbQueueCallback.class); - then(tbClusterServiceMock).should().pushMsgToCore(eq(TENANT_ID), eq(DEVICE_ID), protoCaptor.capture(), callbackCaptor.capture()); + actionVerification.run(); - TbQueueCallback actualCallback = callbackCaptor.getValue(); + TbCallback actualCallback = callbackCaptor.getValue(); - actualCallback.onSuccess(null); + actualCallback.onSuccess(); then(ctxMock).should().tellSuccess(msg); var throwable = new Throwable(); actualCallback.onFailure(throwable); then(ctxMock).should().tellFailure(msg, throwable); - assertThat(expectedToCoreMsg).isEqualTo(protoCaptor.getValue()); - then(tbClusterServiceMock).shouldHaveNoMoreInteractions(); + then(deviceStateManagerMock).shouldHaveNoMoreInteractions(); then(ctxMock).shouldHaveNoMoreInteractions(); } - private static Stream provideSupportedEventsAndExpectedMessages() { + private static Stream givenInactivityEventAndDeviceOriginator_whenOnMsg_thenOnDeviceInactivityIsCalledWithCorrectCallback() { return Stream.of( - Arguments.of(TbMsgType.CONNECT_EVENT, TransportProtos.ToCoreMsg.newBuilder().setDeviceConnectMsg( - TransportProtos.DeviceConnectProto.newBuilder() - .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) - .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) - .setDeviceIdMSB(DEVICE_ID.getId().getMostSignificantBits()) - .setDeviceIdLSB(DEVICE_ID.getId().getLeastSignificantBits()) - .setLastConnectTime(METADATA_TS) - .build()).build()), - Arguments.of(TbMsgType.ACTIVITY_EVENT, TransportProtos.ToCoreMsg.newBuilder().setDeviceActivityMsg( - TransportProtos.DeviceActivityProto.newBuilder() - .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) - .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) - .setDeviceIdMSB(DEVICE_ID.getId().getMostSignificantBits()) - .setDeviceIdLSB(DEVICE_ID.getId().getLeastSignificantBits()) - .setLastActivityTime(METADATA_TS) - .build()).build()), - Arguments.of(TbMsgType.DISCONNECT_EVENT, TransportProtos.ToCoreMsg.newBuilder().setDeviceDisconnectMsg( - TransportProtos.DeviceDisconnectProto.newBuilder() - .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) - .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) - .setDeviceIdMSB(DEVICE_ID.getId().getMostSignificantBits()) - .setDeviceIdLSB(DEVICE_ID.getId().getLeastSignificantBits()) - .setLastDisconnectTime(METADATA_TS) - .build()).build()), - Arguments.of(TbMsgType.INACTIVITY_EVENT, TransportProtos.ToCoreMsg.newBuilder().setDeviceInactivityMsg( - TransportProtos.DeviceInactivityProto.newBuilder() - .setTenantIdMSB(TENANT_ID.getId().getMostSignificantBits()) - .setTenantIdLSB(TENANT_ID.getId().getLeastSignificantBits()) - .setDeviceIdMSB(DEVICE_ID.getId().getMostSignificantBits()) - .setDeviceIdLSB(DEVICE_ID.getId().getLeastSignificantBits()) - .setLastInactivityTime(METADATA_TS) - .build()).build()) + Arguments.of(TbMsgType.CONNECT_EVENT, (Runnable) () -> then(deviceStateManagerMock).should().onDeviceConnect(eq(TENANT_ID), eq(DEVICE_ID), eq(METADATA_TS), callbackCaptor.capture())), + Arguments.of(TbMsgType.ACTIVITY_EVENT, (Runnable) () -> then(deviceStateManagerMock).should().onDeviceActivity(eq(TENANT_ID), eq(DEVICE_ID), eq(METADATA_TS), callbackCaptor.capture())), + Arguments.of(TbMsgType.DISCONNECT_EVENT, (Runnable) () -> then(deviceStateManagerMock).should().onDeviceDisconnect(eq(TENANT_ID), eq(DEVICE_ID), eq(METADATA_TS), callbackCaptor.capture())), + Arguments.of(TbMsgType.INACTIVITY_EVENT, (Runnable) () -> then(deviceStateManagerMock).should().onDeviceInactivity(eq(TENANT_ID), eq(DEVICE_ID), eq(METADATA_TS), callbackCaptor.capture())) ); } From 27b5fe52a40202efe191c2847b428e786b6f563b Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Fri, 26 Jan 2024 15:44:08 +0100 Subject: [PATCH 175/397] fixed stack overflow error --- .../service/sync/vc/DefaultEntitiesVersionControlService.java | 2 +- .../service/telemetry/DefaultTelemetrySubscriptionService.java | 1 - .../server/dao/attributes/CachedAttributesService.java | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java index 7c7f6e7709..18969e4e0b 100644 --- a/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java +++ b/application/src/main/java/org/thingsboard/server/service/sync/vc/DefaultEntitiesVersionControlService.java @@ -283,7 +283,7 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont return cachePut(ctx.getRequestId(), result); } catch (LoadEntityException e) { return cachePut(ctx.getRequestId(), onError(e.getExternalId(), e.getCause())); - } catch (Exception e) { + } catch (Throwable e) { log.info("[{}] Failed to process request [{}] due to: ", ctx.getTenantId(), request, e); return cachePut(ctx.getRequestId(), VersionLoadResult.error(EntityLoadError.runtimeError(e))); } diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java index 2431b344f2..b19fde2983 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java @@ -237,7 +237,6 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer } @Override - public void saveAndNotify(TenantId tenantId, EntityId entityId, String scope, List attributes, FutureCallback callback) { saveAndNotify(tenantId, entityId, scope, attributes, true, callback); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java b/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java index 6760ea8ac7..2757bbecbd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java @@ -256,7 +256,7 @@ public class CachedAttributesService implements AttributesService { @Override public ListenableFuture> save(TenantId tenantId, EntityId entityId, String scope, List attributes) { - return save(tenantId, entityId, scope, attributes); + return save(tenantId, entityId, AttributeScope.valueOf(scope), attributes); } @Override From b1b0e44c7fda9118cea95b6715430cf1641943bc Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Fri, 26 Jan 2024 17:04:49 +0200 Subject: [PATCH 176/397] Add executor to process activity events in a dedicated thread not to avoid blocking main consumer --- .../queue/DefaultTbCoreConsumerService.java | 64 +++++++++++-------- .../DefaultTbCoreConsumerServiceTest.java | 23 +++++++ 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index 5c93351d0a..9942476c01 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -15,6 +15,9 @@ */ package org.thingsboard.server.service.queue; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -148,6 +151,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService future = deviceActivityEventsExecutor.submit(() -> stateService.onDeviceConnect(tenantId, deviceId, deviceConnectMsg.getLastConnectTime())); + DonAsynchron.withCallback(future, + __ -> callback.onSuccess(), + t -> { + log.warn("[{}] Failed to process device connect message for device [{}]", tenantId.getId(), deviceId.getId(), t); + callback.onFailure(t); + }); } void forwardToStateService(TransportProtos.DeviceActivityProto deviceActivityMsg, TbCallback callback) { @@ -680,13 +688,13 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService future = deviceActivityEventsExecutor.submit(() -> stateService.onDeviceActivity(tenantId, deviceId, deviceActivityMsg.getLastActivityTime())); + DonAsynchron.withCallback(future, + __ -> callback.onSuccess(), + t -> { + log.warn("[{}] Failed to process device activity message for device [{}]", tenantId.getId(), deviceId.getId(), t); + callback.onFailure(new RuntimeException("Failed to update device activity for device [" + deviceId.getId() + "]!", t)); + }); } void forwardToStateService(TransportProtos.DeviceDisconnectProto deviceDisconnectMsg, TbCallback callback) { @@ -695,13 +703,13 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService future = deviceActivityEventsExecutor.submit(() -> stateService.onDeviceDisconnect(tenantId, deviceId, deviceDisconnectMsg.getLastDisconnectTime())); + DonAsynchron.withCallback(future, + __ -> callback.onSuccess(), + t -> { + log.warn("[{}] Failed to process device disconnect message for device [{}]", tenantId.getId(), deviceId.getId(), t); + callback.onFailure(t); + }); } void forwardToStateService(TransportProtos.DeviceInactivityProto deviceInactivityMsg, TbCallback callback) { @@ -710,13 +718,13 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService future = deviceActivityEventsExecutor.submit(() -> stateService.onDeviceInactivity(tenantId, deviceId, deviceInactivityMsg.getLastInactivityTime())); + DonAsynchron.withCallback(future, + __ -> callback.onSuccess(), + t -> { + log.warn("[{}] Failed to process device inactivity message for device [{}]", tenantId.getId(), deviceId.getId(), t); + callback.onFailure(t); + }); } private void forwardToNotificationSchedulerService(TransportProtos.NotificationSchedulerServiceMsg msg, TbCallback callback) { diff --git a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerServiceTest.java b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerServiceTest.java index 19166f75d2..621d4c5a91 100644 --- a/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerServiceTest.java @@ -15,6 +15,9 @@ */ package org.thingsboard.server.service.queue; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -29,6 +32,7 @@ import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.service.state.DeviceStateService; import java.util.UUID; +import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -52,12 +56,31 @@ public class DefaultTbCoreConsumerServiceTest { private final DeviceId deviceId = new DeviceId(UUID.randomUUID()); private final long time = System.currentTimeMillis(); + private ListeningExecutorService executor; + @Mock private DefaultTbCoreConsumerService defaultTbCoreConsumerServiceMock; @BeforeEach public void setup() { + executor = MoreExecutors.newDirectExecutorService(); ReflectionTestUtils.setField(defaultTbCoreConsumerServiceMock, "stateService", stateServiceMock); + ReflectionTestUtils.setField(defaultTbCoreConsumerServiceMock, "deviceActivityEventsExecutor", executor); + } + + @AfterEach + public void cleanup() { + if (executor != null) { + executor.shutdown(); + try { + if (!executor.awaitTermination(10L, TimeUnit.SECONDS)) { + executor.shutdownNow(); + } + } catch (InterruptedException e) { + executor.shutdownNow(); + Thread.currentThread().interrupt(); + } + } } @Test From b19d7f1406775e0afd511e46ecd08a4594907064 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Fri, 26 Jan 2024 17:08:50 +0200 Subject: [PATCH 177/397] Clarify information about event ts in node description --- .../rule/engine/action/TbDeviceStateNode.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) 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 7168ad3c0f..d8cc81679c 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 @@ -39,12 +39,9 @@ import java.util.Set; type = ComponentType.ACTION, name = "device state", nodeDescription = "Triggers device connectivity events", - nodeDetails = "If incoming message originator is a device," + - " registers configured event for that device in the Device State Service," + - " which sends appropriate message to the Rule Engine." + - " If metadata ts property is present, it will be used as event timestamp." + - " Incoming message is forwarded using the Success chain," + - " unless an unexpected error occurs during message processing" + + nodeDetails = "If incoming message originator is a device, registers configured event for that device in the Device State Service, which sends appropriate message to the Rule Engine." + + " If metadata ts property is present, it will be used as event timestamp. Otherwise, the message timestamp will be used." + + " Incoming message is forwarded using the Success chain, unless an unexpected error occurs during message processing" + " then incoming message is forwarded using the Failure chain." + "
" + "Supported device connectivity events are:" + @@ -54,8 +51,7 @@ import java.util.Set; "
  • Activity event
  • " + "
  • Inactivity event
  • " + "" + - "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.", + "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, uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeDeviceStateConfig" From 7650387db4fd0098346976b9de33dff03d70ce9f Mon Sep 17 00:00:00 2001 From: Ivan Raznatovskyi Date: Mon, 29 Jan 2024 11:16:26 +0200 Subject: [PATCH 178/397] Added initial connector value --- .../widget/lib/gateway/gateway-connectors.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index 85b3fa9acd..b7ac9d65b5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -382,6 +382,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie if ($event) { $event.stopPropagation(); } + this.initialConnector = attribute.value; const title = `Delete connector ${attribute.key}?`; const content = `All connector data will be deleted.`; this.dialogService.confirm(title, content, 'Cancel', 'Delete').subscribe(result => { From d1a9c4432acb5398497a01b148e01018933fa0b3 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Tue, 30 Jan 2024 11:56:10 +0200 Subject: [PATCH 179/397] Add rate limit of at most one event per second per originator in node --- .../server/common/data/msg/TbMsgType.java | 1 + .../rule/engine/action/TbDeviceStateNode.java | 86 +++++++- .../engine/action/TbDeviceStateNodeTest.java | 187 +++++++++++++++--- 3 files changed, 239 insertions(+), 35 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/msg/TbMsgType.java b/common/data/src/main/java/org/thingsboard/server/common/data/msg/TbMsgType.java index 763f245a09..c7eeef158d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/msg/TbMsgType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/msg/TbMsgType.java @@ -76,6 +76,7 @@ public enum TbMsgType { DEDUPLICATION_TIMEOUT_SELF_MSG(null, true), DELAY_TIMEOUT_SELF_MSG(null, true), MSG_COUNT_SELF_MSG(null, true), + DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG(null, true), // Custom or N/A type: NA; 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 d8cc81679c..a74df13f20 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 @@ -15,6 +15,7 @@ */ package org.thingsboard.rule.engine.action; +import com.google.common.base.Stopwatch; import lombok.extern.slf4j.Slf4j; import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; import org.thingsboard.rule.engine.api.RuleNode; @@ -29,10 +30,15 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.TbCallback; +import java.time.Duration; import java.util.EnumSet; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; @Slf4j @RuleNode( @@ -61,7 +67,11 @@ public class TbDeviceStateNode implements TbNode { private static final Set SUPPORTED_EVENTS = EnumSet.of( TbMsgType.CONNECT_EVENT, TbMsgType.ACTIVITY_EVENT, TbMsgType.DISCONNECT_EVENT, TbMsgType.INACTIVITY_EVENT ); + private static final Duration ONE_SECOND = Duration.ofSeconds(1L); + private static final Duration ENTRY_EXPIRATION_TIME = Duration.ofDays(1L); + private Stopwatch stopwatch; + private ConcurrentMap lastActivityEventTimestamps; private TbMsgType event; @Override @@ -74,31 +84,82 @@ public class TbDeviceStateNode implements TbNode { throw new TbNodeException("Unsupported event: " + event, true); } this.event = event; + lastActivityEventTimestamps = new ConcurrentHashMap<>(); + stopwatch = Stopwatch.createStarted(); + scheduleCleanupMsg(ctx); } @Override public void onMsg(TbContext ctx, TbMsg msg) { + if (msg.isTypeOf(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG)) { + removeStaleEntries(); + scheduleCleanupMsg(ctx); + ctx.ack(msg); + return; + } + if (!EntityType.DEVICE.equals(msg.getOriginator().getEntityType())) { ctx.tellSuccess(msg); return; } + DeviceId originator = new DeviceId(msg.getOriginator().getId()); + + lastActivityEventTimestamps.compute(originator, (__, lastEventTs) -> { + Duration now = stopwatch.elapsed(); + + if (lastEventTs == null) { + sendEvent(ctx, originator, msg); + return now; + } + + Duration elapsedSinceLastEventSent = now.minus(lastEventTs); + if (elapsedSinceLastEventSent.compareTo(ONE_SECOND) < 0) { + ctx.tellSuccess(msg); + return lastEventTs; + } + + sendEvent(ctx, originator, msg); + + return now; + }); + } + + private void scheduleCleanupMsg(TbContext ctx) { + TbMsg cleanupMsg = ctx.newMsg( + null, TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG, ctx.getSelfId(), TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING + ); + ctx.tellSelf(cleanupMsg, Duration.ofHours(1L).toMillis()); + } + + private void removeStaleEntries() { + lastActivityEventTimestamps.entrySet().removeIf(entry -> { + Duration now = stopwatch.elapsed(); + Duration lastEventTs = entry.getValue(); + Duration elapsedSinceLastEventSent = now.minus(lastEventTs); + return elapsedSinceLastEventSent.compareTo(ENTRY_EXPIRATION_TIME) > 0; + }); + } + + private void sendEvent(TbContext ctx, DeviceId originator, TbMsg msg) { TenantId tenantId = ctx.getTenantId(); - DeviceId deviceId = (DeviceId) msg.getOriginator(); + long eventTs = msg.getMetaDataTs(); + RuleEngineDeviceStateManager deviceStateManager = ctx.getDeviceStateManager(); + TbCallback callback = getMsgEnqueuedCallback(ctx, msg); switch (event) { case CONNECT_EVENT: - deviceStateManager.onDeviceConnect(tenantId, deviceId, msg.getMetaDataTs(), getMsgEnqueuedCallback(ctx, msg)); + deviceStateManager.onDeviceConnect(tenantId, originator, eventTs, callback); break; case ACTIVITY_EVENT: - deviceStateManager.onDeviceActivity(tenantId, deviceId, msg.getMetaDataTs(), getMsgEnqueuedCallback(ctx, msg)); + deviceStateManager.onDeviceActivity(tenantId, originator, eventTs, callback); break; case DISCONNECT_EVENT: - deviceStateManager.onDeviceDisconnect(tenantId, deviceId, msg.getMetaDataTs(), getMsgEnqueuedCallback(ctx, msg)); + deviceStateManager.onDeviceDisconnect(tenantId, originator, eventTs, callback); break; case INACTIVITY_EVENT: - deviceStateManager.onDeviceInactivity(tenantId, deviceId, msg.getMetaDataTs(), getMsgEnqueuedCallback(ctx, msg)); + deviceStateManager.onDeviceInactivity(tenantId, originator, eventTs, callback); break; default: ctx.tellFailure(msg, new IllegalStateException("Configured event [" + event + "] is not supported!")); @@ -119,4 +180,19 @@ public class TbDeviceStateNode implements TbNode { }; } + @Override + public void onPartitionChangeMsg(TbContext ctx, PartitionChangeMsg msg) { + lastActivityEventTimestamps.entrySet().removeIf(entry -> !ctx.isLocalEntity(entry.getKey())); + } + + @Override + public void destroy() { + if (lastActivityEventTimestamps != null) { + lastActivityEventTimestamps.clear(); + lastActivityEventTimestamps = null; + } + stopwatch = null; + event = null; + } + } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java index e967ec49b5..af72927e3c 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java @@ -15,6 +15,8 @@ */ package org.thingsboard.rule.engine.action; +import com.google.common.base.Stopwatch; +import com.google.common.base.Ticker; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -26,29 +28,35 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.util.ReflectionTestUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; -import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgMetaData; +import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; +import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TbCallback; +import java.time.Duration; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; @@ -62,28 +70,33 @@ public class TbDeviceStateNodeTest { @Captor private static ArgumentCaptor callbackCaptor; private TbDeviceStateNode node; + private RuleNodeId nodeId; private TbDeviceStateNodeConfiguration config; private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final DeviceId DEVICE_ID = new DeviceId(UUID.randomUUID()); private static final long METADATA_TS = System.currentTimeMillis(); + private TbMsg cleanupMsg; private TbMsg msg; + private long nowNanos; + private final Ticker controlledTicker = new Ticker() { + @Override + public long read() { + return nowNanos; + } + }; @BeforeEach public void setup() { - var device = new Device(); - device.setTenantId(TENANT_ID); - device.setId(DEVICE_ID); - device.setName("My humidity sensor"); - device.setType("Humidity sensor"); - device.setDeviceProfileId(new DeviceProfileId(UUID.randomUUID())); var metaData = new TbMsgMetaData(); - metaData.putValue("deviceName", device.getName()); - metaData.putValue("deviceType", device.getType()); + metaData.putValue("deviceName", "My humidity sensor"); + metaData.putValue("deviceType", "Humidity sensor"); metaData.putValue("ts", String.valueOf(METADATA_TS)); var data = JacksonUtil.newObjectNode(); data.put("humidity", 58.3); - msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, device.getId(), metaData, JacksonUtil.toString(data)); + msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, JacksonUtil.toString(data)); + nodeId = new RuleNodeId(UUID.randomUUID()); + cleanupMsg = TbMsg.newMsg(null, TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG, nodeId, TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING); } @BeforeEach @@ -99,17 +112,121 @@ public class TbDeviceStateNodeTest { @Test public void givenNullEventInConfig_whenInit_thenThrowsUnrecoverableTbNodeException() { - // GIVEN - config.setEvent(null); - var nodeConfig = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); - - // WHEN-THEN - assertThatThrownBy(() -> node.init(ctxMock, nodeConfig)) + // GIVEN-WHEN-THEN + assertThatThrownBy(() -> initNode(null)) .isInstanceOf(TbNodeException.class) .hasMessage("Event cannot be null!") .matches(e -> ((TbNodeException) e).isUnrecoverable()); } + @Test + public void givenValidConfig_whenInit_thenSchedulesCleanupMsg() { + // GIVEN + given(ctxMock.getSelfId()).willReturn(nodeId); + given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); + + // WHEN + try { + initNode(TbMsgType.ACTIVITY_EVENT); + } catch (Exception e) { + fail("Node failed to initialize."); + } + + // THEN + verifyCleanupMsgSent(); + } + + @Test + public void givenCleanupMsg_whenOnMsg_thenCleansStaleEntries() { + // GIVEN + given(ctxMock.getSelfId()).willReturn(nodeId); + given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); + + ConcurrentMap lastActivityEventTimestamps = new ConcurrentHashMap<>(); + ReflectionTestUtils.setField(node, "lastActivityEventTimestamps", lastActivityEventTimestamps); + + Stopwatch stopwatch = Stopwatch.createStarted(controlledTicker); + ReflectionTestUtils.setField(node, "stopwatch", stopwatch); + + // WHEN + Duration expirationTime = Duration.ofDays(1L); + + DeviceId staleId = DEVICE_ID; + Duration staleTs = Duration.ofHours(4L); + lastActivityEventTimestamps.put(staleId, staleTs); + + DeviceId goodId = new DeviceId(UUID.randomUUID()); + Duration goodTs = staleTs.plus(expirationTime); + lastActivityEventTimestamps.put(goodId, goodTs); + + nowNanos = staleTs.toNanos() + expirationTime.toNanos() + 1; + node.onMsg(ctxMock, cleanupMsg); + + // THEN + assertThat(lastActivityEventTimestamps) + .containsKey(goodId) + .doesNotContainKey(staleId) + .size().isOne(); + + verifyCleanupMsgSent(); + then(ctxMock).should().ack(cleanupMsg); + then(ctxMock).shouldHaveNoMoreInteractions(); + } + + @Test + public void givenMsgArrivedTooFast_whenOnMsg_thenRateLimitsThisMsg() { + // GIVEN + ConcurrentMap lastActivityEventTimestamps = new ConcurrentHashMap<>(); + ReflectionTestUtils.setField(node, "lastActivityEventTimestamps", lastActivityEventTimestamps); + + Stopwatch stopwatch = Stopwatch.createStarted(controlledTicker); + ReflectionTestUtils.setField(node, "stopwatch", stopwatch); + + // WHEN + Duration firstEventTs = Duration.ofMillis(1000L); + lastActivityEventTimestamps.put(DEVICE_ID, firstEventTs); + + Duration tooFastEventTs = firstEventTs.plus(Duration.ofMillis(999L)); + nowNanos = tooFastEventTs.toNanos(); + node.onMsg(ctxMock, msg); + + // THEN + Duration actualEventTs = lastActivityEventTimestamps.get(DEVICE_ID); + assertThat(actualEventTs).isEqualTo(firstEventTs); + + then(ctxMock).should().tellSuccess(msg); + then(ctxMock).shouldHaveNoMoreInteractions(); + then(deviceStateManagerMock).shouldHaveNoInteractions(); + } + + @Test + public void givenHasNonLocalDevices_whenOnPartitionChange_thenRemovesEntriesForNonLocalDevices() { + // GIVEN + ConcurrentMap lastActivityEventTimestamps = new ConcurrentHashMap<>(); + ReflectionTestUtils.setField(node, "lastActivityEventTimestamps", lastActivityEventTimestamps); + + lastActivityEventTimestamps.put(DEVICE_ID, Duration.ofHours(24L)); + given(ctxMock.isLocalEntity(eq(DEVICE_ID))).willReturn(true); + + DeviceId nonLocalDeviceId1 = new DeviceId(UUID.randomUUID()); + lastActivityEventTimestamps.put(nonLocalDeviceId1, Duration.ofHours(30L)); + given(ctxMock.isLocalEntity(eq(nonLocalDeviceId1))).willReturn(false); + + DeviceId nonLocalDeviceId2 = new DeviceId(UUID.randomUUID()); + lastActivityEventTimestamps.put(nonLocalDeviceId2, Duration.ofHours(32L)); + given(ctxMock.isLocalEntity(eq(nonLocalDeviceId2))).willReturn(false); + + // WHEN + node.onPartitionChangeMsg(ctxMock, new PartitionChangeMsg(ServiceType.TB_RULE_ENGINE)); + + // THEN + assertThat(lastActivityEventTimestamps) + .containsKey(DEVICE_ID) + .doesNotContainKey(nonLocalDeviceId1) + .doesNotContainKey(nonLocalDeviceId2) + .size().isOne(); + } + @ParameterizedTest @EnumSource( value = TbMsgType.class, @@ -117,12 +234,8 @@ public class TbDeviceStateNodeTest { mode = EnumSource.Mode.EXCLUDE ) public void givenUnsupportedEventInConfig_whenInit_thenThrowsUnrecoverableTbNodeException(TbMsgType unsupportedEvent) { - // GIVEN - config.setEvent(unsupportedEvent); - var nodeConfig = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); - - // WHEN-THEN - assertThatThrownBy(() -> node.init(ctxMock, nodeConfig)) + // GIVEN-WHEN-THEN + assertThatThrownBy(() -> initNode(unsupportedEvent)) .isInstanceOf(TbNodeException.class) .hasMessage("Unsupported event: " + unsupportedEvent) .matches(e -> ((TbNodeException) e).isUnrecoverable()); @@ -156,17 +269,19 @@ public class TbDeviceStateNodeTest { @ParameterizedTest @MethodSource - public void givenInactivityEventAndDeviceOriginator_whenOnMsg_thenOnDeviceInactivityIsCalledWithCorrectCallback(TbMsgType supportedEventType, Runnable actionVerification) { + public void givenSupportedEventAndDeviceOriginator_whenOnMsg_thenCorrectEventIsSentWithCorrectCallback(TbMsgType supportedEventType, Runnable actionVerification) { // GIVEN - config.setEvent(supportedEventType); - var nodeConfig = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); + given(ctxMock.getSelfId()).willReturn(nodeId); + given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); + given(ctxMock.getTenantId()).willReturn(TENANT_ID); + given(ctxMock.getDeviceStateManager()).willReturn(deviceStateManagerMock); + try { - node.init(ctxMock, nodeConfig); + initNode(supportedEventType); } catch (TbNodeException e) { fail("Node failed to initialize!", e); } - given(ctxMock.getTenantId()).willReturn(TENANT_ID); - given(ctxMock.getDeviceStateManager()).willReturn(deviceStateManagerMock); + verifyCleanupMsgSent(); // WHEN node.onMsg(ctxMock, msg); @@ -188,7 +303,7 @@ public class TbDeviceStateNodeTest { then(ctxMock).shouldHaveNoMoreInteractions(); } - private static Stream givenInactivityEventAndDeviceOriginator_whenOnMsg_thenOnDeviceInactivityIsCalledWithCorrectCallback() { + private static Stream givenSupportedEventAndDeviceOriginator_whenOnMsg_thenCorrectEventIsSentWithCorrectCallback() { return Stream.of( Arguments.of(TbMsgType.CONNECT_EVENT, (Runnable) () -> then(deviceStateManagerMock).should().onDeviceConnect(eq(TENANT_ID), eq(DEVICE_ID), eq(METADATA_TS), callbackCaptor.capture())), Arguments.of(TbMsgType.ACTIVITY_EVENT, (Runnable) () -> then(deviceStateManagerMock).should().onDeviceActivity(eq(TENANT_ID), eq(DEVICE_ID), eq(METADATA_TS), callbackCaptor.capture())), @@ -197,4 +312,16 @@ public class TbDeviceStateNodeTest { ); } + private void initNode(TbMsgType event) throws TbNodeException { + config.setEvent(event); + var nodeConfig = new TbNodeConfiguration(JacksonUtil.valueToTree(config)); + node.init(ctxMock, nodeConfig); + } + + private void verifyCleanupMsgSent() { + then(ctxMock).should().getSelfId(); + then(ctxMock).should().newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING)); + then(ctxMock).should().tellSelf(eq(cleanupMsg), eq(Duration.ofHours(1L).toMillis())); + } + } From 2159430c1b50383a4463a8377bee3f6f8b6e9cb3 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Tue, 30 Jan 2024 12:22:37 +0200 Subject: [PATCH 180/397] Fix test for message types with null rule node connections --- .../org/thingsboard/server/common/data/msg/TbMsgTypeTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/data/src/test/java/org/thingsboard/server/common/data/msg/TbMsgTypeTest.java b/common/data/src/test/java/org/thingsboard/server/common/data/msg/TbMsgTypeTest.java index 9dc7110340..ebf717fb63 100644 --- a/common/data/src/test/java/org/thingsboard/server/common/data/msg/TbMsgTypeTest.java +++ b/common/data/src/test/java/org/thingsboard/server/common/data/msg/TbMsgTypeTest.java @@ -22,6 +22,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.thingsboard.server.common.data.msg.TbMsgType.ALARM; import static org.thingsboard.server.common.data.msg.TbMsgType.ALARM_DELETE; +import static org.thingsboard.server.common.data.msg.TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG; import static org.thingsboard.server.common.data.msg.TbMsgType.NA; import static org.thingsboard.server.common.data.msg.TbMsgType.DEDUPLICATION_TIMEOUT_SELF_MSG; import static org.thingsboard.server.common.data.msg.TbMsgType.DELAY_TIMEOUT_SELF_MSG; @@ -53,6 +54,7 @@ class TbMsgTypeTest { DEDUPLICATION_TIMEOUT_SELF_MSG, DELAY_TIMEOUT_SELF_MSG, MSG_COUNT_SELF_MSG, + DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG, NA ); From 89f7b8e17f051a0c471d24e88a6b78c34102f507 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 30 Jan 2024 15:49:17 +0200 Subject: [PATCH 181/397] updated env parameter description --- application/src/main/resources/thingsboard.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 936f30af60..a02ae3da3f 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -379,7 +379,11 @@ sql: # Enable/disable TTL (Time To Live) for timeseries records enabled: "${SQL_TTL_TS_ENABLED:true}" execution_interval_ms: "${SQL_TTL_TS_EXECUTION_INTERVAL:86400000}" # Number of milliseconds. The current value corresponds to one day - ts_key_value_ttl: "${SQL_TTL_TS_TS_KEY_VALUE_TTL:0}" # Number of seconds + # The parameter to specify system TTL(Time To Live) value for timeseries records. Value set in seconds. + # 0 - records are never expired. System TTL value can be overwritten for a particular Tenant, or parent Customer entity by setting the server-side + # attribute TTL to the corresponding Tenant or parent Customer entity. Please, note that the value should be set as long value, otherwise the TTL + # will be used from the higher level(Tenant or System) + ts_key_value_ttl: "${SQL_TTL_TS_TS_KEY_VALUE_TTL:0}" events: # Enable/disable TTL (Time To Live) for event records enabled: "${SQL_TTL_EVENTS_ENABLED:true}" From 41adbe1003f422979b5fa8485d19ab487b27b55c Mon Sep 17 00:00:00 2001 From: nick Date: Tue, 30 Jan 2024 16:37:14 +0200 Subject: [PATCH 182/397] coap: final version --- ...AbstractCoapAttributesIntegrationTest.java | 5 +- .../CoapAttributesUpdatesIntegrationTest.java | 5 ++ ...pAttributesUpdatesJsonIntegrationTest.java | 4 +- ...AttributesUpdatesProtoIntegrationTest.java | 5 +- .../client/CoapClientIntegrationTest.java | 3 ++ ...tractCoapServerSideRpcIntegrationTest.java | 18 +++++-- ...apServerSideRpcDefaultIntegrationTest.java | 3 ++ .../CoapServerSideRpcJsonIntegrationTest.java | 3 ++ ...CoapServerSideRpcProtoIntegrationTest.java | 3 ++ .../transport/coap/CoapTransportResource.java | 40 +++----------- .../coap/callback/CoapResponseCallback.java | 54 +++++++++++++++++++ ...ack.java => CoapResponseCodeCallback.java} | 4 +- .../coap/client/DefaultCoapClientContext.java | 29 +++++++--- pom.xml | 2 +- 14 files changed, 127 insertions(+), 51 deletions(-) create mode 100644 common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCallback.java rename common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/{CoapOkCallback.java => CoapResponseCodeCallback.java} (88%) diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java index 081e0ce1b2..e8766ea039 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java @@ -25,6 +25,7 @@ import org.awaitility.Awaitility; import org.eclipse.californium.core.CoapObserveRelation; import org.eclipse.californium.core.CoapResponse; import org.eclipse.californium.core.coap.CoAP; +import org.eclipse.californium.core.coap.CoAP.ResponseCode; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.DynamicProtoUtils; @@ -238,7 +239,7 @@ public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoap String awaitAlias = "await Json Test Subscribe To AttributesUpdates (client.getObserveRelation)"; await(awaitAlias) .atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .until(() -> CoAP.ResponseCode.CONTENT.equals(callbackCoap.getResponseCode()) && + .until(() -> ResponseCode.VALID.equals(callbackCoap.getResponseCode()) && callbackCoap.getObserve() != null && 0 == callbackCoap.getObserve().intValue()); if (emptyCurrentStateNotification) { @@ -285,7 +286,7 @@ public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoap CoapObserveRelation observeRelation = client.getObserveRelation(callbackCoap); await(awaitAlias) .atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .until(() -> CoAP.ResponseCode.CONTENT.equals(callbackCoap.getResponseCode()) && + .until(() -> ResponseCode.VALID.equals(callbackCoap.getResponseCode()) && callbackCoap.getObserve() != null && 0 == callbackCoap.getObserve().intValue()); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java index 9ac2d5fc11..a7de7eb571 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesIntegrationTest.java @@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.server.resources.Resource; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.coapserver.DefaultCoapServerService; @@ -59,11 +60,15 @@ public class CoapAttributesUpdatesIntegrationTest extends AbstractCoapAttributes processAfterTest(); } + + + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception { processJsonTestSubscribeToAttributesUpdates(false); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification() throws Exception { processJsonTestSubscribeToAttributesUpdates(true); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesJsonIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesJsonIntegrationTest.java index 3fa625796c..4755ba134d 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesJsonIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesJsonIntegrationTest.java @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.coap.attributes.updates; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.thingsboard.server.common.data.CoapDeviceType; import org.thingsboard.server.common.data.TransportPayloadType; @@ -44,11 +45,12 @@ public class CoapAttributesUpdatesJsonIntegrationTest extends AbstractCoapAttrib processAfterTest(); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception { processJsonTestSubscribeToAttributesUpdates(false); } - + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification() throws Exception { processJsonTestSubscribeToAttributesUpdates(true); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesProtoIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesProtoIntegrationTest.java index 1ddeabb56d..1c9589bba9 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesProtoIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/updates/CoapAttributesUpdatesProtoIntegrationTest.java @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.coap.attributes.updates; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.thingsboard.server.common.data.CoapDeviceType; import org.thingsboard.server.common.data.TransportPayloadType; @@ -43,12 +44,12 @@ public class CoapAttributesUpdatesProtoIntegrationTest extends AbstractCoapAttri public void afterTest() throws Exception { processAfterTest(); } - + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testSubscribeToAttributesUpdatesFromTheServer() throws Exception { processProtoTestSubscribeToAttributesUpdates(false); } - + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testSubscribeToAttributesUpdatesFromTheServerWithEmptyCurrentStateNotification() throws Exception { processProtoTestSubscribeToAttributesUpdates(true); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java index 5be03683f7..e7a7485ef5 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/client/CoapClientIntegrationTest.java @@ -26,6 +26,7 @@ import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.MediaTypeRegistry; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.id.DeviceId; @@ -82,6 +83,7 @@ public class CoapClientIntegrationTest extends AbstractCoapIntegrationTest { processAfterTest(); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testConfirmableRequests() throws Exception { boolean confirmable = true; @@ -90,6 +92,7 @@ public class CoapClientIntegrationTest extends AbstractCoapIntegrationTest { processTestRequestAttributesValuesFromTheServer(confirmable); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testNonConfirmableRequests() throws Exception { boolean confirmable = false; diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java index 4a21495a96..384bfe4772 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/AbstractCoapServerSideRpcIntegrationTest.java @@ -82,15 +82,27 @@ public abstract class AbstractCoapServerSideRpcIntegrationTest extends AbstractC .until(() -> CoAP.ResponseCode.VALID.equals(callbackCoap.getResponseCode()) && callbackCoap.getObserve() != null && 0 == callbackCoap.getObserve()); validateCurrentStateNotification(callbackCoap); - int expectedObserveAfterRpcProcessed = callbackCoap.getObserve() + 1; - String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; + + int expectedObserveAfterRpcProcessed1 = callbackCoap.getObserve() + 1; + String setGpioRequest = "{\"method\":\"setGpio1\",\"params\":{\"pin\": \"21\",\"value\": 1}}"; String deviceId = savedDevice.getId().getId().toString(); String result = doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); awaitAlias = "await One Way Rpc setGpio(method, params, value)"; await(awaitAlias) .atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS) .until(() -> CoAP.ResponseCode.CONTENT.equals(callbackCoap.getResponseCode()) && - callbackCoap.getObserve() != null && expectedObserveAfterRpcProcessed == callbackCoap.getObserve()); + callbackCoap.getObserve() != null && expectedObserveAfterRpcProcessed1 == callbackCoap.getObserve()); + validateOneWayStateChangedNotification(callbackCoap, result); + + int expectedObserveAfterRpcProcessed2 = callbackCoap.getObserve() + 1; + setGpioRequest = "{\"method\":\"setGpio2\",\"params\":{\"pin\": \"22\",\"value\": 2}}"; + deviceId = savedDevice.getId().getId().toString(); + result = doPostAsync("/api/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isOk()); + awaitAlias = "await One Way Rpc setGpio(method, params, value)"; + await(awaitAlias) + .atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS) + .until(() -> CoAP.ResponseCode.CONTENT.equals(callbackCoap.getResponseCode()) && + callbackCoap.getObserve() != null && expectedObserveAfterRpcProcessed2 == callbackCoap.getObserve()); validateOneWayStateChangedNotification(callbackCoap, result); observeRelation.proactiveCancel(); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcDefaultIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcDefaultIntegrationTest.java index df1159b128..8f9d3379ef 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcDefaultIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcDefaultIntegrationTest.java @@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.service.security.AccessValidator; @@ -82,11 +83,13 @@ public class CoapServerSideRpcDefaultIntegrationTest extends AbstractCoapServerS Assert.assertEquals(AccessValidator.DEVICE_WITH_REQUESTED_ID_NOT_FOUND, result); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testServerCoapOneWayRpc() throws Exception { processOneWayRpcTest(false); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testServerCoapTwoWayRpc() throws Exception { processTwoWayRpcTest("{\"value1\":\"A\",\"value2\":\"B\"}", false); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcJsonIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcJsonIntegrationTest.java index 5c94e91b72..34d678b5b5 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcJsonIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcJsonIntegrationTest.java @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.coap.rpc; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.thingsboard.server.common.data.CoapDeviceType; import org.thingsboard.server.common.data.TransportPayloadType; @@ -43,11 +44,13 @@ public class CoapServerSideRpcJsonIntegrationTest extends AbstractCoapServerSide processAfterTest(); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testServerCoapOneWayRpc() throws Exception { processOneWayRpcTest(false); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testServerCoapTwoWayRpc() throws Exception { processTwoWayRpcTest("{\"value1\":\"A\",\"value2\":\"B\"}", false); diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcProtoIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcProtoIntegrationTest.java index 2f7d46a390..138f87e964 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcProtoIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/rpc/CoapServerSideRpcProtoIntegrationTest.java @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.coap.rpc; import lombok.extern.slf4j.Slf4j; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.thingsboard.server.common.data.CoapDeviceType; import org.thingsboard.server.common.data.TransportPayloadType; @@ -44,11 +45,13 @@ public class CoapServerSideRpcProtoIntegrationTest extends AbstractCoapServerSid processAfterTest(); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testServerCoapOneWayRpc() throws Exception { processOneWayRpcTest(true); } + @Ignore // Uncomment when Californium 3.11 is released with https://github.com/eclipse-californium/californium/pull/2215 @Test public void testServerCoapTwoWayRpc() throws Exception { processTwoWayRpcTest("{\"payload\":\"{\\\"value1\\\":\\\"A\\\",\\\"value2\\\":\\\"B\\\"}\"}", true); diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java index 2528c0992e..ebc52fc034 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportResource.java @@ -19,7 +19,6 @@ import com.google.gson.JsonParseException; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.Request; -import org.eclipse.californium.core.coap.Response; import org.eclipse.californium.core.network.Exchange; import org.eclipse.californium.core.observe.ObserveRelation; import org.eclipse.californium.core.server.resources.CoapExchange; @@ -27,6 +26,8 @@ import org.eclipse.californium.core.server.resources.Resource; import org.eclipse.californium.core.server.resources.ResourceObserver; import org.thingsboard.server.coapserver.CoapServerService; import org.thingsboard.server.coapserver.TbCoapDtlsSessionInfo; +import org.thingsboard.server.common.adaptor.AdaptorException; +import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceTransportType; @@ -35,13 +36,11 @@ import org.thingsboard.server.common.data.TransportPayloadType; import org.thingsboard.server.common.data.security.DeviceTokenCredentials; import org.thingsboard.server.common.msg.session.FeatureType; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.adaptor.AdaptorException; -import org.thingsboard.server.common.adaptor.JsonConverter; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.transport.coap.callback.CoapDeviceAuthCallback; import org.thingsboard.server.transport.coap.callback.CoapNoOpCallback; -import org.thingsboard.server.transport.coap.callback.CoapOkCallback; +import org.thingsboard.server.transport.coap.callback.CoapResponseCodeCallback; import org.thingsboard.server.transport.coap.callback.GetAttributesSyncSessionCallback; import org.thingsboard.server.transport.coap.callback.ToServerRpcSyncSessionCallback; import org.thingsboard.server.transport.coap.client.CoapClientContext; @@ -54,7 +53,6 @@ import java.util.Random; import java.util.UUID; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import static org.eclipse.californium.elements.DtlsEndpointContext.KEY_SESSION_ID; @@ -84,30 +82,6 @@ public class CoapTransportResource extends AbstractCoapTransportResource { ctx.getScheduler().scheduleAtFixedRate(clients::reportActivity, new Random().nextInt((int) sessionReportTimeout), sessionReportTimeout, TimeUnit.MILLISECONDS); } - /* - * Overwritten method from CoapResource to be able to manage our own observe notification counters. - */ - @Override - public void checkObserveRelation(Exchange exchange, Response response) { - String token = getTokenFromRequest(exchange.getRequest()); - final ObserveRelation relation = exchange.getRelation(); - if (relation == null || relation.isCanceled()) { - return; // because request did not try to establish a relation - } - if (response.getCode().isSuccess()) { - if (!relation.isEstablished()) { - relation.setEstablished(); - addObserveRelation(relation); - } - AtomicInteger state = clients.getNotificationCounterByToken(token); - if (state != null) { - response.getOptions().setObserve(state.getAndIncrement()); - } else { - response.getOptions().removeObserve(); - } - } // ObserveLayer takes care of the else case - } - @Override protected void processHandleGet(CoapExchange exchange) { Optional featureType = getFeatureType(exchange.advanced().getRequest()); @@ -278,7 +252,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { UUID sessionId = toSessionId(sessionInfo); transportService.process(sessionInfo, clientState.getAdaptor().convertToPostAttributes(sessionId, request, clientState.getConfiguration().getAttributesMsgDescriptor()), - new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); + new CoapResponseCodeCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); } private void handlePostTelemetryRequest(TbCoapClientState clientState, CoapExchange exchange, Request request) throws AdaptorException { @@ -286,7 +260,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { UUID sessionId = toSessionId(sessionInfo); transportService.process(sessionInfo, clientState.getAdaptor().convertToPostTelemetry(sessionId, request, clientState.getConfiguration().getTelemetryMsgDescriptor()), - new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); + new CoapResponseCodeCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); } private void handleClaimRequest(TbCoapClientState clientState, CoapExchange exchange, Request request) throws AdaptorException { @@ -294,7 +268,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { UUID sessionId = toSessionId(sessionInfo); transportService.process(sessionInfo, clientState.getAdaptor().convertToClaimDevice(sessionId, request, sessionInfo), - new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); + new CoapResponseCodeCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); } private void handleAttributeSubscribeRequest(TbCoapClientState clientState, CoapExchange exchange, Request request) { @@ -320,7 +294,7 @@ public class CoapTransportResource extends AbstractCoapTransportResource { UUID sessionId = toSessionId(session); transportService.process(session, clientState.getAdaptor().convertToDeviceRpcResponse(sessionId, request, clientState.getConfiguration().getRpcResponseMsgDescriptor()), - new CoapOkCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); + new CoapResponseCodeCallback(exchange, CoAP.ResponseCode.CREATED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); } private void handleRpcSubscribeRequest(TbCoapClientState clientState, CoapExchange exchange, Request request) { diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCallback.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCallback.java new file mode 100644 index 0000000000..c0baf62bc1 --- /dev/null +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCallback.java @@ -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. + */ +package org.thingsboard.server.transport.coap.callback; + +import org.eclipse.californium.core.coap.Response; +import org.eclipse.californium.core.server.resources.CoapExchange; +import org.thingsboard.server.common.transport.TransportServiceCallback; + +public class CoapResponseCallback implements TransportServiceCallback { + + protected final CoapExchange exchange; + protected final Response onSuccessResponse; + protected final Response onFailureResponse; + + public CoapResponseCallback(CoapExchange exchange, Response onSuccessResponse, Response onFailureResponse) { + this.exchange = exchange; + this.onSuccessResponse = onSuccessResponse; + this.onFailureResponse = onFailureResponse; + } + + /** + * @param msg + */ + @Override + public void onSuccess(Void msg) { + this.onSuccessResponse.setConfirmable(isConRequest()); + exchange.respond(this.onSuccessResponse); + } + + /** + * @param e + */ + @Override + public void onError(Throwable e) { + exchange.respond(onFailureResponse); + } + + protected boolean isConRequest() { + return exchange.advanced().getRequest().isConfirmable(); + } +} diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapOkCallback.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCodeCallback.java similarity index 88% rename from common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapOkCallback.java rename to common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCodeCallback.java index a45821d9d6..21293395ea 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapOkCallback.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/callback/CoapResponseCodeCallback.java @@ -20,13 +20,13 @@ import org.eclipse.californium.core.coap.Response; import org.eclipse.californium.core.server.resources.CoapExchange; import org.thingsboard.server.common.transport.TransportServiceCallback; -public class CoapOkCallback implements TransportServiceCallback { +public class CoapResponseCodeCallback implements TransportServiceCallback { protected final CoapExchange exchange; protected final CoAP.ResponseCode onSuccessResponse; protected final CoAP.ResponseCode onFailureResponse; - public CoapOkCallback(CoapExchange exchange, CoAP.ResponseCode onSuccessResponse, CoAP.ResponseCode onFailureResponse) { + public CoapResponseCodeCallback(CoapExchange exchange, CoAP.ResponseCode onSuccessResponse, CoAP.ResponseCode onFailureResponse) { this.exchange = exchange; this.onSuccessResponse = onSuccessResponse; this.onFailureResponse = onFailureResponse; diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java index 735ec1d524..2140e1966c 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.coap.client; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.coap.CoAP; +import org.eclipse.californium.core.coap.CoAP.ResponseCode; import org.eclipse.californium.core.coap.Response; import org.eclipse.californium.core.observe.ObserveRelation; import org.eclipse.californium.core.server.resources.CoapExchange; @@ -26,6 +27,7 @@ import org.springframework.context.annotation.Lazy; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import org.thingsboard.server.coapserver.CoapServerContext; +import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; @@ -45,7 +47,6 @@ import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.rpc.RpcStatus; import org.thingsboard.server.common.msg.session.FeatureType; -import org.thingsboard.server.transport.coap.CoapSessionMsgType; import org.thingsboard.server.common.transport.DeviceDeletedEvent; import org.thingsboard.server.common.transport.DeviceProfileUpdatedEvent; import org.thingsboard.server.common.transport.DeviceUpdatedEvent; @@ -53,18 +54,19 @@ import org.thingsboard.server.common.transport.SessionMsgListener; import org.thingsboard.server.common.transport.TransportDeviceProfileCache; import org.thingsboard.server.common.transport.TransportService; import org.thingsboard.server.common.transport.TransportServiceCallback; -import org.thingsboard.server.common.adaptor.AdaptorException; import org.thingsboard.server.common.transport.auth.SessionInfoCreator; import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.discovery.PartitionService; +import org.thingsboard.server.transport.coap.CoapSessionMsgType; import org.thingsboard.server.transport.coap.CoapTransportContext; import org.thingsboard.server.transport.coap.TbCoapMessageObserver; import org.thingsboard.server.transport.coap.TransportConfigurationContainer; import org.thingsboard.server.transport.coap.adaptors.CoapTransportAdaptor; import org.thingsboard.server.transport.coap.callback.AbstractSyncSessionCallback; import org.thingsboard.server.transport.coap.callback.CoapNoOpCallback; -import org.thingsboard.server.transport.coap.callback.CoapOkCallback; +import org.thingsboard.server.transport.coap.callback.CoapResponseCallback; +import org.thingsboard.server.transport.coap.callback.CoapResponseCodeCallback; import java.util.Optional; import java.util.UUID; @@ -329,9 +331,14 @@ public class DefaultCoapClientContext implements CoapClientContext { TransportProtos.GetAttributeRequestMsg.newBuilder().setOnlyShared(true).build(), new CoapNoOpCallback(exchange)); } else { + Response response = new Response(CoAP.ResponseCode.VALID); + if (state.getRpc() == null) { + state.setRpc(new TbCoapObservationState(exchange, token)); + } + response.getOptions().setObserve(state.getRpc().getObserveCounter().getAndIncrement()); transportService.process(state.getSession(), TransportProtos.SubscribeToRPCMsg.getDefaultInstance(), - new CoapOkCallback(exchange, CoAP.ResponseCode.VALID, CoAP.ResponseCode.INTERNAL_SERVER_ERROR) + new CoapResponseCallback(exchange, response, new Response(CoAP.ResponseCode.INTERNAL_SERVER_ERROR)) ); } } @@ -478,7 +485,13 @@ public class DefaultCoapClientContext implements CoapClientContext { TbCoapObservationState attrs = state.getAttrs(); if (attrs != null) { try { - Response response = state.getAdaptor().convertToPublish(msg); + Response resp = state.getAdaptor().convertToPublish(msg); + Response response = new Response(ResponseCode.VALID); + response.setPayload(resp.getPayload()); + if (state.getRpc() == null) { + state.setRpc(new TbCoapObservationState(attrs.getExchange(), attrs.getToken())); + } + response.getOptions().setObserve(state.getRpc().getObserveCounter().getAndIncrement()); respond(attrs.getExchange(), response, state.getContentFormat()); } catch (AdaptorException e) { log.trace("Failed to reply due to error", e); @@ -509,6 +522,7 @@ public class DefaultCoapClientContext implements CoapClientContext { boolean conRequest = AbstractSyncSessionCallback.isConRequest(state.getAttrs()); int requestId = getNextMsgId(); Response response = state.getAdaptor().convertToPublish(msg); + response.getOptions().setObserve(state.getRpc().getObserveCounter().getAndIncrement()); response.setConfirmable(conRequest); response.setMID(requestId); if (conRequest) { @@ -573,6 +587,7 @@ public class DefaultCoapClientContext implements CoapClientContext { int requestId = getNextMsgId(); try { Response response = state.getAdaptor().convertToPublish(msg, state.getConfiguration().getRpcRequestDynamicMessageBuilder()); + response.getOptions().setObserve(state.getRpc().getObserveCounter().getAndIncrement()); response.setConfirmable(conRequest); response.setMID(requestId); if (conRequest) { @@ -808,7 +823,7 @@ public class DefaultCoapClientContext implements CoapClientContext { state.setRpc(null); transportService.process(state.getSession(), TransportProtos.SubscribeToRPCMsg.newBuilder().setUnsubscribe(true).build(), - new CoapOkCallback(exchange, CoAP.ResponseCode.DELETED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); + new CoapResponseCodeCallback(exchange, CoAP.ResponseCode.DELETED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); if (state.getAttrs() == null) { closeAndCleanup(state); } @@ -822,7 +837,7 @@ public class DefaultCoapClientContext implements CoapClientContext { state.setAttrs(null); transportService.process(state.getSession(), TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().setUnsubscribe(true).build(), - new CoapOkCallback(exchange, CoAP.ResponseCode.DELETED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); + new CoapResponseCodeCallback(exchange, CoAP.ResponseCode.DELETED, CoAP.ResponseCode.INTERNAL_SERVER_ERROR)); if (state.getRpc() == null) { closeAndCleanup(state); } diff --git a/pom.xml b/pom.xml index 062a69746c..9079dc08e9 100755 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ 1.3.4 4.2.1 2.2.6 - 3.9.1 + 3.10.0 2.0.0-M14 2.9.0 2.3.30 From 4eda0d668c36cf763538a11958fe198ac023a92f Mon Sep 17 00:00:00 2001 From: nick Date: Tue, 30 Jan 2024 18:49:21 +0200 Subject: [PATCH 183/397] coap: msa tests --- .../server/msa/TestCoapClient.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClient.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClient.java index 67638ebefb..8fa6c44f4a 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClient.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClient.java @@ -22,6 +22,11 @@ import org.eclipse.californium.core.CoapResponse; import org.eclipse.californium.core.coap.CoAP; import org.eclipse.californium.core.coap.MediaTypeRegistry; import org.eclipse.californium.core.coap.Request; +import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.californium.elements.config.Configuration.ModuleDefinitionsProvider; +import org.eclipse.californium.elements.config.IntegerDefinition; +import org.eclipse.californium.elements.config.StringDefinition; +import org.eclipse.californium.elements.config.TcpConfig; import org.eclipse.californium.elements.exception.ConnectorException; import org.thingsboard.server.common.msg.session.FeatureType; @@ -32,6 +37,26 @@ public class TestCoapClient { private static final String COAP_BASE_URL = "coap://localhost:5683/api/v1/"; private static final long CLIENT_REQUEST_TIMEOUT = 60000L; + + private static final String MODULE2 = "TEST2."; + private static final IntegerDefinition INT2 = new IntegerDefinition(MODULE2 + "INT2", "TEST", null, 1); + private static final StringDefinition STRING = new StringDefinition(MODULE2 + "STRING", "TEST"); + + private static final ModuleDefinitionsProvider DEFAULTS = new ModuleDefinitionsProvider() { + + @Override + public String getModule() { + return MODULE2; + } + + @Override + public void applyDefinitions(Configuration config) { + TcpConfig.register(); + config.set(INT2, 100); + config.set(STRING, "Hallo"); + } + }; + private final CoapClient client; public TestCoapClient(){ @@ -43,7 +68,8 @@ public class TestCoapClient { } public TestCoapClient(String featureTokenUrl) { - this.client = createClient(featureTokenUrl); + Configuration.addDefaultModule(DEFAULTS); + this.client = new CoapClient(featureTokenUrl); } public void connectToCoap(String accessToken) { From b3e49d4cda8de527078c46fd034c103d5e285031 Mon Sep 17 00:00:00 2001 From: Ivan Raznatovskyi Date: Wed, 31 Jan 2024 10:04:30 +0200 Subject: [PATCH 184/397] Removed ng-deep --- .../gateway/gateway-connectors.component.scss | 5 ----- ...teway-service-rpc-connector.component.html | 2 +- ...teway-service-rpc-connector.component.scss | 20 +------------------ .../gateway-service-rpc.component.html | 10 ++++++---- .../gateway-service-rpc.component.scss | 7 ------- 5 files changed, 8 insertions(+), 36 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss index 036523e269..76676b4c5e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss @@ -97,8 +97,3 @@ background-color: rgb(25, 128, 56); } } - -:host ::ng-deep tb-json-object-edit > div { - flex-grow: 1; -} - diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html index d0d8e32acd..2d992187f6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html @@ -279,7 +279,7 @@ {{ 'gateway.rpc.oids' | translate }}*
    - +
    - {{ 'gateway.rpc-command-result' | translate }} -
    schedule - {{ resultTime | date: 'yyyy/MM/dd HH:mm:ss' }}
    + {{ 'gateway.rpc-command-result' | translate }} +
    + schedule + {{ resultTime | date: 'yyyy/MM/dd HH:mm:ss' }} +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.scss index d3dd9114c4..f74097bbba 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.scss @@ -81,10 +81,3 @@ border-radius: 4px; } } - -:host ::ng-deep { - .tb-json-content { - height: 100%; - } -} - From 719ec92653a01c25851094db38b7a128ca272a59 Mon Sep 17 00:00:00 2001 From: Ivan Raznatovskyi Date: Wed, 31 Jan 2024 11:11:47 +0200 Subject: [PATCH 185/397] Fixed methods writing --- ...eway-service-rpc-connector-templates.component.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.ts index 6e212dc079..4392b35f2d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector-templates.component.ts @@ -23,6 +23,7 @@ import { EntityType } from '@shared/models/entity-type.models'; import { AttributeScope } from '@shared/models/telemetry/telemetry.models'; import { AttributeService } from '@core/http/attribute.service'; import { WidgetContext } from '@home/models/widget-component.models'; +import { isLiteralObject } from '@app/core/utils'; @Component({ selector: 'tb-gateway-service-rpc-connector-templates', @@ -46,6 +47,9 @@ export class GatewayServiceRPCConnectorTemplatesComponent implements OnInit { @Input() rpcTemplates: Array; + public readonly originalOrder = (): number => 0; + public readonly isObject = (value: any) => isLiteralObject(value); + constructor(private attributeService: AttributeService) { } @@ -75,12 +79,4 @@ export class GatewayServiceRPCConnectorTemplatesComponent implements OnInit { }]).subscribe(() => { }) } - - public originalOrder = (a, b): number => { - return 0; - } - - public isObject(value: any) { - return value !== null && typeof value === 'object' && !Array.isArray(value); - } } From 537a8be9828b2a6edc915f77d37d3b3e6941497e Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 31 Jan 2024 13:32:47 +0200 Subject: [PATCH 186/397] coap: comments1 --- .../transport/coap/client/DefaultCoapClientContext.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java index 2140e1966c..08e4c513df 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java @@ -488,10 +488,7 @@ public class DefaultCoapClientContext implements CoapClientContext { Response resp = state.getAdaptor().convertToPublish(msg); Response response = new Response(ResponseCode.VALID); response.setPayload(resp.getPayload()); - if (state.getRpc() == null) { - state.setRpc(new TbCoapObservationState(attrs.getExchange(), attrs.getToken())); - } - response.getOptions().setObserve(state.getRpc().getObserveCounter().getAndIncrement()); + response.getOptions().setObserve(attrs.getObserveCounter().getAndIncrement()); respond(attrs.getExchange(), response, state.getContentFormat()); } catch (AdaptorException e) { log.trace("Failed to reply due to error", e); @@ -522,7 +519,7 @@ public class DefaultCoapClientContext implements CoapClientContext { boolean conRequest = AbstractSyncSessionCallback.isConRequest(state.getAttrs()); int requestId = getNextMsgId(); Response response = state.getAdaptor().convertToPublish(msg); - response.getOptions().setObserve(state.getRpc().getObserveCounter().getAndIncrement()); + response.getOptions().setObserve(attrs.getObserveCounter().getAndIncrement()); response.setConfirmable(conRequest); response.setMID(requestId); if (conRequest) { From e9e511f94daf33c1c874651de68fcafe256d0403 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 31 Jan 2024 14:17:48 +0200 Subject: [PATCH 187/397] updated SQL_TTL_TS_TS_KEY_VALUE_TTL parameter description --- application/src/main/resources/thingsboard.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index a02ae3da3f..82ad2bc8a9 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -380,9 +380,7 @@ sql: enabled: "${SQL_TTL_TS_ENABLED:true}" execution_interval_ms: "${SQL_TTL_TS_EXECUTION_INTERVAL:86400000}" # Number of milliseconds. The current value corresponds to one day # The parameter to specify system TTL(Time To Live) value for timeseries records. Value set in seconds. - # 0 - records are never expired. System TTL value can be overwritten for a particular Tenant, or parent Customer entity by setting the server-side - # attribute TTL to the corresponding Tenant or parent Customer entity. Please, note that the value should be set as long value, otherwise the TTL - # will be used from the higher level(Tenant or System) + # 0 - records are never expired. ts_key_value_ttl: "${SQL_TTL_TS_TS_KEY_VALUE_TTL:0}" events: # Enable/disable TTL (Time To Live) for event records From f35ce53fce3b0284d9c0708888f59ce730a5f2d3 Mon Sep 17 00:00:00 2001 From: Rhyaldir <150129324+Rhyaldir@users.noreply.github.com> Date: Wed, 31 Jan 2024 14:13:57 +0100 Subject: [PATCH 188/397] Add mockito-inline to support mocking statics and final classes --- common/transport/lwm2m/pom.xml | 5 +++++ pom.xml | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/common/transport/lwm2m/pom.xml b/common/transport/lwm2m/pom.xml index 0f00bbb2c9..530000f95e 100644 --- a/common/transport/lwm2m/pom.xml +++ b/common/transport/lwm2m/pom.xml @@ -94,6 +94,11 @@ junit-vintage-engine test + + org.mockito + mockito-inline + test + org.awaitility awaitility diff --git a/pom.xml b/pom.xml index 6efb293c41..3a5e64db9e 100755 --- a/pom.xml +++ b/pom.xml @@ -131,6 +131,7 @@ 2.7.2 1.5.2 5.8.2 + 4.5.1 2.6.0 5.13.1 1.3.0 @@ -1649,6 +1650,12 @@ + + org.mockito + mockito-inline + ${mockito.version} + test + org.testng testng From 99d8f9966b35b3ac21fc7ed59707654d3cbffb45 Mon Sep 17 00:00:00 2001 From: Rhyaldir <150129324+Rhyaldir@users.noreply.github.com> Date: Wed, 31 Jan 2024 16:49:22 +0100 Subject: [PATCH 189/397] Fix: Registration is not found when using CID and address or port has changed --- .../store/TbLwM2mRedisRegistrationStore.java | 22 +- .../store/util/LwM2MIdentitySerDes.java | 63 +++++ .../TbLwM2mRedisRegistrationStoreTest.java | 265 ++++++++++++++++++ .../store/util/LwM2MIdentitySerDesTest.java | 77 +++++ 4 files changed, 422 insertions(+), 5 deletions(-) create mode 100644 common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MIdentitySerDes.java create mode 100644 common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStoreTest.java create mode 100644 common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MIdentitySerDesTest.java diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java index ff86e60490..23c7a57dd6 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStore.java @@ -29,7 +29,6 @@ import org.eclipse.leshan.core.util.NamedThreadFactory; import org.eclipse.leshan.core.util.Validate; import org.eclipse.leshan.server.californium.registration.CaliforniumRegistrationStore; import org.eclipse.leshan.server.redis.RedisRegistrationStore; -import org.eclipse.leshan.server.redis.serialization.IdentitySerDes; import org.eclipse.leshan.server.redis.serialization.ObservationSerDes; import org.eclipse.leshan.server.redis.serialization.RegistrationSerDes; import org.eclipse.leshan.server.registration.Deregistration; @@ -45,6 +44,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.Cursor; import org.springframework.data.redis.core.ScanOptions; import org.springframework.integration.redis.util.RedisLockRegistry; +import org.thingsboard.server.transport.lwm2m.server.store.util.LwM2MIdentitySerDes; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -110,12 +110,18 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec, long lifetimeGracePeriodInSec, int cleanLimit) { + this(connectionFactory, schedExecutor, cleanPeriodInSec, lifetimeGracePeriodInSec, cleanLimit, + new RedisLockRegistry(connectionFactory, "Registration")); + } + + public TbLwM2mRedisRegistrationStore(RedisConnectionFactory connectionFactory, ScheduledExecutorService schedExecutor, long cleanPeriodInSec, + long lifetimeGracePeriodInSec, int cleanLimit, RedisLockRegistry lockRegistry) { this.connectionFactory = connectionFactory; this.schedExecutor = schedExecutor; this.cleanPeriod = cleanPeriodInSec; this.cleanLimit = cleanLimit; this.gracePeriod = lifetimeGracePeriodInSec; - this.redisLock = new RedisLockRegistry(connectionFactory, "Registration"); + this.redisLock = lockRegistry; } /* *************** Redis Key utility function **************** */ @@ -173,7 +179,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto if (!oldRegistration.getSocketAddress().equals(registration.getSocketAddress())) { removeAddrIndex(connection, oldRegistration); } - if (!oldRegistration.getIdentity().equals(registration.getIdentity())) { + if (registrationsHaveDifferentIdentities(oldRegistration, registration)) { removeIdentityIndex(connection, oldRegistration); } // remove old observation @@ -231,7 +237,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto if (!r.getSocketAddress().equals(updatedRegistration.getSocketAddress())) { removeAddrIndex(connection, r); } - if (!r.getIdentity().equals(updatedRegistration.getIdentity())) { + if (registrationsHaveDifferentIdentities(r, updatedRegistration)) { removeIdentityIndex(connection, r); } @@ -402,6 +408,12 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto connection.zRem(EXP_EP, registration.getEndpoint().getBytes(UTF_8)); } + private boolean registrationsHaveDifferentIdentities(Registration first, Registration second){ + var first_identity_string = LwM2MIdentitySerDes.serialize(first.getIdentity()).toString(); + var second_identity_string = LwM2MIdentitySerDes.serialize(second.getIdentity()).toString(); + return !first_identity_string.equals(second_identity_string); + } + private byte[] toRegIdKey(String registrationId) { return toKey(REG_EP_REGID_IDX, registrationId); } @@ -411,7 +423,7 @@ public class TbLwM2mRedisRegistrationStore implements CaliforniumRegistrationSto } private byte[] toRegIdentityKey(Identity identity) { - return toKey(REG_EP_IDENTITY, IdentitySerDes.serialize(identity).toString()); + return toKey(REG_EP_IDENTITY, LwM2MIdentitySerDes.serialize(identity).toString()); } private byte[] toEndpointKey(String endpoint) { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MIdentitySerDes.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MIdentitySerDes.java new file mode 100644 index 0000000000..4ffbfd82bb --- /dev/null +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MIdentitySerDes.java @@ -0,0 +1,63 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.server.store.util; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonObject; +import org.apache.commons.lang3.NotImplementedException; +import org.eclipse.leshan.core.request.Identity; +import org.eclipse.leshan.core.util.Hex; + +import java.security.PublicKey; + +public class LwM2MIdentitySerDes { + + private static final String KEY_ADDRESS = "address"; + private static final String KEY_PORT = "port"; + private static final String KEY_ID = "id"; + private static final String KEY_CN = "cn"; + private static final String KEY_RPK = "rpk"; + protected static final String KEY_LWM2MIDENTITY_TYPE = "type"; + protected static final String LWM2MIDENTITY_TYPE_UNSECURE = "unsecure"; + protected static final String LWM2MIDENTITY_TYPE_PSK = "psk"; + protected static final String LWM2MIDENTITY_TYPE_X509 = "x509"; + protected static final String LWM2MIDENTITY_TYPE_RPK = "rpk"; + + public static JsonObject serialize(Identity identity) { + JsonObject o = Json.object(); + + if (identity.isPSK()) { + o.set(KEY_LWM2MIDENTITY_TYPE, LWM2MIDENTITY_TYPE_PSK); + o.set(KEY_ID, identity.getPskIdentity()); + } else if (identity.isRPK()) { + o.set(KEY_LWM2MIDENTITY_TYPE, LWM2MIDENTITY_TYPE_RPK); + PublicKey publicKey = identity.getRawPublicKey(); + o.set(KEY_RPK, Hex.encodeHexString(publicKey.getEncoded())); + } else if (identity.isX509()) { + o.set(KEY_LWM2MIDENTITY_TYPE, LWM2MIDENTITY_TYPE_X509); + o.set(KEY_CN, identity.getX509CommonName()); + } else { + o.set(KEY_LWM2MIDENTITY_TYPE, LWM2MIDENTITY_TYPE_UNSECURE); + o.set(KEY_ADDRESS, identity.getPeerAddress().getHostString()); + o.set(KEY_PORT, identity.getPeerAddress().getPort()); + } + return o; + } + + public static Identity deserialize(JsonObject peer) { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStoreTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStoreTest.java new file mode 100644 index 0000000000..e09f2205b7 --- /dev/null +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/TbLwM2mRedisRegistrationStoreTest.java @@ -0,0 +1,265 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.server.store; + +import org.eclipse.leshan.core.link.Link; +import org.eclipse.leshan.core.request.Identity; +import org.eclipse.leshan.core.util.NamedThreadFactory; +import org.eclipse.leshan.server.redis.serialization.RegistrationSerDes; +import org.eclipse.leshan.server.registration.Registration; +import org.eclipse.leshan.server.registration.RegistrationUpdate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.integration.redis.util.RedisLockRegistry; +import org.springframework.test.util.ReflectionTestUtils; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.locks.Lock; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mRedisRegistrationStore.DEFAULT_CLEAN_LIMIT; +import static org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mRedisRegistrationStore.DEFAULT_CLEAN_PERIOD; +import static org.thingsboard.server.transport.lwm2m.server.store.TbLwM2mRedisRegistrationStore.DEFAULT_GRACE_PERIOD; + + +@ExtendWith(MockitoExtension.class) +class TbLwM2mRedisRegistrationStoreTest { + + RedisConnectionFactory connectionFactory; + RedisConnection connection; + RedisLockRegistry lockRegistry; + + TbLwM2mRedisRegistrationStore registrationStore; + + @BeforeEach + void setUp() { + lockRegistry = mock(RedisLockRegistry.class); + lenient().when(lockRegistry.obtain(any())).thenReturn(mock(Lock.class)); + connection = mock(RedisConnection.class); + //when(connection.set(any(byte[].class), any(byte[].class))). + connectionFactory = mock(RedisConnectionFactory.class); + lenient().when(connectionFactory.getConnection()).thenReturn(connection); + ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, + new NamedThreadFactory(String.format("RedisRegistrationStore Cleaner (%ds)", DEFAULT_CLEAN_PERIOD))); + registrationStore = new TbLwM2mRedisRegistrationStore(connectionFactory, executorService, + DEFAULT_CLEAN_PERIOD, DEFAULT_GRACE_PERIOD, DEFAULT_CLEAN_LIMIT, lockRegistry); + } + + @Test + void testAddRegistrationWithNoOldRegistration() { + setOldRegistration(null); + Registration registration = buildRegistration(); + + assertThat(registrationStore.addRegistration(registration)).isNull(); + + byte[] endpoint = registration.getEndpoint().getBytes(UTF_8); + verify(connection, times(1)).set(getRegIdKey(registration), endpoint); + verify(connection, times(1)).set(getRegAddrKey(registration), endpoint); + verify(connection, times(1)).set(getRegIdentityKey(registration), endpoint); + verify(connection, times(3)).set(any(byte[].class), any(byte[].class)); + verify(connection, times(0)).del(any(byte[].class)); + } + + @Test + void testAddRegistrationWithOldRegistrationEqualToCurrent(){ + var oldRegistration = buildRegistration(); + setOldRegistration(oldRegistration); + Registration registration = buildRegistration(); + + var deregistration = registrationStore.addRegistration(registration); + + assertThat(deregistration.getRegistration()).isEqualTo(oldRegistration); + + byte[] endpoint = registration.getEndpoint().getBytes(UTF_8); + verify(connection, times(1)).set(getRegIdKey(registration), endpoint); + verify(connection, times(1)).set(getRegAddrKey(registration), endpoint); + verify(connection, times(1)).set(getRegIdentityKey(registration), endpoint); + verify(connection, times(3)).set(any(byte[].class), any(byte[].class)); + verify(connection, times(1)).del(getTknsRegIdKey(oldRegistration)); + verify(connection, times(1)).del(any(byte[].class)); + } + + @Test + void testAddRegistrationRemovesIndexes(){ + var oldRegistration = buildRegistration(Identity.unsecure(getTestAddress(1234))); + setOldRegistration(oldRegistration); + var registration = buildRegistration(Identity.unsecure(getTestAddress(2345))); + + var deregistration = registrationStore.addRegistration(registration); + + assertThat(deregistration.getRegistration()).isEqualTo(oldRegistration); + byte[] endpoint = registration.getEndpoint().getBytes(UTF_8); + verify(connection, times(1)).set(getRegIdKey(registration), endpoint); + verify(connection, times(1)).set(getRegAddrKey(registration), endpoint); + verify(connection, times(1)).set(getRegIdentityKey(registration), endpoint); + verify(connection, times(3)).set(any(byte[].class), any(byte[].class)); + verify(connection, times(1)).del(getRegAddrKey(oldRegistration)); + verify(connection, times(1)).del(getRegIdentityKey(oldRegistration)); + verify(connection, times(1)).del(getTknsRegIdKey(oldRegistration)); + verify(connection, times(3)).del(any(byte[].class)); + } + + @Test + void testUpdateRegistrationWhenNoRegistrationFound() { + setOldRegistration(null); + Registration registration = buildRegistration(); + RegistrationUpdate update = createUpdateFromRegistration(registration); + + assertThat(registrationStore.updateRegistration(update)).isNull(); + + verify(connection, times(1)).get(getRegIdKey(registration)); + verify(connection, times(1)).get(any(byte[].class)); + verify(connection, times(0)).del(any(byte[].class)); + } + + @Test + void testUpdateRegistrationWithSameRegistration() { + Registration registration = buildRegistration(); + setOldRegistration(registration); + RegistrationUpdate update = createUpdateFromRegistration(registration); + + assertThat(registrationStore.updateRegistration(update)).isNotNull(); + + var endpoint = registration.getEndpoint().getBytes(UTF_8); + // check registration and addressIndex here updated + verify(connection, times(1)).set(eq(getEndpointKey(endpoint)), any(byte[].class)); + verify(connection, times(1)).set(getRegAddrKey(registration), endpoint); + verify(connection, times(2)).set(any(byte[].class), any(byte[].class)); + verify(connection, times(0)).del(any(byte[].class)); + } + + @Test + void testUpdateRegistrationWithRegistrationFromSecureIdentitiesWithDifferentAddress() { + Registration oldRegistration = buildRegistration(Identity.psk(getTestAddress(1234), "my:psk")); + setOldRegistration(oldRegistration); + Registration newRegistration = buildRegistration(Identity.psk(getTestAddress(2345), "my:psk")); + RegistrationUpdate update = createUpdateFromRegistration(newRegistration); + assertThat(oldRegistration.getEndpoint()).isEqualTo(newRegistration.getEndpoint()); + + assertThat(registrationStore.updateRegistration(update)).isNotNull(); + + var endpoint = newRegistration.getEndpoint().getBytes(UTF_8); + // check registration and addressIndex here updated + verify(connection, times(1)).set(eq(getEndpointKey(endpoint)), any(byte[].class)); + verify(connection, times(1)).set(getRegAddrKey(newRegistration), endpoint); + // check old AddrIndex has been removed + verify(connection, times(1)).del(getRegAddrKey(oldRegistration)); + // check identityIndex has not been removed + verify(connection, times(0)).del(getRegIdentityKey(oldRegistration)); + // check only one key (AddrIndex) in total was removed + verify(connection, times(1)).del(any(byte[].class)); + } + + @Test + void testGetRegistrationByIdentityReturnsRegistrationForSecureIdentityWithDifferentAddress() { + Registration registration = buildRegistration(Identity.psk(getTestAddress(1234), "my:psk")); + setOldRegistration(registration); + Identity sameIdentityWithDifferentAddress = Identity.psk(getTestAddress(2345), "my:psk"); + + Registration retrievedRegistration = registrationStore.getRegistrationByIdentity(sameIdentityWithDifferentAddress); + + assertThat(retrievedRegistration).isEqualTo(registration); + } + + private void setOldRegistration(Registration oldRegistration){ + byte[] serializedRegistration = null; + if (oldRegistration != null){ + byte[] endpoint = oldRegistration.getEndpoint().getBytes(UTF_8); + // set the AddrIndex + byte[] regAddrKey = getRegAddrKey(oldRegistration); + lenient().when(connection.get(eq(regAddrKey))).thenReturn(endpoint); + // set the IdentityIndex + byte[] regIdentityKey = getRegIdentityKey(oldRegistration); + lenient().when(connection.get(eq(regIdentityKey))).thenReturn(endpoint); + // set the IdIndex + byte[] regIdKey = getRegIdKey(oldRegistration); + lenient().when(connection.get(eq(regIdKey))).thenReturn(endpoint); + // set the registration + serializedRegistration = RegistrationSerDes.bSerialize(oldRegistration); + lenient().when(connection.get(eq(getEndpointKey(endpoint)))).thenReturn(serializedRegistration); + } + lenient().when(connection.getSet(any(byte[].class), any(byte[].class))).thenReturn(serializedRegistration); + } + + private byte[] getRegAddrKey(Registration registration){ + return ReflectionTestUtils.invokeMethod(registrationStore, "toRegAddrKey", registration.getSocketAddress()); + } + + private byte[] getRegIdentityKey(Registration registration){ + return ReflectionTestUtils.invokeMethod(registrationStore, "toRegIdentityKey", registration.getIdentity()); + } + + private byte[] getRegIdKey(Registration registration){ + return ReflectionTestUtils.invokeMethod(registrationStore, "toRegIdKey", registration.getId()); + } + + private byte[] getEndpointKey(byte[] endpoint){ + return ReflectionTestUtils.invokeMethod(registrationStore, "toEndpointKey", endpoint); + } + + private byte[] getTknsRegIdKey(Registration registration){ + return ReflectionTestUtils.invokeMethod(registrationStore, "toKey", "TKNS:REGID:", registration.getId()); + } + + private static Registration buildRegistration() { + return buildRegistration(Identity.psk(getTestAddress(), "my:psk")); + } + + private static Registration buildRegistration(Identity identity){ + return new Registration.Builder("my_reg_id", "abcde", identity) + .objectLinks(new Link[]{}) + .build(); + } + + private static RegistrationUpdate createUpdateFromRegistration(Registration registration){ + return new RegistrationUpdate( + registration.getId(), + registration.getIdentity(), + registration.getLifeTimeInSec(), + registration.getSmsNumber(), + registration.getBindingMode(), + registration.getObjectLinks(), + registration.getAdditionalRegistrationAttributes() + ); + } + + private static InetSocketAddress getTestAddress() { + return getTestAddress(5684); + } + + private static InetSocketAddress getTestAddress(int port) { + try { + return new InetSocketAddress(InetAddress.getByName("1.2.3.4"), port); + } catch (UnknownHostException e) { + throw new AssertionError("Cannot create test address"); + } + } +} \ No newline at end of file diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MIdentitySerDesTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MIdentitySerDesTest.java new file mode 100644 index 0000000000..c75ed7a195 --- /dev/null +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MIdentitySerDesTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.server.store.util; + +import com.eclipsesource.json.JsonObject; +import org.apache.commons.lang3.NotImplementedException; +import org.eclipse.leshan.core.request.Identity; +import org.junit.jupiter.api.Test; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.security.PublicKey; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class LwM2MIdentitySerDesTest { + + @Test + void serializePskIdentity() { + assertThat(LwM2MIdentitySerDes.serialize(Identity.psk(getTestAddress(), "my:psk")).toString()) + .isEqualTo("{\"type\":\"psk\",\"id\":\"my:psk\"}"); + } + + + @Test + void serializeRpkIdentity() { + var public_key = mock(PublicKey.class); + when(public_key.getEncoded()).thenReturn(new byte[]{1,2,3,4,5,6,7,8,9}); + + assertThat(LwM2MIdentitySerDes.serialize(Identity.rpk(getTestAddress(), public_key)).toString()) + .isEqualTo("{\"type\":\"rpk\",\"rpk\":\"010203040506070809\"}"); + } + + @Test + void serializeX509Identity() { + assertThat(LwM2MIdentitySerDes.serialize(Identity.x509(getTestAddress(), "MyCommonName")).toString()) + .isEqualTo("{\"type\":\"x509\",\"cn\":\"MyCommonName\"}"); + } + + @Test + void serializeUnsecureIdentity() { + assertThat(LwM2MIdentitySerDes.serialize(Identity.unsecure(getTestAddress())).toString()) + .isEqualTo("{\"type\":\"unsecure\",\"address\":\"1.2.3.4\",\"port\":5684}"); + } + + + @Test + void deserialize() { + assertThatThrownBy(() -> LwM2MIdentitySerDes.deserialize(mock(JsonObject.class))) + .isInstanceOf(NotImplementedException.class); + } + + private static InetSocketAddress getTestAddress() { + try { + return new InetSocketAddress(InetAddress.getByName("1.2.3.4"), 5684); + } catch (UnknownHostException e) { + throw new AssertionError("Cannot create test address"); + } + } +} \ No newline at end of file From 7748c56bc3e5d39a9e5d1f5b194d5ce57441d81f Mon Sep 17 00:00:00 2001 From: nick Date: Thu, 1 Feb 2024 15:47:26 +0200 Subject: [PATCH 190/397] coap: comments1 --- .../server/msa/AbstractCoapClientTest.java | 81 ++++++++++ .../server/msa/TestCoapClient.java | 148 ------------------ .../server/msa/TestCoapClientCallback.java | 68 -------- .../msa/connectivity/CoapClientTest.java | 28 +--- 4 files changed, 85 insertions(+), 240 deletions(-) create mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractCoapClientTest.java delete mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClient.java delete mode 100644 msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClientCallback.java diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractCoapClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractCoapClientTest.java new file mode 100644 index 0000000000..4ed5426bc4 --- /dev/null +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractCoapClientTest.java @@ -0,0 +1,81 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.msa; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.eclipse.californium.core.CoapClient; +import org.eclipse.californium.core.coap.MediaTypeRegistry; +import org.eclipse.californium.core.config.CoapConfig; +import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.californium.elements.config.Configuration.ModuleDefinitionsProvider; +import org.eclipse.californium.elements.config.IntegerDefinition; +import org.eclipse.californium.elements.config.TcpConfig; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.msg.session.FeatureType; + +public abstract class AbstractCoapClientTest extends AbstractContainerTest{ + + private static final String COAP_BASE_URL = "coap://localhost:5683/api/v1/"; + private static final long CLIENT_REQUEST_TIMEOUT = 60000L; + + + private static final String COAP_CLIENT_TEST = "COAP_CLIENT_TEST."; + private static final IntegerDefinition COAP_PORT_DEF = CoapConfig.COAP_PORT; + + private static final ModuleDefinitionsProvider MODULE_DEFINITIONS_PROVIDER = new ModuleDefinitionsProvider() { + + @Override + public String getModule() { + return COAP_CLIENT_TEST; + } + + @Override + public void applyDefinitions(Configuration config) { + TcpConfig.register(); + config.set(COAP_PORT_DEF, 5683); + } + }; + + protected CoapClient client; + + protected byte[] createCoapClientAndPublish(String deviceName) throws Exception { + String provisionRequestMsg = createTestProvisionMessage(deviceName); + Configuration.addDefaultModule(MODULE_DEFINITIONS_PROVIDER); + String featureTokenUrl = COAP_BASE_URL + FeatureType.PROVISION.name().toLowerCase(); + client = new CoapClient(featureTokenUrl); + return client.setTimeout(CLIENT_REQUEST_TIMEOUT) + .post(provisionRequestMsg.getBytes(), MediaTypeRegistry.APPLICATION_JSON) + .getPayload(); + } + + protected void disconnect() { + if (client != null) { + client.shutdown(); + } + } + + private String createTestProvisionMessage(String deviceName) { + ObjectNode provisionRequest = JacksonUtil.newObjectNode(); + provisionRequest.put("provisionDeviceKey", TEST_PROVISION_DEVICE_KEY); + provisionRequest.put("provisionDeviceSecret", TEST_PROVISION_DEVICE_SECRET); + if (deviceName != null) { + provisionRequest.put("deviceName", deviceName); + } + return provisionRequest.toString(); + } +} + + diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClient.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClient.java deleted file mode 100644 index 8fa6c44f4a..0000000000 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClient.java +++ /dev/null @@ -1,148 +0,0 @@ -/** - * Copyright © 2016-2024 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.msa; - -import org.eclipse.californium.core.CoapClient; -import org.eclipse.californium.core.CoapHandler; -import org.eclipse.californium.core.CoapObserveRelation; -import org.eclipse.californium.core.CoapResponse; -import org.eclipse.californium.core.coap.CoAP; -import org.eclipse.californium.core.coap.MediaTypeRegistry; -import org.eclipse.californium.core.coap.Request; -import org.eclipse.californium.elements.config.Configuration; -import org.eclipse.californium.elements.config.Configuration.ModuleDefinitionsProvider; -import org.eclipse.californium.elements.config.IntegerDefinition; -import org.eclipse.californium.elements.config.StringDefinition; -import org.eclipse.californium.elements.config.TcpConfig; -import org.eclipse.californium.elements.exception.ConnectorException; -import org.thingsboard.server.common.msg.session.FeatureType; - -import java.io.IOException; - -public class TestCoapClient { - - private static final String COAP_BASE_URL = "coap://localhost:5683/api/v1/"; - private static final long CLIENT_REQUEST_TIMEOUT = 60000L; - - - private static final String MODULE2 = "TEST2."; - private static final IntegerDefinition INT2 = new IntegerDefinition(MODULE2 + "INT2", "TEST", null, 1); - private static final StringDefinition STRING = new StringDefinition(MODULE2 + "STRING", "TEST"); - - private static final ModuleDefinitionsProvider DEFAULTS = new ModuleDefinitionsProvider() { - - @Override - public String getModule() { - return MODULE2; - } - - @Override - public void applyDefinitions(Configuration config) { - TcpConfig.register(); - config.set(INT2, 100); - config.set(STRING, "Hallo"); - } - }; - - private final CoapClient client; - - public TestCoapClient(){ - this.client = createClient(); - } - - public TestCoapClient(String accessToken, FeatureType featureType) { - this.client = createClient(getFeatureTokenUrl(accessToken, featureType)); - } - - public TestCoapClient(String featureTokenUrl) { - Configuration.addDefaultModule(DEFAULTS); - this.client = new CoapClient(featureTokenUrl); - } - - public void connectToCoap(String accessToken) { - setURI(accessToken, null); - } - - public void connectToCoap(String accessToken, FeatureType featureType) { - setURI(accessToken, featureType); - } - - public void disconnect() { - if (client != null) { - client.shutdown(); - } - } - - public CoapResponse postMethod(String requestBody) throws ConnectorException, IOException { - return this.postMethod(requestBody.getBytes()); - } - - public CoapResponse postMethod(byte[] requestBodyBytes) throws ConnectorException, IOException { - return client.setTimeout(CLIENT_REQUEST_TIMEOUT).post(requestBodyBytes, MediaTypeRegistry.APPLICATION_JSON); - } - - public void postMethod(CoapHandler handler, String payload, int format) { - client.post(handler, payload, format); - } - - public void postMethod(CoapHandler handler, byte[] payload, int format) { - client.post(handler, payload, format); - } - - public CoapResponse getMethod() throws ConnectorException, IOException { - return client.setTimeout(CLIENT_REQUEST_TIMEOUT).get(); - } - - public CoapObserveRelation getObserveRelation(TestCoapClientCallback callback){ - Request request = Request.newGet().setObserve(); - request.setType(CoAP.Type.CON); - return client.observe(request, callback); - } - - public void setURI(String featureTokenUrl) { - if (client == null) { - throw new RuntimeException("Failed to connect! CoapClient is not initialized!"); - } - client.setURI(featureTokenUrl); - } - - public void setURI(String accessToken, FeatureType featureType) { - if (featureType == null){ - featureType = FeatureType.ATTRIBUTES; - } - setURI(getFeatureTokenUrl(accessToken, featureType)); - } - - private CoapClient createClient() { - return new CoapClient(); - } - - private CoapClient createClient(String featureTokenUrl) { - return new CoapClient(featureTokenUrl); - } - - public static String getFeatureTokenUrl(FeatureType featureType) { - return COAP_BASE_URL + featureType.name().toLowerCase(); - } - - public static String getFeatureTokenUrl(String token, FeatureType featureType) { - return COAP_BASE_URL + token + "/" + featureType.name().toLowerCase(); - } - - public static String getFeatureTokenUrl(String token, FeatureType featureType, int requestId) { - return COAP_BASE_URL + token + "/" + featureType.name().toLowerCase() + "/" + requestId; - } -} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClientCallback.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClientCallback.java deleted file mode 100644 index 49c5a06476..0000000000 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/TestCoapClientCallback.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright © 2016-2024 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.msa; - -import lombok.Data; -import lombok.extern.slf4j.Slf4j; -import org.eclipse.californium.core.CoapHandler; -import org.eclipse.californium.core.CoapResponse; -import org.eclipse.californium.core.coap.CoAP; - -import java.util.concurrent.CountDownLatch; - -@Slf4j -@Data -public class TestCoapClientCallback implements CoapHandler { - - protected final CountDownLatch latch; - protected Integer observe; - protected byte[] payloadBytes; - protected CoAP.ResponseCode responseCode; - - public TestCoapClientCallback() { - this.latch = new CountDownLatch(1); - } - - public TestCoapClientCallback(int subscribeCount) { - this.latch = new CountDownLatch(subscribeCount); - } - - public Integer getObserve() { - return observe; - } - - public byte[] getPayloadBytes() { - return payloadBytes; - } - - public CoAP.ResponseCode getResponseCode() { - return responseCode; - } - - @Override - public void onLoad(CoapResponse response) { - observe = response.getOptions().getObserve(); - payloadBytes = response.getPayload(); - responseCode = response.getCode(); - latch.countDown(); - } - - @Override - public void onError() { - log.warn("Command Response Ack Error, No connect"); - } - -} diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/CoapClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/CoapClientTest.java index 4dc7d91b2a..a65aff1bc1 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/CoapClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/CoapClientTest.java @@ -16,7 +16,6 @@ package org.thingsboard.server.msa.connectivity; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.gson.JsonObject; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; @@ -26,18 +25,14 @@ import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileProvisionType; import org.thingsboard.server.common.data.security.DeviceCredentials; -import org.thingsboard.server.common.msg.session.FeatureType; -import org.thingsboard.server.msa.AbstractContainerTest; +import org.thingsboard.server.msa.AbstractCoapClientTest; import org.thingsboard.server.msa.DisableUIListeners; -import org.thingsboard.server.msa.TestCoapClient; import static org.assertj.core.api.Assertions.assertThat; import static org.thingsboard.server.msa.prototypes.DevicePrototypes.defaultDevicePrototype; @DisableUIListeners -public class CoapClientTest extends AbstractContainerTest { - private TestCoapClient client; - +public class CoapClientTest extends AbstractCoapClientTest{ private Device device; @BeforeMethod public void setUp() throws Exception { @@ -48,6 +43,7 @@ public class CoapClientTest extends AbstractContainerTest { @AfterMethod public void tearDown() { testRestClient.deleteDeviceIfExists(device.getId()); + disconnect(); } @Test @@ -101,21 +97,5 @@ public class CoapClientTest extends AbstractContainerTest { assertThat(response.get("status").asText()).isEqualTo("NOT_FOUND"); } - - private byte[] createCoapClientAndPublish(String deviceName) throws Exception { - String provisionRequestMsg = createTestProvisionMessage(deviceName); - client = new TestCoapClient(TestCoapClient.getFeatureTokenUrl(FeatureType.PROVISION)); - return client.postMethod(provisionRequestMsg.getBytes()).getPayload(); - } - - private String createTestProvisionMessage(String deviceName) { - ObjectNode provisionRequest = JacksonUtil.newObjectNode(); - provisionRequest.put("provisionDeviceKey", TEST_PROVISION_DEVICE_KEY); - provisionRequest.put("provisionDeviceSecret", TEST_PROVISION_DEVICE_SECRET); - if (deviceName != null) { - provisionRequest.put("deviceName", deviceName); - } - return provisionRequest.toString(); - } - } + From 691a6b5d6a1cc0acd300eca5d9396e296207bf82 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Fri, 2 Feb 2024 10:52:38 +0200 Subject: [PATCH 191/397] Polishing after review --- .../queue/DefaultTbCoreConsumerService.java | 2 +- .../server/common/data/msg/TbMsgType.java | 2 +- .../server/common/data/msg/TbMsgTypeTest.java | 16 ++++++++-------- .../rule/engine/action/TbDeviceStateNode.java | 15 +++++++-------- .../engine/action/TbDeviceStateNodeTest.java | 11 +++++------ 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index 9942476c01..6db0e16f28 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -199,7 +199,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService typesWithNullRuleNodeConnection = List.of( ALARM, ALARM_DELETE, @@ -54,7 +54,7 @@ class TbMsgTypeTest { DEDUPLICATION_TIMEOUT_SELF_MSG, DELAY_TIMEOUT_SELF_MSG, MSG_COUNT_SELF_MSG, - DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG, + DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG, NA ); 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 a74df13f20..9d6901ea01 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 @@ -69,6 +69,7 @@ public class TbDeviceStateNode implements TbNode { ); private static final Duration ONE_SECOND = Duration.ofSeconds(1L); private static final Duration ENTRY_EXPIRATION_TIME = Duration.ofDays(1L); + private static final Duration ENTRY_CLEANUP_PERIOD = Duration.ofHours(1L); private Stopwatch stopwatch; private ConcurrentMap lastActivityEventTimestamps; @@ -91,10 +92,9 @@ public class TbDeviceStateNode implements TbNode { @Override public void onMsg(TbContext ctx, TbMsg msg) { - if (msg.isTypeOf(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG)) { + if (msg.isTypeOf(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG)) { removeStaleEntries(); scheduleCleanupMsg(ctx); - ctx.ack(msg); return; } @@ -109,7 +109,7 @@ public class TbDeviceStateNode implements TbNode { Duration now = stopwatch.elapsed(); if (lastEventTs == null) { - sendEvent(ctx, originator, msg); + sendEventAndTell(ctx, originator, msg); return now; } @@ -119,17 +119,16 @@ public class TbDeviceStateNode implements TbNode { return lastEventTs; } - sendEvent(ctx, originator, msg); - + sendEventAndTell(ctx, originator, msg); return now; }); } private void scheduleCleanupMsg(TbContext ctx) { TbMsg cleanupMsg = ctx.newMsg( - null, TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG, ctx.getSelfId(), TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING + null, TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG, ctx.getSelfId(), TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING ); - ctx.tellSelf(cleanupMsg, Duration.ofHours(1L).toMillis()); + ctx.tellSelf(cleanupMsg, ENTRY_CLEANUP_PERIOD.toMillis()); } private void removeStaleEntries() { @@ -141,7 +140,7 @@ public class TbDeviceStateNode implements TbNode { }); } - private void sendEvent(TbContext ctx, DeviceId originator, TbMsg msg) { + private void sendEventAndTell(TbContext ctx, DeviceId originator, TbMsg msg) { TenantId tenantId = ctx.getTenantId(); long eventTs = msg.getMetaDataTs(); diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java index af72927e3c..1ce49b3a7b 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java @@ -96,7 +96,7 @@ public class TbDeviceStateNodeTest { data.put("humidity", 58.3); msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, JacksonUtil.toString(data)); nodeId = new RuleNodeId(UUID.randomUUID()); - cleanupMsg = TbMsg.newMsg(null, TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG, nodeId, TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING); + cleanupMsg = TbMsg.newMsg(null, TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG, nodeId, TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING); } @BeforeEach @@ -123,7 +123,7 @@ public class TbDeviceStateNodeTest { public void givenValidConfig_whenInit_thenSchedulesCleanupMsg() { // GIVEN given(ctxMock.getSelfId()).willReturn(nodeId); - given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); + given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); // WHEN try { @@ -140,7 +140,7 @@ public class TbDeviceStateNodeTest { public void givenCleanupMsg_whenOnMsg_thenCleansStaleEntries() { // GIVEN given(ctxMock.getSelfId()).willReturn(nodeId); - given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); + given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); ConcurrentMap lastActivityEventTimestamps = new ConcurrentHashMap<>(); ReflectionTestUtils.setField(node, "lastActivityEventTimestamps", lastActivityEventTimestamps); @@ -169,7 +169,6 @@ public class TbDeviceStateNodeTest { .size().isOne(); verifyCleanupMsgSent(); - then(ctxMock).should().ack(cleanupMsg); then(ctxMock).shouldHaveNoMoreInteractions(); } @@ -272,7 +271,7 @@ public class TbDeviceStateNodeTest { public void givenSupportedEventAndDeviceOriginator_whenOnMsg_thenCorrectEventIsSentWithCorrectCallback(TbMsgType supportedEventType, Runnable actionVerification) { // GIVEN given(ctxMock.getSelfId()).willReturn(nodeId); - given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); + given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); given(ctxMock.getTenantId()).willReturn(TENANT_ID); given(ctxMock.getDeviceStateManager()).willReturn(deviceStateManagerMock); @@ -320,7 +319,7 @@ public class TbDeviceStateNodeTest { private void verifyCleanupMsgSent() { then(ctxMock).should().getSelfId(); - then(ctxMock).should().newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING)); + then(ctxMock).should().newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING)); then(ctxMock).should().tellSelf(eq(cleanupMsg), eq(Duration.ofHours(1L).toMillis())); } From 46dca971e119c031f63cd5fab40390d6cf9576a0 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Fri, 2 Feb 2024 11:19:20 +0200 Subject: [PATCH 192/397] Add check to ensure that received inactivity time is not outdated relative to current activity time --- .../state/DefaultDeviceStateService.java | 8 ++++- .../state/DefaultDeviceStateServiceTest.java | 32 +++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java index b400b4f65a..30c59b3da8 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java @@ -327,10 +327,16 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService Date: Fri, 2 Feb 2024 16:03:35 +0200 Subject: [PATCH 193/397] Add test to ensure message timestamp is used as event timestamp when metadata ts property is not present --- .../thingsboard/server/common/msg/TbMsg.java | 5 ++++ .../engine/action/TbDeviceStateNodeTest.java | 25 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java index d81393cf25..cbf9ae34b3 100644 --- a/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java +++ b/common/message/src/main/java/org/thingsboard/server/common/msg/TbMsg.java @@ -131,6 +131,11 @@ public final class TbMsg implements Serializable { metaData.copy(), TbMsgDataType.JSON, data, null, null, null, TbMsgCallback.EMPTY); } + public static TbMsg newMsg(TbMsgType type, EntityId originator, TbMsgMetaData metaData, String data, long ts) { + return new TbMsg(null, UUID.randomUUID(), ts, type, originator, null, + metaData.copy(), TbMsgDataType.JSON, data, null, null, null, TbMsgCallback.EMPTY); + } + // REALLY NEW MSG /** diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java index 1ce49b3a7b..d66babea9a 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java @@ -55,6 +55,7 @@ import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.BDDMockito.given; @@ -75,7 +76,7 @@ public class TbDeviceStateNodeTest { private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final DeviceId DEVICE_ID = new DeviceId(UUID.randomUUID()); - private static final long METADATA_TS = System.currentTimeMillis(); + private static final long METADATA_TS = 123L; private TbMsg cleanupMsg; private TbMsg msg; private long nowNanos; @@ -266,6 +267,28 @@ public class TbDeviceStateNodeTest { then(ctxMock).shouldHaveNoMoreInteractions(); } + @Test + public void givenMetadataDoesNotContainTs_whenOnMsg_thenMsgTsIsUsedAsEventTs() { + // GIVEN + try { + initNode(TbMsgType.ACTIVITY_EVENT); + } catch (TbNodeException e) { + fail("Node failed to initialize!", e); + } + + given(ctxMock.getTenantId()).willReturn(TENANT_ID); + given(ctxMock.getDeviceStateManager()).willReturn(deviceStateManagerMock); + + long msgTs = METADATA_TS + 1; + msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, TbMsg.EMPTY_JSON_OBJECT, msgTs); + + // WHEN + node.onMsg(ctxMock, msg); + + // THEN + then(deviceStateManagerMock).should().onDeviceActivity(eq(TENANT_ID), eq(DEVICE_ID), eq(msgTs), any()); + } + @ParameterizedTest @MethodSource public void givenSupportedEventAndDeviceOriginator_whenOnMsg_thenCorrectEventIsSentWithCorrectCallback(TbMsgType supportedEventType, Runnable actionVerification) { From a89802e801a73245daa38b4f831dd863b6197794 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Fri, 2 Feb 2024 17:23:11 +0200 Subject: [PATCH 194/397] Response code fix --- .../attributes/AbstractCoapAttributesIntegrationTest.java | 4 ++-- .../transport/coap/client/DefaultCoapClientContext.java | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java index e8766ea039..92554b3067 100644 --- a/application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/coap/attributes/AbstractCoapAttributesIntegrationTest.java @@ -239,7 +239,7 @@ public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoap String awaitAlias = "await Json Test Subscribe To AttributesUpdates (client.getObserveRelation)"; await(awaitAlias) .atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .until(() -> ResponseCode.VALID.equals(callbackCoap.getResponseCode()) && + .until(() -> ResponseCode.CONTENT.equals(callbackCoap.getResponseCode()) && callbackCoap.getObserve() != null && 0 == callbackCoap.getObserve().intValue()); if (emptyCurrentStateNotification) { @@ -286,7 +286,7 @@ public abstract class AbstractCoapAttributesIntegrationTest extends AbstractCoap CoapObserveRelation observeRelation = client.getObserveRelation(callbackCoap); await(awaitAlias) .atMost(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .until(() -> ResponseCode.VALID.equals(callbackCoap.getResponseCode()) && + .until(() -> ResponseCode.CONTENT.equals(callbackCoap.getResponseCode()) && callbackCoap.getObserve() != null && 0 == callbackCoap.getObserve().intValue()); diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java index 08e4c513df..7177542c3d 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java @@ -485,9 +485,7 @@ public class DefaultCoapClientContext implements CoapClientContext { TbCoapObservationState attrs = state.getAttrs(); if (attrs != null) { try { - Response resp = state.getAdaptor().convertToPublish(msg); - Response response = new Response(ResponseCode.VALID); - response.setPayload(resp.getPayload()); + Response response = state.getAdaptor().convertToPublish(msg); response.getOptions().setObserve(attrs.getObserveCounter().getAndIncrement()); respond(attrs.getExchange(), response, state.getContentFormat()); } catch (AdaptorException e) { From 6a755ab0b7dc54e51ee67315572e095705ce1be0 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 6 Feb 2024 15:10:09 +0200 Subject: [PATCH 195/397] deleted java keystore type of creds support --- .../src/main/resources/thingsboard.yml | 32 ++------- .../cache/RedisKeystoreCredentialsConfig.java | 36 ---------- .../cache/RedisPemCredentialsConfig.java | 28 -------- ...guration.java => RedisSslCredentials.java} | 9 ++- .../cache/TBRedisCacheConfiguration.java | 69 +++++-------------- .../org/thingsboard/common/util/SslUtil.java | 1 + msa/black-box-tests/README.md | 4 ++ .../src/main/resources/tb-coap-transport.yml | 32 ++------- .../src/main/resources/tb-http-transport.yml | 32 ++------- .../src/main/resources/tb-lwm2m-transport.yml | 32 ++------- .../src/main/resources/tb-mqtt-transport.yml | 32 ++------- .../src/main/resources/tb-snmp-transport.yml | 32 ++------- 12 files changed, 70 insertions(+), 269 deletions(-) delete mode 100644 common/cache/src/main/java/org/thingsboard/server/cache/RedisKeystoreCredentialsConfig.java delete mode 100644 common/cache/src/main/java/org/thingsboard/server/cache/RedisPemCredentialsConfig.java rename common/cache/src/main/java/org/thingsboard/server/cache/{RedisSslCredentialsConfiguration.java => RedisSslCredentials.java} (84%) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 38cfdd64a0..050d46a700 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -643,32 +643,14 @@ redis: ssl: # Enable/disable secure connection enabled: "${TB_REDIS_SSL_ENABLED:false}" - # Server SSL credentials + # Server SSL credentials (only PEM format is supported) credentials: - # Server credentials type (pem - pem certificate file; keystore - java keystore) - type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" - # PEM server credentials - pem: - # Path redis server (CA) certificate - cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client - user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. - user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" - # Keystore server credentials - keystore: - # Type of the trust store (JKS or PKCS12) - truststore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the trust store file - truststore_location: "${TB_REDIS_SSL_TRUSTSTORE_LOCATION:}" - # The password of trust store file if specified - truststore_password: "${TB_REDIS_SSL_TRUSTSTORE_PASSWORD:}" - # Type of the key store (JKS or PKCS12) - keystore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the key store file. This is optional for the client and can be used for two-way authentication for the client - keystore_location: "${TB_REDIS_SSL_KEYSTORE_LOCATION:}" - # The store password for the key store file. This is optional for the client and only needed if ‘ssl.keystore.location’ is configured. Key store password is not supported for PEM format - keystore_password: "${TB_REDIS_SSL_KEYSTORE_PASSWORD:}" + # Path redis server (CA) certificate + cert_file: "${TB_REDIS_SSL_PEM_CERT:}" + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client + user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" + # Path to user private key file. This is optional for the client and only needed if ‘user_cert_file’ is configured. + user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # pool config pool_config: # Maximum number of connections that can be allocated by the connection pool diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/RedisKeystoreCredentialsConfig.java b/common/cache/src/main/java/org/thingsboard/server/cache/RedisKeystoreCredentialsConfig.java deleted file mode 100644 index 1d2a08e6d4..0000000000 --- a/common/cache/src/main/java/org/thingsboard/server/cache/RedisKeystoreCredentialsConfig.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright © 2016-2024 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.cache; - -import lombok.Data; - -@Data -public class RedisKeystoreCredentialsConfig { - - private String type; - - private String truststoreType; - - private String truststoreLocation; - - private String truststorePassword; - - private String keystoreType; - - private String keystoreLocation; - - private String keystorePassword; -} diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/RedisPemCredentialsConfig.java b/common/cache/src/main/java/org/thingsboard/server/cache/RedisPemCredentialsConfig.java deleted file mode 100644 index 50e2c71966..0000000000 --- a/common/cache/src/main/java/org/thingsboard/server/cache/RedisPemCredentialsConfig.java +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright © 2016-2024 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.cache; - -import lombok.Data; - -@Data -public class RedisPemCredentialsConfig { - - private String certFile; - - private String userCertFile; - - private String userKeyFile; -} diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/RedisSslCredentialsConfiguration.java b/common/cache/src/main/java/org/thingsboard/server/cache/RedisSslCredentials.java similarity index 84% rename from common/cache/src/main/java/org/thingsboard/server/cache/RedisSslCredentialsConfiguration.java rename to common/cache/src/main/java/org/thingsboard/server/cache/RedisSslCredentials.java index 6bd46baf1b..aeac975d15 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/RedisSslCredentialsConfiguration.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/RedisSslCredentials.java @@ -22,12 +22,11 @@ import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties(prefix = "redis.ssl.credentials") @Data -public class RedisSslCredentialsConfiguration { +public class RedisSslCredentials { - private String type; + private String certFile; - private RedisKeystoreCredentialsConfig keystore; - - private RedisPemCredentialsConfig pem; + private String userCertFile; + private String userKeyFile; } diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisCacheConfiguration.java b/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisCacheConfiguration.java index d8805044f3..c3d3655883 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisCacheConfiguration.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/TBRedisCacheConfiguration.java @@ -42,11 +42,14 @@ import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; -import java.io.FileInputStream; +import java.io.IOException; import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.cert.CertPath; import java.security.cert.Certificate; +import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.time.Duration; @@ -100,13 +103,16 @@ public abstract class TBRedisCacheConfiguration { @Value("${redis.pool_config.blockWhenExhausted:true}") private boolean blockWhenExhausted; + @Value("${redis.ssl.enabled:false}") + private boolean sslEnabled; + @Bean public RedisConnectionFactory redisConnectionFactory() { return loadFactory(); } @Autowired - private RedisSslCredentialsConfiguration redisSslCredentials; + private RedisSslCredentials redisSslCredentials; protected abstract JedisConnectionFactory loadFactory(); @@ -176,57 +182,35 @@ public abstract class TBRedisCacheConfiguration { sslContext.init(keyManagerFactory == null ? null : keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); return sslContext.getSocketFactory(); } catch (Exception e) { - throw new RuntimeException(e); + throw new RuntimeException("Creating TLS factory failed!", e); } } private TrustManagerFactory createAndInitTrustManagerFactory() throws Exception { - String type = redisSslCredentials.getType(); - if ("pem".equals(type)) { - RedisPemCredentialsConfig pemCredentials = redisSslCredentials.getPem(); - List caCerts = SslUtil.readCertFileByPath(pemCredentials.getCertFile()); - + List caCerts = SslUtil.readCertFileByPath(redisSslCredentials.getCertFile()); KeyStore caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); caKeyStore.load(null, null); for (X509Certificate caCert : caCerts) { caKeyStore.setCertificateEntry("redis-caCert-cert-" + caCert.getSubjectX500Principal().getName(), caCert); } - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(caKeyStore); return trustManagerFactory; - } else if ("keystore".equals(type)) { - RedisKeystoreCredentialsConfig keystore = redisSslCredentials.getKeystore(); - KeyStore trustStore = KeyStore.getInstance(keystore.getKeystoreType()); - trustStore.load(new FileInputStream(keystore.getTruststoreLocation()), keystore.getTruststorePassword().toCharArray()); - - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); - trustManagerFactory.init(trustStore); - return trustManagerFactory; - } else { - throw new RuntimeException(type + ": Invalid SSL credentials configuration. None of the PEM or KEYSTORE configurations can be used!"); - } } private KeyManagerFactory createAndInitKeyManagerFactory() throws Exception { - String type = redisSslCredentials.getType(); - if ("pem".equals(type)) { - RedisPemCredentialsConfig pemCredentials = redisSslCredentials.getPem(); - return getKeyManagerFactory(pemCredentials); - } else if ("keystore".equals(type)) { - RedisKeystoreCredentialsConfig keystore = redisSslCredentials.getKeystore(); - return getKeyManagerFactory(keystore); - } else { - throw new RuntimeException(type + ": Invalid SSL credentials configuration. None of the PEM or KEYSTORE configurations can be used!"); - } + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(loadKeyStore(), null); + return kmf; } - private KeyManagerFactory getKeyManagerFactory(RedisPemCredentialsConfig pemCredentials) throws Exception { - if (pemCredentials.getUserCertFile().isBlank() || pemCredentials.getUserKeyFile().isBlank()) { + private KeyStore loadKeyStore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { + if (redisSslCredentials.getUserCertFile().isBlank() || redisSslCredentials.getUserKeyFile().isBlank()) { return null; } - List certificates = SslUtil.readCertFileByPath(pemCredentials.getCertFile()); - PrivateKey privateKey = SslUtil.readPrivateKeyByFilePath(pemCredentials.getUserKeyFile(), null); + List certificates = SslUtil.readCertFileByPath(redisSslCredentials.getCertFile()); + PrivateKey privateKey = SslUtil.readPrivateKeyByFilePath(redisSslCredentials.getUserKeyFile(), null); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); @@ -242,21 +226,6 @@ public abstract class TBRedisCacheConfiguration { Certificate[] x509Certificates = path.toArray(new Certificate[0]); keyStore.setKeyEntry("redis-private-key", privateKey, null, x509Certificates); } - - KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX"); - kmf.init(keyStore, null); - return kmf; - } - - private KeyManagerFactory getKeyManagerFactory(RedisKeystoreCredentialsConfig keystore) throws Exception { - if (keystore.getKeystoreLocation().isBlank() || keystore.getKeystoreLocation().isBlank()) { - return null; - } - KeyStore keyStore = KeyStore.getInstance(keystore.getKeystoreType()); - keyStore.load(new FileInputStream(keystore.getKeystoreLocation()), keystore.getKeystorePassword().toCharArray()); - - KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX"); - kmf.init(keyStore, keystore.getKeystorePassword().toCharArray()); - return kmf; + return keyStore; } } diff --git a/common/util/src/main/java/org/thingsboard/common/util/SslUtil.java b/common/util/src/main/java/org/thingsboard/common/util/SslUtil.java index e520e946ec..a62870ea9b 100644 --- a/common/util/src/main/java/org/thingsboard/common/util/SslUtil.java +++ b/common/util/src/main/java/org/thingsboard/common/util/SslUtil.java @@ -129,4 +129,5 @@ public class SslUtil { } return privateKey; } + } diff --git a/msa/black-box-tests/README.md b/msa/black-box-tests/README.md index 340f0d0eb8..31277e2a55 100644 --- a/msa/black-box-tests/README.md +++ b/msa/black-box-tests/README.md @@ -22,6 +22,10 @@ As result, in REPOSITORY column, next images should be present: mvn clean install -DblackBoxTests.skip=false +- Run the black box tests (without ui tests) in the [msa/black-box-tests](../black-box-tests) directory with Redis standalone with TLS: + + mvn clean install -DblackBoxTests.skip=false -DblackBoxTests.redisSsl=true + - Run the black box tests in the [msa/black-box-tests](../black-box-tests) directory with Redis cluster: mvn clean install -DblackBoxTests.skip=false -DblackBoxTests.redisCluster=true diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index 78ca89851d..3934acfb87 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -97,32 +97,14 @@ redis: ssl: # Enable/disable secure connection enabled: "${TB_REDIS_SSL_ENABLED:false}" - # Server SSL credentials + # Server SSL credentials (only PEM format is supported) credentials: - # Server credentials type (pem - pem certificate file; keystore - java keystore) - type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" - # PEM server credentials - pem: - # Path redis server (CA) certificate - cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client - user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. - user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" - # Keystore server credentials - keystore: - # Type of the trust store (JKS or PKCS12) - truststore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the trust store file - truststore_location: "${TB_REDIS_SSL_TRUSTSTORE_LOCATION:}" - # The password of trust store file if specified - truststore_password: "${TB_REDIS_SSL_TRUSTSTORE_PASSWORD:}" - # Type of the key store (JKS or PKCS12) - keystore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the key store file. This is optional for the client and can be used for two-way authentication for the client - keystore_location: "${TB_REDIS_SSL_KEYSTORE_LOCATION:}" - # The store password for the key store file. This is optional for the client and only needed if ‘ssl.keystore.location’ is configured. Key store password is not supported for PEM format - keystore_password: "${TB_REDIS_SSL_KEYSTORE_PASSWORD:}" + # Path redis server (CA) certificate + cert_file: "${TB_REDIS_SSL_PEM_CERT:}" + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client + user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" + # Path to user private key file. This is optional for the client and only needed if ‘user_cert_file’ is configured. + user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # pool config pool_config: # Maximum number of connections that can be allocated by the connection pool diff --git a/transport/http/src/main/resources/tb-http-transport.yml b/transport/http/src/main/resources/tb-http-transport.yml index 04a9c9417f..556c004bf8 100644 --- a/transport/http/src/main/resources/tb-http-transport.yml +++ b/transport/http/src/main/resources/tb-http-transport.yml @@ -130,32 +130,14 @@ redis: ssl: # Enable/disable secure connection enabled: "${TB_REDIS_SSL_ENABLED:false}" - # Server SSL credentials + # Server SSL credentials (only PEM format is supported) credentials: - # Server credentials type (pem - pem certificate file; keystore - java keystore) - type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" - # PEM server credentials - pem: - # Path redis server (CA) certificate - cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client - user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. - user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" - # Keystore server credentials - keystore: - # Type of the trust store (JKS or PKCS12) - truststore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the trust store file - truststore_location: "${TB_REDIS_SSL_TRUSTSTORE_LOCATION:}" - # The password of trust store file if specified - truststore_password: "${TB_REDIS_SSL_TRUSTSTORE_PASSWORD:}" - # Type of the key store (JKS or PKCS12) - keystore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the key store file. This is optional for the client and can be used for two-way authentication for the client - keystore_location: "${TB_REDIS_SSL_KEYSTORE_LOCATION:}" - # The store password for the key store file. This is optional for the client and only needed if ‘ssl.keystore.location’ is configured. Key store password is not supported for PEM format - keystore_password: "${TB_REDIS_SSL_KEYSTORE_PASSWORD:}" + # Path redis server (CA) certificate + cert_file: "${TB_REDIS_SSL_PEM_CERT:}" + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client + user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" + # Path to user private key file. This is optional for the client and only needed if ‘user_cert_file’ is configured. + user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # pool config pool_config: # Maximum number of connections that can be allocated by the connection pool diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index c079f690ed..6d7257d7f9 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -97,32 +97,14 @@ redis: ssl: # Enable/disable secure connection enabled: "${TB_REDIS_SSL_ENABLED:false}" - # Server SSL credentials + # Server SSL credentials (only PEM format is supported) credentials: - # Server credentials type (pem - pem certificate file; keystore - java keystore) - type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" - # PEM server credentials - pem: - # Path redis server (CA) certificate - cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client - user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. - user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" - # Keystore server credentials - keystore: - # Type of the trust store (JKS or PKCS12) - truststore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the trust store file - truststore_location: "${TB_REDIS_SSL_TRUSTSTORE_LOCATION:}" - # The password of trust store file if specified - truststore_password: "${TB_REDIS_SSL_TRUSTSTORE_PASSWORD:}" - # Type of the key store (JKS or PKCS12) - keystore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the key store file. This is optional for the client and can be used for two-way authentication for the client - keystore_location: "${TB_REDIS_SSL_KEYSTORE_LOCATION:}" - # The store password for the key store file. This is optional for the client and only needed if ‘ssl.keystore.location’ is configured. Key store password is not supported for PEM format - keystore_password: "${TB_REDIS_SSL_KEYSTORE_PASSWORD:}" + # Path redis server (CA) certificate + cert_file: "${TB_REDIS_SSL_PEM_CERT:}" + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client + user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" + # Path to user private key file. This is optional for the client and only needed if ‘user_cert_file’ is configured. + user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # pool config pool_config: # Maximum number of connections that can be allocated by the connection pool diff --git a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml index 430b5bfed5..41d96ff9d7 100644 --- a/transport/mqtt/src/main/resources/tb-mqtt-transport.yml +++ b/transport/mqtt/src/main/resources/tb-mqtt-transport.yml @@ -98,32 +98,14 @@ redis: ssl: # Enable/disable secure connection enabled: "${TB_REDIS_SSL_ENABLED:false}" - # Server SSL credentials + # Server SSL credentials (only PEM format is supported) credentials: - # Server credentials type (pem - pem certificate file; keystore - java keystore) - type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" - # PEM server credentials - pem: - # Path redis server (CA) certificate - cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client - user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. - user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" - # Keystore server credentials - keystore: - # Type of the trust store (JKS or PKCS12) - truststore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the trust store file - truststore_location: "${TB_REDIS_SSL_TRUSTSTORE_LOCATION:}" - # The password of trust store file if specified - truststore_password: "${TB_REDIS_SSL_TRUSTSTORE_PASSWORD:}" - # Type of the key store (JKS or PKCS12) - keystore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the key store file. This is optional for the client and can be used for two-way authentication for the client - keystore_location: "${TB_REDIS_SSL_KEYSTORE_LOCATION:}" - # The store password for the key store file. This is optional for the client and only needed if ‘ssl.keystore.location’ is configured. Key store password is not supported for PEM format - keystore_password: "${TB_REDIS_SSL_KEYSTORE_PASSWORD:}" + # Path redis server (CA) certificate + cert_file: "${TB_REDIS_SSL_PEM_CERT:}" + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client + user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" + # Path to user private key file. This is optional for the client and only needed if ‘user_cert_file’ is configured. + user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # pool config pool_config: # Maximum number of connections that can be allocated by the connection pool diff --git a/transport/snmp/src/main/resources/tb-snmp-transport.yml b/transport/snmp/src/main/resources/tb-snmp-transport.yml index 68b69bb03a..971237efe0 100644 --- a/transport/snmp/src/main/resources/tb-snmp-transport.yml +++ b/transport/snmp/src/main/resources/tb-snmp-transport.yml @@ -97,32 +97,14 @@ redis: ssl: # Enable/disable secure connection enabled: "${TB_REDIS_SSL_ENABLED:false}" - # Server SSL credentials + # Server SSL credentials (only PEM format is supported) credentials: - # Server credentials type (pem - pem certificate file; keystore - java keystore) - type: "${TB_REDIS_SSL_CREDENTIALS_TYPE:pem}" - # PEM server credentials - pem: - # Path redis server (CA) certificate - cert_file: "${TB_REDIS_SSL_PEM_CERT:}" - # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client - user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" - # Path to user private key file. This is optional for the client and only needed if ‘ssl.pem.user_cert_file’ is configured. - user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" - # Keystore server credentials - keystore: - # Type of the trust store (JKS or PKCS12) - truststore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the trust store file - truststore_location: "${TB_REDIS_SSL_TRUSTSTORE_LOCATION:}" - # The password of trust store file if specified - truststore_password: "${TB_REDIS_SSL_TRUSTSTORE_PASSWORD:}" - # Type of the key store (JKS or PKCS12) - keystore_type: "${TB_REDIS_SSL_KEY_STORE_TYPE:JKS}" - # The location of the key store file. This is optional for the client and can be used for two-way authentication for the client - keystore_location: "${TB_REDIS_SSL_KEYSTORE_LOCATION:}" - # The store password for the key store file. This is optional for the client and only needed if ‘ssl.keystore.location’ is configured. Key store password is not supported for PEM format - keystore_password: "${TB_REDIS_SSL_KEYSTORE_PASSWORD:}" + # Path redis server (CA) certificate + cert_file: "${TB_REDIS_SSL_PEM_CERT:}" + # Path to user certificate file. This is optional for the client and can be used for two-way authentication for the client + user_cert_file: "${TB_REDIS_SSL_PEM_KEY:}" + # Path to user private key file. This is optional for the client and only needed if ‘user_cert_file’ is configured. + user_key_file: "${TB_REDIS_SSL_PEM_KEY_PASSWORD:}" # pool config pool_config: # Maximum number of connections that can be allocated by the connection pool From c7dd55925ab587b0b188158f4f6f8af54a697401 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 7 Feb 2024 17:28:14 +0200 Subject: [PATCH 196/397] Mobile notifications: additionalConfig and Firebase notification data --- .../channels/MobileAppNotificationChannel.java | 18 +++++++++++++++++- .../provider/DefaultFirebaseService.java | 6 ++++-- .../notification/NotificationApiTest.java | 18 ++++++++++++------ ...eAppDeliveryMethodNotificationTemplate.java | 3 +++ .../api/notification/FirebaseService.java | 4 +++- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java index a1de832d14..3f2fcd40f5 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java @@ -20,10 +20,12 @@ import com.google.firebase.messaging.MessagingErrorCode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.notification.FirebaseService; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; +import org.thingsboard.server.common.data.notification.info.NotificationInfo; import org.thingsboard.server.common.data.notification.settings.MobileAppNotificationDeliveryMethodConfig; import org.thingsboard.server.common.data.notification.settings.NotificationSettings; import org.thingsboard.server.common.data.notification.template.MobileAppDeliveryMethodNotificationTemplate; @@ -31,7 +33,10 @@ import org.thingsboard.server.dao.notification.NotificationSettingsService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.service.notification.NotificationProcessingContext; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; +import java.util.Optional; import java.util.Set; @Component @@ -53,9 +58,20 @@ public class MobileAppNotificationChannel implements NotificationChannel validTokens = new HashSet<>(mobileSessions.keySet()); + + String subject = processedTemplate.getSubject(); + String body = processedTemplate.getBody(); + Map data = Optional.ofNullable(processedTemplate.getAdditionalConfig()) + .map(JacksonUtil::toFlatMap).orElseGet(HashMap::new); + Optional.ofNullable(ctx.getRequest().getInfo()) + .map(NotificationInfo::getStateEntityId) + .ifPresent(stateEntityId -> { + data.put("stateEntityId", stateEntityId.getId().toString()); + data.put("stateEntityType", stateEntityId.getEntityType().name()); + }); for (String token : mobileSessions.keySet()) { try { - firebaseService.sendMessage(ctx.getTenantId(), credentials, token, processedTemplate.getSubject(), processedTemplate.getBody()); + firebaseService.sendMessage(ctx.getTenantId(), credentials, token, subject, body, data); } catch (FirebaseMessagingException e) { MessagingErrorCode errorCode = e.getMessagingErrorCode(); if (errorCode == MessagingErrorCode.UNREGISTERED || errorCode == MessagingErrorCode.INVALID_ARGUMENT) { diff --git a/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java b/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java index b85d567c3b..a1a02d52f1 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java @@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.id.TenantId; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Map; import java.util.concurrent.TimeUnit; @Service @@ -51,7 +52,7 @@ public class DefaultFirebaseService implements FirebaseService { .build(); @Override - public void sendMessage(TenantId tenantId, String credentials, String fcmToken, String title, String body) throws FirebaseMessagingException { + public void sendMessage(TenantId tenantId, String credentials, String fcmToken, String title, String body, Map data) throws FirebaseMessagingException { FirebaseContext firebaseContext = contexts.asMap().compute(tenantId.toString(), (key, context) -> { if (context == null) { return new FirebaseContext(key, credentials); @@ -62,6 +63,7 @@ public class DefaultFirebaseService implements FirebaseService { }); Message message = Message.builder() + .setToken(fcmToken) .setNotification(Notification.builder() .setTitle(title) .setBody(body) @@ -69,7 +71,7 @@ public class DefaultFirebaseService implements FirebaseService { .setAndroidConfig(AndroidConfig.builder() .setPriority(AndroidConfig.Priority.HIGH) .build()) - .setToken(fcmToken) + .putAllData(data) .build(); firebaseContext.getMessaging().send(message); log.trace("[{}] Sent message for FCM token {}", tenantId, fcmToken); diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java index d5a089dc82..2d93573a25 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.ResultActions; import org.springframework.web.client.RestTemplate; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.NotificationCenter; import org.thingsboard.rule.engine.api.notification.FirebaseService; import org.thingsboard.server.common.data.EntityType; @@ -66,6 +67,7 @@ import org.thingsboard.server.common.data.notification.template.DeliveryMethodNo import org.thingsboard.server.common.data.notification.template.EmailDeliveryMethodNotificationTemplate; import org.thingsboard.server.common.data.notification.template.MicrosoftTeamsDeliveryMethodNotificationTemplate; import org.thingsboard.server.common.data.notification.template.MicrosoftTeamsDeliveryMethodNotificationTemplate.Button.LinkType; +import org.thingsboard.server.common.data.notification.template.MobileAppDeliveryMethodNotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplate; import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig; import org.thingsboard.server.common.data.notification.template.SlackDeliveryMethodNotificationTemplate; @@ -76,7 +78,6 @@ import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.notification.DefaultNotifications; import org.thingsboard.server.dao.notification.NotificationDao; import org.thingsboard.server.dao.service.DaoSqlTest; -import org.thingsboard.server.service.executors.DbCallbackExecutorService; import org.thingsboard.server.service.notification.channels.MicrosoftTeamsNotificationChannel; import org.thingsboard.server.service.ws.notification.cmd.UnreadNotificationsUpdate; @@ -92,6 +93,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.InstanceOfAssertFactories.type; import static org.awaitility.Awaitility.await; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doThrow; @@ -739,6 +742,9 @@ public class NotificationApiTest extends AbstractNotificationApiTest { loginTenantAdmin(); NotificationTarget target = createNotificationTarget(new AllUsersFilter()); NotificationTemplate template = createNotificationTemplate(NotificationType.GENERAL, "Title", "Message", NotificationDeliveryMethod.MOBILE_APP); + ((MobileAppDeliveryMethodNotificationTemplate) template.getConfiguration().getDeliveryMethodsTemplates().get(NotificationDeliveryMethod.MOBILE_APP)) + .setAdditionalConfig(JacksonUtil.newObjectNode().set("test", JacksonUtil.newObjectNode().put("test", "test"))); + saveNotificationTemplate(template); NotificationRequest request = submitNotificationRequest(List.of(target.getId()), template.getId(), 0); NotificationRequestStats stats = awaitNotificationRequest(request.getId()); @@ -747,11 +753,11 @@ public class NotificationApiTest extends AbstractNotificationApiTest { .contains("doesn't use the mobile app"); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("tenantFcmToken1"), eq("Title"), eq("Message")); + eq("tenantFcmToken1"), eq("Title"), eq("Message"), argThat(data -> "test".equals(data.get("test.test")))); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("tenantFcmToken2"), eq("Title"), eq("Message")); + eq("tenantFcmToken2"), eq("Title"), eq("Message"), argThat(data -> "test".equals(data.get("test.test")))); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("customerFcmToken"), eq("Title"), eq("Message")); + eq("customerFcmToken"), eq("Title"), eq("Message"), argThat(data -> "test".equals(data.get("test.test")))); verifyNoMoreInteractions(firebaseService); clearInvocations(firebaseService); @@ -759,9 +765,9 @@ public class NotificationApiTest extends AbstractNotificationApiTest { request = submitNotificationRequest(List.of(target.getId()), template.getId(), 0); awaitNotificationRequest(request.getId()); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("tenantFcmToken1"), eq("Title"), eq("Message")); + eq("tenantFcmToken1"), eq("Title"), eq("Message"), anyMap()); verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), - eq("customerFcmToken"), eq("Title"), eq("Message")); + eq("customerFcmToken"), eq("Title"), eq("Message"), anyMap()); verifyNoMoreInteractions(firebaseService); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileAppDeliveryMethodNotificationTemplate.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileAppDeliveryMethodNotificationTemplate.java index f621eee832..96e8b80453 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileAppDeliveryMethodNotificationTemplate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/template/MobileAppDeliveryMethodNotificationTemplate.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.common.data.notification.template; +import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -32,6 +33,7 @@ public class MobileAppDeliveryMethodNotificationTemplate extends DeliveryMethodN @NotEmpty private String subject; + private JsonNode additionalConfig; private final List templatableValues = List.of( TemplatableValue.of(this::getBody, this::setBody), @@ -41,6 +43,7 @@ public class MobileAppDeliveryMethodNotificationTemplate extends DeliveryMethodN public MobileAppDeliveryMethodNotificationTemplate(MobileAppDeliveryMethodNotificationTemplate other) { super(other); this.subject = other.subject; + this.additionalConfig = other.additionalConfig; } @Override diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/notification/FirebaseService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/notification/FirebaseService.java index 96128c7410..28aa4c96af 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/notification/FirebaseService.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/notification/FirebaseService.java @@ -17,8 +17,10 @@ package org.thingsboard.rule.engine.api.notification; import org.thingsboard.server.common.data.id.TenantId; +import java.util.Map; + public interface FirebaseService { - void sendMessage(TenantId tenantId, String credentials, String fcmToken, String title, String body) throws Exception; + void sendMessage(TenantId tenantId, String credentials, String fcmToken, String title, String body, Map data) throws Exception; } From ba7605cb85dee4b1a9aba733c33fe456b6ebbcff Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 7 Feb 2024 17:50:47 +0200 Subject: [PATCH 197/397] UI: Redesign delivery mehod congiguration in notification --- .../pages/notification/notification.module.ts | 4 +- .../rule-notification-dialog.component.ts | 3 + .../sent/sent-error-dialog.component.html | 2 +- .../sent/sent-error-dialog.component.ts | 4 +- .../sent-notification-dialog.component.html | 348 +-------------- .../sent-notification-dialog.component.scss | 2 +- .../sent/sent-notification-dialog.componet.ts | 15 +- .../sent/sent-table-config.resolver.ts | 4 +- .../notification-settings.component.html | 2 +- .../notification-settings.component.ts | 4 +- ...tion-template-configuration.component.html | 398 ++++++++++++++++++ ...tion-template-configuration.component.scss | 66 +++ ...cation-template-configuration.component.ts | 312 ++++++++++++++ .../template/template-configuration.ts | 152 +------ ...emplate-notification-dialog.component.html | 341 +-------------- ...emplate-notification-dialog.component.scss | 25 +- .../template-notification-dialog.component.ts | 25 +- .../template-autocomplete.component.html | 2 +- .../template-autocomplete.component.ts | 4 +- ...ack-conversation-autocomplete.component.ts | 7 +- .../app/shared/models/notification.models.ts | 60 ++- .../assets/locale/locale.constant-en_US.json | 4 +- 22 files changed, 908 insertions(+), 876 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.html create mode 100644 ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.scss create mode 100644 ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.ts diff --git a/ui-ngx/src/app/modules/home/pages/notification/notification.module.ts b/ui-ngx/src/app/modules/home/pages/notification/notification.module.ts index 3d400341a8..5e29010035 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/notification.module.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/notification.module.ts @@ -39,6 +39,7 @@ import { NotificationSettingsComponent } from '@home/pages/notification/settings import { NotificationSettingFormComponent } from '@home/pages/notification/settings/notification-setting-form.component'; +import { NotificationTemplateConfigurationComponent } from '@home/pages/notification/template/notification-template-configuration.component'; @NgModule({ declarations: [ @@ -55,7 +56,8 @@ import { RuleNotificationDialogComponent, RuleTableHeaderComponent, NotificationSettingsComponent, - NotificationSettingFormComponent + NotificationSettingFormComponent, + NotificationTemplateConfigurationComponent ], imports: [ CommonModule, diff --git a/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts index 9604670757..c3cf4581e2 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.ts @@ -362,6 +362,9 @@ export class RuleNotificationDialogComponent extends changeStep($event: StepperSelectionEvent) { this.selectedIndex = $event.selectedIndex; + if ($event.previouslySelectedIndex > $event.selectedIndex) { + $event.previouslySelectedStep.interacted = false; + } } backStep() { diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.html index 2ba3814146..75042166d3 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.html @@ -26,7 +26,7 @@
    -
    {{ notificationDeliveryMethodTranslateMap.get(errorStat.key) | translate }}
    +
    {{ NotificationDeliveryMethodInfoMap.get(errorStat.key).name | translate }}
    + + + + + + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss new file mode 100644 index 0000000000..9d990c50a7 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss @@ -0,0 +1,181 @@ +/** + * 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. + */ + +$maxLegendWidth: 25%; +$maxLegendHeight: 35%; + +.tb-time-series-chart-panel { + width: 100%; + height: 100%; + position: relative; + display: flex; + flex-direction: column; + gap: 16px; + padding: 20px 24px 24px 24px; + > div:not(.tb-time-series-chart-overlay) { + z-index: 1; + } + .tb-time-series-chart-overlay { + position: absolute; + top: 12px; + left: 12px; + bottom: 12px; + right: 12px; + } + div.tb-widget-title { + padding: 0; + } + .tb-time-series-chart-content { + flex: 1; + min-width: 0; + min-height: 0; + display: flex; + flex-direction: column; + gap: 16px; + &.legend-top { + flex-direction: column-reverse; + } + &.legend-right { + flex-direction: row; + } + &.legend-left { + flex-direction: row-reverse; + } + .tb-time-series-chart-shape { + flex: 1; + min-width: 0; + min-height: 0; + display: flex; + align-items: center; + justify-content: center; + } + &.legend-right, &.legend-left { + .tb-time-series-chart-legend { + display: inline-grid; + grid-auto-flow: column; + grid-template-rows: repeat(auto-fit, minmax(16px, min-content)); + max-width: calc($maxLegendWidth - 8px); + height: fit-content; + max-height: 100%; + } + } + &.legend-top, &.legend-bottom { + .tb-time-series-chart-legend { + align-self: center; + &.tb-simple-legend { + justify-content: center; + } + &:not(.tb-simple-legend) { + width: 100%; + } + } + } + .tb-time-series-chart-legend { + display: flex; + align-items: flex-start; + align-self: stretch; + column-gap: 16px; + row-gap: 8px; + flex-wrap: wrap; + overflow: auto; + width: fit-content; + max-width: 100%; + max-height: calc($maxLegendHeight - 8px); + .tb-time-series-chart-legend-table { + border-spacing: 0; + table-layout: fixed; + &.vertical { + width: 100%; + table-layout: auto; + } + + thead th, tbody th { + position: sticky; + z-index: 1; + backdrop-filter: blur(5000px); + } + thead th { + top: 0; + &:first-child { + left: 0; + z-index: 2; + } + } + tbody th { + left: 0; + } + th, td { + &:not(:last-child) { + padding-right: 8px; + } + } + thead tr, tbody tr:not(:last-child) { + th, td { + padding-bottom: 8px; + } + } + .tb-time-series-chart-legend-item { + align-items: flex-end; + &.left { + align-items: flex-start; + } + } + } + .tb-time-series-chart-legend-item { + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + user-select: none; + .tb-time-series-chart-legend-item-label { + display: flex; + align-items: center; + gap: 4px; + color: #ccc; + white-space: nowrap; + cursor: pointer; + .tb-time-series-chart-legend-item-label-circle { + width: 8px; + height: 8px; + border-radius: 50%; + background-color: #ccc; + } + } + } + .tb-time-series-chart-legend-type-label { + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 16px; + color: rgba(0, 0, 0, 0.38); + white-space: nowrap; + text-align: left; + &.right { + text-align: right; + } + } + .tb-time-series-chart-legend-value { + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + color: rgba(0, 0, 0, 0.87); + white-space: nowrap; + text-align: right; + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts new file mode 100644 index 0000000000..560309b08b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts @@ -0,0 +1,163 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { + AfterViewInit, + ChangeDetectorRef, + Component, + ElementRef, + Input, + OnDestroy, + OnInit, + Renderer2, + TemplateRef, + ViewChild, + ViewEncapsulation +} from '@angular/core'; +import { timeSeriesChartKeyDefaultSettings, TimeSeriesChartKeySettings } from '@home/components/widget/lib/chart/time-series-chart.models'; +import { WidgetContext } from '@home/models/widget-component.models'; +import { Observable } from 'rxjs'; +import { backgroundStyle, ComponentStyle, overlayStyle, textStyle } from '@shared/models/widget-settings.models'; +import { ImagePipe } from '@shared/pipe/image.pipe'; +import { DomSanitizer } from '@angular/platform-browser'; +import { LegendConfig, LegendData, LegendKey, LegendPosition } from '@shared/models/widget.models'; +import { TbTimeSeriesChart } from '@home/components/widget/lib/chart/time-series-chart'; +import { + timeSeriesChartWidgetDefaultSettings, + TimeSeriesChartWidgetSettings +} from '@home/components/widget/lib/chart/time-series-chart-widget.models'; +import { mergeDeep } from '@core/utils'; + +@Component({ + selector: 'tb-time-series-chart-widget', + templateUrl: './time-series-chart-widget.component.html', + styleUrls: ['./time-series-chart-widget.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class TimeSeriesChartWidgetComponent implements OnInit, OnDestroy, AfterViewInit { + + @ViewChild('chartShape', {static: false}) + chartShape: ElementRef; + + settings: TimeSeriesChartWidgetSettings; + + @Input() + ctx: WidgetContext; + + @Input() + widgetTitlePanel: TemplateRef; + + horizontalLegendPosition = false; + + showLegend: boolean; + legendClass: string; + legendConfig: LegendConfig; + legendData: LegendData; + legendKeys: LegendKey[]; + + backgroundStyle$: Observable; + overlayStyle: ComponentStyle = {}; + + legendLabelStyle: ComponentStyle; + disabledLegendLabelStyle: ComponentStyle; + + displayLegendValues = false; + + private timeSeriesChart: TbTimeSeriesChart; + + constructor(private imagePipe: ImagePipe, + private sanitizer: DomSanitizer, + private renderer: Renderer2, + private cd: ChangeDetectorRef) { + } + + ngOnInit(): void { + this.ctx.$scope.timeSeriesChartWidget = this; + this.settings = {...timeSeriesChartWidgetDefaultSettings, ...this.ctx.settings}; + + this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); + this.overlayStyle = overlayStyle(this.settings.background.overlay); + + this.showLegend = this.settings.showLegend; + if (this.showLegend) { + this.legendData = this.ctx.defaultSubscription.legendData; + this.legendConfig = this.settings.legendConfig; + this.legendKeys = this.legendData.keys; + if (this.legendConfig.sortDataKeys) { + this.legendKeys = this.legendData.keys.sort((key1, key2) => key1.dataKey.label.localeCompare(key2.dataKey.label)); + } + this.legendKeys.forEach(legendKey => { + legendKey.dataKey.settings = mergeDeep({} as TimeSeriesChartKeySettings, + timeSeriesChartKeyDefaultSettings, legendKey.dataKey.settings); + legendKey.dataKey.hidden = legendKey.dataKey.settings.dataHiddenByDefault; + }); + this.legendKeys = this.legendKeys.filter(legendKey => legendKey.dataKey.settings.showInLegend); + if (!this.legendKeys.length) { + this.showLegend = false; + } + } + + if (this.showLegend) { + this.horizontalLegendPosition = [LegendPosition.left, LegendPosition.right].includes(this.legendConfig.position); + this.legendClass = `legend-${this.legendConfig.position}`; + this.legendLabelStyle = textStyle(this.settings.legendLabelFont); + this.disabledLegendLabelStyle = textStyle(this.settings.legendLabelFont); + this.legendLabelStyle.color = this.settings.legendLabelColor; + this.displayLegendValues = this.legendConfig.showMin || this.legendConfig.showMax || + this.legendConfig.showAvg || this.legendConfig.showTotal || this.legendConfig.showLatest; + } + } + + ngAfterViewInit() { + this.timeSeriesChart = new TbTimeSeriesChart(this.ctx, this.settings, this.chartShape.nativeElement, this.renderer); + } + + ngOnDestroy() { + if (this.timeSeriesChart) { + this.timeSeriesChart.destroy(); + } + } + + public onInit() { + const borderRadius = this.ctx.$widgetElement.css('borderRadius'); + this.overlayStyle = {...this.overlayStyle, ...{borderRadius}}; + this.cd.detectChanges(); + } + + public onDataUpdated() { + if (this.timeSeriesChart) { + this.timeSeriesChart.update(); + } + } + + public onLatestDataUpdated() { + if (this.timeSeriesChart) { + this.timeSeriesChart.latestUpdated(); + } + } + + public onLegendKeyEnter(legendKey: LegendKey) { + this.timeSeriesChart.keyEnter(legendKey.dataKey); + } + + public onLegendKeyLeave(legendKey: LegendKey) { + this.timeSeriesChart.keyLeave(legendKey.dataKey); + } + + public toggleLegendKey(legendKey: LegendKey) { + this.timeSeriesChart.toggleKey(legendKey.dataKey); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.models.ts new file mode 100644 index 0000000000..ccfca7c4d0 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.models.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 { timeSeriesChartDefaultSettings, TimeSeriesChartSettings } from '@home/components/widget/lib/chart/time-series-chart.models'; +import { BackgroundSettings, BackgroundType, Font } from '@shared/models/widget-settings.models'; +import { defaultLegendConfig, LegendConfig, LegendPosition, widgetType } from '@shared/models/widget.models'; +import { mergeDeep } from '@core/utils'; + +export interface TimeSeriesChartWidgetSettings extends TimeSeriesChartSettings { + showLegend: boolean; + legendLabelFont: Font; + legendLabelColor: string; + legendConfig: LegendConfig; + background: BackgroundSettings; +} + +export const timeSeriesChartWidgetDefaultSettings: TimeSeriesChartWidgetSettings = + mergeDeep({} as TimeSeriesChartWidgetSettings, timeSeriesChartDefaultSettings as TimeSeriesChartWidgetSettings, { + showLegend: true, + legendLabelFont: { + family: 'Roboto', + size: 12, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '16px' + }, + legendLabelColor: 'rgba(0, 0, 0, 0.76)', + legendConfig: {...defaultLegendConfig(widgetType.timeseries), position: LegendPosition.top}, + background: { + type: BackgroundType.color, + color: '#fff', + overlay: { + enabled: false, + color: 'rgba(255,255,255,0.72)', + blur: 3 + } + } + } as TimeSeriesChartWidgetSettings); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts new file mode 100644 index 0000000000..ef8b432e46 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -0,0 +1,873 @@ +/// +/// 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 { + ECharts, + EChartsOption, + EChartsSeriesItem, + EChartsTooltipTrigger, + EChartsTooltipWidgetSettings, + measureThresholdLabelOffset +} from '@home/components/widget/lib/chart/echarts-widget.models'; +import { ComponentStyle, Font, simpleDateFormat, textStyle } from '@shared/models/widget-settings.models'; +import { XAXisOption, YAXisOption } from 'echarts/types/dist/shared'; +import { CustomSeriesOption, LineSeriesOption } from 'echarts/charts'; +import { formatValue, isDefinedAndNotNull, parseFunction } from '@core/utils'; +import { LinearGradientObject } from 'zrender/lib/graphic/LinearGradient'; +import tinycolor from 'tinycolor2'; +import Axis2D from 'echarts/types/src/coord/cartesian/Axis2D'; +import { Interval } from '@shared/models/time/time.models'; +import { ValueAxisBaseOption } from 'echarts/types/src/coord/axisCommonTypes'; +import { SeriesLabelOption } from 'echarts/types/src/util/types'; +import { + BarRenderContext, + BarVisualSettings, + renderTimeSeriesBar +} from '@home/components/widget/lib/chart/time-series-chart-bar.models'; +import { DataKey } from '@shared/models/widget.models'; +import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; +import { TbColorScheme } from '@shared/models/color.models'; + +export enum PointLabelPosition { + top = 'top', + bottom = 'bottom' +} + +export enum AxisPosition { + left = 'left', + right = 'right', + top = 'top', + bottom = 'bottom' +} + +export enum TimeSeriesChartShape { + emptyCircle = 'emptyCircle', + circle = 'circle', + rect = 'rect', + roundRect = 'roundRect', + triangle = 'triangle', + diamond = 'diamond', + pin = 'pin', + arrow = 'arrow', + none = 'none' +} + +export enum TimeSeriesChartLineType { + solid = 'solid', + dashed = 'dashed', + dotted = 'dotted' +} + +export enum ThresholdLabelPosition { + start = 'start', + middle = 'middle', + end = 'end', + insideStart = 'insideStart', + insideStartTop = 'insideStartTop', + insideStartBottom = 'insideStartBottom', + insideMiddle = 'insideMiddle', + insideMiddleTop = 'insideMiddleTop', + insideMiddleBottom = 'insideMiddleBottom', + insideEnd = 'insideEnd', + insideEndTop = 'insideEndTop', + insideEndBottom = 'insideEndBottom' +} + +export interface TimeSeriesChartAxisSettings { + show: boolean; + position: AxisPosition; + label?: string; + labelFont?: Font; + labelColor?: string; + showLine: boolean; + lineColor: string; + showTicks: boolean; + ticksColor: string; + showTickLabels: boolean; + tickLabelFont: Font; + tickLabelColor: string; + showSplitLines: boolean; + splitLinesColor: string; +} + +export interface TimeSeriesChartYAxisSettings extends TimeSeriesChartAxisSettings { + min?: number | string; + max?: number | string; + intervalCalculator?: string; +} + +export enum TimeSeriesChartThresholdType { + constant = 'constant', + latestKey = 'latestKey', + entity = 'entity' +} + +export interface TimeSeriesChartThreshold { + type: TimeSeriesChartThresholdType; + value?: number; + latestKeyName?: string; + entityAlias?: string; + entityKeyType?: DataKeyType.attribute | DataKeyType.timeseries; + entityKey?: string; + units?: string; + decimals?: number; + lineWidth: number; + lineType: TimeSeriesChartLineType; + lineColor: string; + startSymbol: TimeSeriesChartShape; + startSymbolSize: number; + endSymbol: TimeSeriesChartShape; + endSymbolSize: number; + showLabel: boolean; + labelPosition: ThresholdLabelPosition; + labelFont: Font; + labelColor: string; +} + +const timeSeriesChartColorScheme: TbColorScheme = { + 'threshold.line': { + light: 'rgba(0, 0, 0, 0.76)', + dark: '#eee' + }, + 'threshold.label': { + light: 'rgba(0, 0, 0, 0.76)', + dark: '#eee' + }, + 'axis.line': { + light: 'rgba(0, 0, 0, 0.54)', + dark: '#B9B8CE' + }, + 'axis.label': { + light: 'rgba(0, 0, 0, 0.54)', + dark: '#B9B8CE' + }, + 'axis.ticks': { + light: 'rgba(0, 0, 0, 0.54)', + dark: '#B9B8CE' + }, + 'axis.tickLabel': { + light: 'rgba(0, 0, 0, 0.54)', + dark: '#B9B8CE' + }, + 'axis.splitLine': { + light: 'rgba(0, 0, 0, 0.12)', + dark: '#484753' + }, + 'series.pointLabel': { + light: 'rgba(0, 0, 0, 0.76)', + dark: '#eee' + } +}; + +export const timeSeriesChartThresholdDefaultSettings: TimeSeriesChartThreshold = { + type: TimeSeriesChartThresholdType.constant, + units: '', + decimals: 0, + lineWidth: 1, + lineType: TimeSeriesChartLineType.solid, + lineColor: timeSeriesChartColorScheme['threshold.line'].light, + startSymbol: TimeSeriesChartShape.none, + startSymbolSize: 5, + endSymbol: TimeSeriesChartShape.arrow, + endSymbolSize: 5, + showLabel: true, + labelPosition: ThresholdLabelPosition.end, + labelFont: { + family: 'Roboto', + size: 12, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '1' + }, + labelColor: timeSeriesChartColorScheme['threshold.label'].light +}; + +export interface TimeSeriesChartSettings extends EChartsTooltipWidgetSettings { + darkMode: boolean; + dataZoom: boolean; + stack: boolean; + thresholds: TimeSeriesChartThreshold[]; + xAxis: TimeSeriesChartAxisSettings; + yAxis: TimeSeriesChartYAxisSettings; +} + +export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { + darkMode: false, + dataZoom: true, + stack: false, + thresholds: [], + xAxis: { + show: true, + position: AxisPosition.bottom, + label: '', + labelFont: { + family: 'Roboto', + size: 12, + sizeUnit: 'px', + style: 'normal', + weight: '600', + lineHeight: '1' + }, + labelColor: timeSeriesChartColorScheme['axis.label'].light, + showLine: true, + lineColor: timeSeriesChartColorScheme['axis.line'].light, + showTicks: true, + ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, + showTickLabels: true, + tickLabelFont: { + family: 'Roboto', + size: 10, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '1' + }, + tickLabelColor: timeSeriesChartColorScheme['axis.tickLabel'].light, + showSplitLines: true, + splitLinesColor: timeSeriesChartColorScheme['axis.splitLine'].light + }, + yAxis: { + show: true, + position: AxisPosition.left, + label: '', + labelFont: { + family: 'Roboto', + size: 12, + sizeUnit: 'px', + style: 'normal', + weight: '600', + lineHeight: '1' + }, + labelColor: timeSeriesChartColorScheme['axis.label'].light, + showLine: true, + lineColor: timeSeriesChartColorScheme['axis.line'].light, + showTicks: true, + ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, + showTickLabels: true, + tickLabelFont: { + family: 'Roboto', + size: 12, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '1' + }, + tickLabelColor: timeSeriesChartColorScheme['axis.tickLabel'].light, + showSplitLines: true, + splitLinesColor: timeSeriesChartColorScheme['axis.splitLine'].light + }, + showTooltip: true, + tooltipTrigger: EChartsTooltipTrigger.axis, + tooltipValueFont: { + family: 'Roboto', + size: 12, + sizeUnit: 'px', + style: 'normal', + weight: '500', + lineHeight: '16px' + }, + tooltipValueColor: 'rgba(0, 0, 0, 0.76)', + tooltipShowDate: true, + tooltipDateInterval: true, + tooltipDateFormat: simpleDateFormat('dd MMM yyyy HH:mm:ss'), + tooltipDateFont: { + family: 'Roboto', + size: 11, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '16px' + }, + tooltipDateColor: 'rgba(0, 0, 0, 0.76)', + tooltipBackgroundColor: 'rgba(255, 255, 255, 0.76)', + tooltipBackgroundBlur: 4 +}; + +export enum SeriesFillType { + none = 'none', + opacity = 'opacity', + gradient = 'gradient' +} + +export interface SeriesFillSettings { + type: SeriesFillType; + opacity: number; + gradient: { + start: number; + end: number; + }; +} + +export interface LineSeriesSettings { + step: false | 'start' | 'end' | 'middle'; + smooth: boolean; + showLine: boolean; + lineWidth: number; + lineType: TimeSeriesChartLineType; + fillAreaSettings: SeriesFillSettings; + showPoints: boolean; + pointShape: TimeSeriesChartShape; + pointSize: number; +} + +export interface BarSeriesSettings { + showBorder: boolean; + borderWidth: number; + borderRadius: number; + backgroundSettings: SeriesFillSettings; +} + +export enum TimeSeriesChartSeriesType { + line = 'line', + bar = 'bar' +} + +export interface TimeSeriesChartKeySettings { + dataHiddenByDefault: boolean; + showInLegend: boolean; + showPointLabel: boolean; + pointLabelPosition: PointLabelPosition; + pointLabelFont: Font; + pointLabelColor: string; + type: TimeSeriesChartSeriesType; + lineSettings: LineSeriesSettings; + barSettings: BarSeriesSettings; +} + +export const timeSeriesChartKeyDefaultSettings: TimeSeriesChartKeySettings = { + showInLegend: true, + dataHiddenByDefault: false, + showPointLabel: false, + pointLabelPosition: PointLabelPosition.top, + pointLabelFont: { + family: 'Roboto', + size: 11, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '1' + }, + pointLabelColor: timeSeriesChartColorScheme['series.pointLabel'].light, + type: TimeSeriesChartSeriesType.line, + lineSettings: { + step: false, + smooth: false, + showLine: true, + lineWidth: 2, + lineType: TimeSeriesChartLineType.solid, + fillAreaSettings: { + type: SeriesFillType.none, + opacity: 0.4, + gradient: { + start: 100, + end: 0 + } + }, + showPoints: false, + pointShape: TimeSeriesChartShape.emptyCircle, + pointSize: 4 + }, + barSettings: { + showBorder: false, + borderWidth: 2, + borderRadius: 0, + backgroundSettings: { + type: SeriesFillType.none, + opacity: 0.4, + gradient: { + start: 100, + end: 0 + } + } + } +}; + +export interface TimeSeriesChartDataItem extends EChartsSeriesItem { + yAxisIndex: number; + option?: LineSeriesOption | CustomSeriesOption; + barRenderContext?: BarRenderContext; +} + +type TimeSeriesChartThresholdValue = number | string | (number | string)[]; + +export interface TimeSeriesChartThresholdItem { + id: string; + yAxisIndex: number; + latestDataKey?: DataKey; + units?: string; + decimals?: number; + value: TimeSeriesChartThresholdValue; + settings: TimeSeriesChartThreshold; + option?: LineSeriesOption; +} + +export interface TimeSeriesChartYAxis { + id: string; + units: string; + option: YAXisOption & ValueAxisBaseOption; + intervalCalculator?: (axis: Axis2D) => number; +} + +export const createTimeSeriesYAxis = (axisId: string, units: string, + decimals: number, settings: TimeSeriesChartYAxisSettings, + darkMode: boolean): TimeSeriesChartYAxis => { + const yAxisTickLabelStyle = createChartTextStyle(settings.tickLabelFont, + settings.tickLabelColor, darkMode, 'axis.tickLabel'); + const yAxisNameStyle = createChartTextStyle(settings.labelFont, + settings.labelColor, darkMode, 'axis.label'); + const yAxis: TimeSeriesChartYAxis = { + id: axisId, + units, + option: { + show: settings.show, + type: 'value', + position: settings.position, + id: axisId, + offset: 0, + alignTicks: true, + scale: true, + min: settings.min, + max: settings.max, + name: settings.label, + nameLocation: 'middle', + nameRotate: settings.position === AxisPosition.left ? 90 : -90, + nameTextStyle: { + color: yAxisNameStyle.color, + fontStyle: yAxisNameStyle.fontStyle, + fontWeight: yAxisNameStyle.fontWeight, + fontFamily: yAxisNameStyle.fontFamily, + fontSize: yAxisNameStyle.fontSize + }, + axisLine: { + show: settings.showLine, + onZero: false, + lineStyle: { + color: prepareChartThemeColor(settings.lineColor, darkMode, 'axis.line') + } + }, + axisTick: { + show: settings.showTicks, + lineStyle: { + color: prepareChartThemeColor(settings.ticksColor, darkMode, 'axis.ticks') + } + }, + axisLabel: { + show: settings.showTickLabels, + color: yAxisTickLabelStyle.color, + fontStyle: yAxisTickLabelStyle.fontStyle, + fontWeight: yAxisTickLabelStyle.fontWeight, + fontFamily: yAxisTickLabelStyle.fontFamily, + fontSize: yAxisTickLabelStyle.fontSize, + formatter: (value: any) => formatValue(value, decimals, units, false) + }, + splitLine: { + show: settings.showSplitLines, + lineStyle: { + color: prepareChartThemeColor(settings.splitLinesColor, darkMode, 'axis.splitLine') + } + } + } + }; + if (settings.intervalCalculator && settings.intervalCalculator.length) { + yAxis.intervalCalculator = parseFunction(settings.intervalCalculator, ['axis']); + } + return yAxis; +}; + +export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartAxisSettings, + min: number, max: number, darkMode: boolean): XAXisOption => { + const xAxisTickLabelStyle = createChartTextStyle(settings.tickLabelFont, + settings.tickLabelColor, darkMode, 'axis.tickLabel'); + const xAxisNameStyle = createChartTextStyle(settings.labelFont, + settings.labelColor, darkMode, 'axis.label'); + return { + show: settings.show, + type: 'time', + scale: true, + position: settings.position, + name: settings.label, + nameLocation: 'middle', + nameTextStyle: { + color: xAxisNameStyle.color, + fontStyle: xAxisNameStyle.fontStyle, + fontWeight: xAxisNameStyle.fontWeight, + fontFamily: xAxisNameStyle.fontFamily, + fontSize: xAxisNameStyle.fontSize + }, + axisTick: { + show: settings.showTicks, + lineStyle: { + color: prepareChartThemeColor(settings.ticksColor, darkMode, 'axis.ticks') + } + }, + axisLabel: { + show: settings.showTickLabels, + color: xAxisTickLabelStyle.color, + fontStyle: xAxisTickLabelStyle.fontStyle, + fontWeight: xAxisTickLabelStyle.fontWeight, + fontFamily: xAxisTickLabelStyle.fontFamily, + fontSize: xAxisTickLabelStyle.fontSize, + hideOverlap: true + }, + axisLine: { + show: settings.showLine, + onZero: false, + lineStyle: { + color: prepareChartThemeColor(settings.lineColor, darkMode, 'axis.line') + } + }, + splitLine: { + show: settings.showSplitLines, + lineStyle: { + color: prepareChartThemeColor(settings.splitLinesColor, darkMode, 'axis.splitLine') + } + }, + min, + max + }; +}; + +export const generateChartData = (dataItems: TimeSeriesChartDataItem[], + thresholdItems: TimeSeriesChartThresholdItem[], + timeInterval: Interval, + stack: boolean, + darkMode: boolean): Array => { + let series = generateChartSeries(dataItems, timeInterval, stack, darkMode); + if (thresholdItems.length) { + const thresholds = generateChartThresholds(thresholdItems, darkMode); + series = series.concat(thresholds); + } + return series; +}; + +export const calculateThresholdsOffset = (chart: ECharts, + thresholdItems: TimeSeriesChartThresholdItem[], + yAxisList: TimeSeriesChartYAxis[]): [number, number] => { + const result: [number, number] = [0, 0]; + for (const item of thresholdItems) { + const yAxis = yAxisList[item.yAxisIndex]; + const offset = measureThresholdLabelOffset(chart, yAxis.id, item.id, item.value); + result[0] = Math.max(result[0], offset[0]); + result[1] = Math.max(result[1], offset[1]); + } + return result; +}; + +export const parseThresholdData = (value: any): TimeSeriesChartThresholdValue => { + let thresholdValue: TimeSeriesChartThresholdValue; + if (Array.isArray(value)) { + thresholdValue = value; + } else { + try { + const parsedData = JSON.parse(value); + thresholdValue = Array.isArray(parsedData) ? parsedData : [parsedData]; + } catch (e) { + thresholdValue = [value]; + } + } + return thresholdValue; +}; + +const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[], darkMode: boolean): Array => { + const series: Array = []; + for (const item of thresholdItems) { + if (isDefinedAndNotNull(item.value)) { + let seriesOption = item.option; + if (!item.option) { + const thresholdLabelStyle = createChartTextStyle(item.settings.labelFont, + item.settings.labelColor, darkMode, 'threshold.label'); + seriesOption = { + type: 'line', + id: item.id, + dataGroupId: item.id, + yAxisIndex: item.yAxisIndex, + animation: true, + data: [], + tooltip: { + show: false + }, + markLine: { + animation: true, + symbol: [item.settings.startSymbol, item.settings.endSymbol], + symbolSize: [item.settings.startSymbolSize, item.settings.endSymbolSize], + lineStyle: { + width: item.settings.lineWidth, + color: prepareChartThemeColor(item.settings.lineColor, darkMode, 'threshold.line'), + type: item.settings.lineType + }, + label: { + show: item.settings.showLabel, + position: item.settings.labelPosition, + color: thresholdLabelStyle.color, + fontStyle: thresholdLabelStyle.fontStyle, + fontWeight: thresholdLabelStyle.fontWeight, + fontFamily: thresholdLabelStyle.fontFamily, + fontSize: thresholdLabelStyle.fontSize, + formatter: params => formatValue(params.value, item.decimals, + item.units, false) + }, + emphasis: { + disabled: true + } + } + }; + item.option = seriesOption; + } + seriesOption.markLine.data = []; + if (Array.isArray(item.value)) { + for (const val of item.value) { + seriesOption.markLine.data.push({ + yAxis: val + }); + } + } else { + seriesOption.markLine.data.push({ + yAxis: item.value + }); + } + series.push(seriesOption); + } + } + return series; +}; + +const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], + timeInterval: Interval, + stack: boolean, + darkMode: boolean): Array => { + const series: Array = []; + const enabledDataItems = dataItems.filter(d => d.enabled); + const barDataItems = enabledDataItems.filter(d => + d.dataKey.settings.type === TimeSeriesChartSeriesType.bar && d.data.length); + let barsCount = barDataItems.length; + const barGroups: number[] = []; + if (stack) { + barDataItems.forEach(item => { + if (barGroups.indexOf(item.yAxisIndex) === -1) { + barGroups.push(item.yAxisIndex); + } + }); + barsCount = barGroups.length; + } + for (const item of enabledDataItems) { + if (item.dataKey.settings.type === TimeSeriesChartSeriesType.bar) { + if (!item.barRenderContext) { + item.barRenderContext = {}; + } + item.barRenderContext.barsCount = barsCount; + item.barRenderContext.barIndex = stack ? barGroups.indexOf(item.yAxisIndex) : barDataItems.indexOf(item); + item.barRenderContext.timeInterval = timeInterval; + if (stack) { + const stackItems = enabledDataItems.filter(d => d.yAxisIndex === item.yAxisIndex); + item.barRenderContext.currentStackItems = stackItems; + item.barRenderContext.barStackIndex = stackItems.indexOf(item); + } + } + const seriesOption = createTimeSeriesChartSeries(item, stack, darkMode); + series.push(seriesOption); + } + return series; +}; + +export const updateDarkMode = (options: EChartsOption, settings: TimeSeriesChartSettings, + dataItems: TimeSeriesChartDataItem[], thresholdDataItems: TimeSeriesChartThresholdItem[], + darkMode: boolean): EChartsOption => { + options.darkMode = darkMode; + if (Array.isArray(options.yAxis)) { + for (const yAxis of options.yAxis) { + yAxis.nameTextStyle.color = prepareChartThemeColor(settings.yAxis.labelColor, darkMode, 'axis.label'); + yAxis.axisLabel.color = prepareChartThemeColor(settings.yAxis.tickLabelColor, darkMode, 'axis.tickLabel'); + yAxis.axisLine.lineStyle.color = prepareChartThemeColor(settings.yAxis.lineColor, darkMode, 'axis.line'); + yAxis.axisTick.lineStyle.color = prepareChartThemeColor(settings.yAxis.ticksColor, darkMode, 'axis.ticks'); + yAxis.splitLine.lineStyle.color = prepareChartThemeColor(settings.yAxis.splitLinesColor, darkMode, 'axis.splitLine'); + } + } + if (Array.isArray(options.xAxis)) { + for (const xAxis of options.xAxis) { + xAxis.nameTextStyle.color = prepareChartThemeColor(settings.xAxis.labelColor, darkMode, 'axis.label'); + xAxis.axisLabel.color = prepareChartThemeColor(settings.xAxis.tickLabelColor, darkMode, 'axis.tickLabel'); + xAxis.axisLine.lineStyle.color = prepareChartThemeColor(settings.xAxis.lineColor, darkMode, 'axis.line'); + xAxis.axisTick.lineStyle.color = prepareChartThemeColor(settings.xAxis.ticksColor, darkMode, 'axis.ticks'); + xAxis.splitLine.lineStyle.color = prepareChartThemeColor(settings.xAxis.splitLinesColor, darkMode, 'axis.splitLine'); + } + } + for (const item of dataItems) { + if (item.dataKey.settings.type === TimeSeriesChartSeriesType.line) { + if (item.option.label?.show) { + item.option.label.rich.value.color = prepareChartThemeColor(item.dataKey.settings.pointLabelColor, darkMode, 'series.pointLabel'); + } + if (Array.isArray(options.series)) { + const series = options.series.find(s => s.id === item.id); + if (series) { + if (series.label?.show) { + series.label.rich.value.color = prepareChartThemeColor(item.dataKey.settings.pointLabelColor, darkMode, 'series.pointLabel'); + } + } + } + } else { + if (item.barRenderContext?.labelOption?.show) { + item.barRenderContext.labelOption.rich.value.color = prepareChartThemeColor(item.dataKey.settings.pointLabelColor, + darkMode, 'series.pointLabel'); + } + } + } + for (const item of thresholdDataItems) { + if (Array.isArray(options.series)) { + const series = options.series.find(s => s.id === item.id); + if (series) { + series.markLine.lineStyle.color = prepareChartThemeColor(item.settings.lineColor, darkMode, 'threshold.line'); + if (series.markLine?.label?.show) { + series.markLine.label.color = prepareChartThemeColor(item.settings.labelColor, darkMode, 'threshold.label'); + } + } + } + } + return options; +}; + +const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem, + stack: boolean, + darkMode: boolean): LineSeriesOption | CustomSeriesOption => { + let seriesOption = item.option; + if (!seriesOption) { + const dataKey = item.dataKey; + const settings: TimeSeriesChartKeySettings = dataKey.settings; + const seriesColor = item.dataKey.color; + let pointLabelStyle: ComponentStyle = {}; + if (settings.showPointLabel) { + pointLabelStyle = createChartTextStyle(settings.pointLabelFont, settings.pointLabelColor, darkMode, 'series.pointLabel'); + } + const label: SeriesLabelOption = { + show: settings.showPointLabel, + position: settings.pointLabelPosition, + formatter: (params): string => { + const value = formatValue(params.value[1], item.decimals, item.units, false); + return `{value|${value}}`; + }, + rich: { + value: pointLabelStyle + } + }; + seriesOption = { + id: item.id, + dataGroupId: item.id, + yAxisIndex: item.yAxisIndex, + name: item.dataKey.label, + color: seriesColor, + stack: stack ? (item.yAxisIndex + '') : undefined, + stackStrategy: 'all', + emphasis: { + focus: 'series' + }, + animation: true, + dimensions: [ + {name: 'intervalStart', type: 'number'}, + {name: 'intervalEnd', type: 'number'} + ], + encode: { + intervalStart: 2, + intervalEnd: 3 + } + }; + item.option = seriesOption; + if (settings.type === TimeSeriesChartSeriesType.line) { + const lineSettings = settings.lineSettings; + const lineSeriesOption = seriesOption as LineSeriesOption; + lineSeriesOption.type = 'line'; + lineSeriesOption.label = label; + lineSeriesOption.step = lineSettings.step; + lineSeriesOption.smooth = lineSettings.smooth; + lineSeriesOption.lineStyle = { + width: lineSettings.showLine ? lineSettings.lineWidth : 0, + type: lineSettings.lineType + }; + if (lineSettings.fillAreaSettings.type !== SeriesFillType.none) { + lineSeriesOption.areaStyle = {}; + if (lineSettings.fillAreaSettings.type === SeriesFillType.opacity) { + lineSeriesOption.areaStyle.opacity = lineSettings.fillAreaSettings.opacity; + } else { + lineSeriesOption.areaStyle.opacity = 1; + lineSeriesOption.areaStyle.color = createLinearOpacityGradient(seriesColor, lineSettings.fillAreaSettings.gradient); + } + } + lineSeriesOption.showSymbol = lineSettings.showPoints; + lineSeriesOption.symbol = lineSettings.pointShape; + lineSeriesOption.symbolSize = lineSettings.pointSize; + } else { + const barSettings = settings.barSettings; + const barSeriesOption = (seriesOption as any) as CustomSeriesOption; + barSeriesOption.type = 'custom'; + const barVisualSettings: BarVisualSettings = { + color: seriesColor, + borderColor: seriesColor, + borderWidth: barSettings.showBorder ? barSettings.borderWidth : 0, + borderRadius: barSettings.borderRadius + }; + if (barSettings.backgroundSettings.type === SeriesFillType.none) { + barVisualSettings.color = seriesColor; + } else if (barSettings.backgroundSettings.type === SeriesFillType.opacity) { + barVisualSettings.color = tinycolor(seriesColor).setAlpha(barSettings.backgroundSettings.opacity).toRgbString(); + } else { + barVisualSettings.color = createLinearOpacityGradient(seriesColor, barSettings.backgroundSettings.gradient); + } + item.barRenderContext.visualSettings = barVisualSettings; + item.barRenderContext.labelOption = label; + barSeriesOption.renderItem = (params, api) => + renderTimeSeriesBar(params, api, item.barRenderContext); + } + } + seriesOption.data = item.data; + return seriesOption; +}; + +const createChartTextStyle = (font: Font, color: string, darkMode: boolean, colorKey?: string): ComponentStyle => { + const style = textStyle(font); + delete style.lineHeight; + style.fontSize = font.size; + style.color = prepareChartThemeColor(color, darkMode, colorKey); + return style; +}; + +const createLinearOpacityGradient = (color: string, gradient: {start: number; end: number}): LinearGradientObject => ({ + type: 'linear', + x: 0, + y: 0, + x2: 0, + y2: 1, + colorStops: [{ + offset: 0, color: tinycolor(color).setAlpha(gradient.start / 100).toRgbString() // color at 0% + }, { + offset: 1, color: tinycolor(color).setAlpha(gradient.end / 100).toRgbString() // color at 100% + }], + global: false +}); + +const prepareChartThemeColor = (color: string, darkMode: boolean, colorKey?: string): string => { + if (darkMode) { + let colorInstance = tinycolor(color); + if (colorInstance.isDark()) { + if (colorKey && timeSeriesChartColorScheme[colorKey]) { + return timeSeriesChartColorScheme[colorKey].dark; + } else { + const rgb = colorInstance.toRgb(); + colorInstance = tinycolor({r: 255 - rgb.r, g: 255 - rgb.g, b: 255 - rgb.b, a: rgb.a}); + return colorInstance.toRgbString(); + } + } + } + return color; +}; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts new file mode 100644 index 0000000000..48c2dfaf57 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -0,0 +1,642 @@ +/// +/// 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 { WidgetContext } from '@home/models/widget-component.models'; +import { + AxisPosition, + calculateThresholdsOffset, + createTimeSeriesXAxisOption, + createTimeSeriesYAxis, + generateChartData, + TimeSeriesChartDataItem, + timeSeriesChartDefaultSettings, + timeSeriesChartKeyDefaultSettings, + TimeSeriesChartKeySettings, + TimeSeriesChartSeriesType, + TimeSeriesChartSettings, + TimeSeriesChartThresholdItem, + TimeSeriesChartThresholdType, + TimeSeriesChartYAxis, + parseThresholdData, + PointLabelPosition, + updateDarkMode +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { ResizeObserver } from '@juggle/resize-observer'; +import { + calculateXAxisHeight, + calculateYAxisWidth, + ECharts, + echartsModule, + EChartsOption, + echartsTooltipFormatter, + EChartsTooltipTrigger, + getAxisExtent, + getYAxis, + measureXAxisNameHeight, + measureYAxisNameWidth, + toNamedData +} from '@home/components/widget/lib/chart/echarts-widget.models'; +import { DateFormatProcessor } from '@shared/models/widget-settings.models'; +import { isDefinedAndNotNull, mergeDeep } from '@core/utils'; +import { DataKey, Datasource, DatasourceType, widgetType } from '@shared/models/widget.models'; +import * as echarts from 'echarts/core'; +import { CallbackDataParams } from 'echarts/types/dist/shared'; +import { Renderer2 } from '@angular/core'; +import { CustomSeriesOption, LineSeriesOption } from 'echarts/charts'; +import { BehaviorSubject } from 'rxjs'; +import { AggregationType } from '@shared/models/time/time.models'; +import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; +import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; + +export class TbTimeSeriesChart { + + private readonly shapeResize$: ResizeObserver; + + private dataItems: TimeSeriesChartDataItem[] = []; + private thresholdItems: TimeSeriesChartThresholdItem[] = []; + private yAxisList: TimeSeriesChartYAxis[] = []; + + private timeSeriesChart: ECharts; + private timeSeriesChartOptions: EChartsOption; + + private readonly tooltipDateFormat: DateFormatProcessor; + + private yMinSubject = new BehaviorSubject(-1); + private yMaxSubject = new BehaviorSubject(1); + + private darkMode = false; + + private messageChannel = new BroadcastChannel('tbMessageChannel'); + + private topPointLabels = false; + + private componentIndexCounter = 0; + + private highlightedDataKey: DataKey; + + yMin$ = this.yMinSubject.asObservable(); + yMax$ = this.yMaxSubject.asObservable(); + + constructor(private ctx: WidgetContext, + private readonly settings: TimeSeriesChartSettings, + private chartElement: HTMLElement, + private renderer: Renderer2, + private autoResize = true) { + + this.settings = mergeDeep({} as TimeSeriesChartSettings, timeSeriesChartDefaultSettings, this.settings); + this.darkMode = this.settings.darkMode; + this.setupData(); + this.setupThresholds(); + if (this.settings.showTooltip && this.settings.tooltipShowDate) { + this.tooltipDateFormat = DateFormatProcessor.fromSettings(this.ctx.$injector, this.settings.tooltipDateFormat); + } + this.onResize(); + if (this.autoResize) { + this.shapeResize$ = new ResizeObserver(() => { + this.onResize(); + }); + this.shapeResize$.observe(this.chartElement); + } + this.messageChannel.addEventListener('message', (event) => { + if (event?.data?.type === 'tbDarkMode') { + const darkMode = !!event?.data?.darkMode; + this.setDarkMode(darkMode); + } + }); + } + + public update(): void { + for (const item of this.dataItems) { + const datasourceData = this.ctx.data ? this.ctx.data.find(d => d.dataKey === item.dataKey) : null; + item.data = datasourceData?.data ? toNamedData(datasourceData.data) : []; + } + this.onResize(); + if (this.timeSeriesChart) { + this.timeSeriesChartOptions.xAxis[0].min = this.ctx.defaultSubscription.timeWindow.minTime; + this.timeSeriesChartOptions.xAxis[0].max = this.ctx.defaultSubscription.timeWindow.maxTime; + this.timeSeriesChartOptions.xAxis[0].tbTimeWindow = this.ctx.defaultSubscription.timeWindow; + if (this.ctx.defaultSubscription.timeWindowConfig?.aggregation?.type === AggregationType.NONE) { + this.timeSeriesChartOptions.tooltip[0].axisPointer.type = 'line'; + } else { + this.timeSeriesChartOptions.tooltip[0].axisPointer.type = 'shadow'; + } + this.updateSeriesData(true); + if (this.highlightedDataKey) { + this.keyEnter(this.highlightedDataKey); + } + } + } + + public latestUpdated() { + let update = false; + if (this.ctx.latestData) { + for (const item of this.thresholdItems) { + if (item.settings.type === TimeSeriesChartThresholdType.latestKey && item.latestDataKey) { + const data = this.ctx.latestData.find(d => d.dataKey === item.latestDataKey); + if (data.data[0]) { + item.value = parseThresholdData(data.data[0][1]); + update = true; + } + } + } + } + if (this.timeSeriesChart && update) { + this.updateSeriesData(); + } + } + + public keyEnter(dataKey: DataKey): void { + this.highlightedDataKey = dataKey; + const item = this.dataItems.find(d => d.dataKey === dataKey); + if (item) { + this.timeSeriesChart.dispatchAction({ + type: 'highlight', + seriesId: item.id + }); + } + } + + public keyLeave(dataKey: DataKey): void { + this.highlightedDataKey = null; + const item = this.dataItems.find(d => d.dataKey === dataKey); + if (item) { + this.timeSeriesChart.dispatchAction({ + type: 'downplay', + seriesId: item.id + }); + } + } + + public toggleKey(dataKey: DataKey): void { + const enable = dataKey.hidden; + const dataItem = this.dataItems.find(d => d.dataKey === dataKey); + if (dataItem) { + dataItem.enabled = enable; + if (!enable) { + this.timeSeriesChart.dispatchAction({ + type: 'downplay', + seriesId: dataItem.id + }); + } + this.timeSeriesChartOptions.series = this.updateSeries(); + const mergeList = ['series']; + if (this.updateYAxisScale(this.yAxisList)) { + this.timeSeriesChartOptions.yAxis = this.yAxisList.map(axis => axis.option); + mergeList.push('yAxis'); + } + this.timeSeriesChart.setOption(this.timeSeriesChartOptions, this.settings.stack ? {notMerge: true} : {replaceMerge: mergeList}); + this.updateAxes(); + dataKey.hidden = !enable; + if (enable) { + this.timeSeriesChart.dispatchAction({ + type: 'highlight', + seriesId: dataItem.id + }); + } + } + } + + public destroy(): void { + if (this.shapeResize$) { + this.shapeResize$.disconnect(); + } + if (this.timeSeriesChart) { + this.timeSeriesChart.dispose(); + } + this.yMinSubject.complete(); + this.yMaxSubject.complete(); + this.messageChannel.close(); + } + + public resize(): void { + this.onResize(); + } + + public setDarkMode(darkMode: boolean): void { + if (this.darkMode !== darkMode) { + this.darkMode = darkMode; + if (this.timeSeriesChart) { + this.timeSeriesChartOptions = updateDarkMode(this.timeSeriesChartOptions, this.settings, this.dataItems, + this.thresholdItems, darkMode); + this.timeSeriesChart.setOption(this.timeSeriesChartOptions); + } + } + } + + public isDarkMode(): boolean { + return this.darkMode; + } + + private setupData(): void { + if (this.ctx.datasources.length) { + for (const datasource of this.ctx.datasources) { + const dataKeys = datasource.dataKeys; + for (const dataKey of dataKeys) { + const keySettings = mergeDeep({} as TimeSeriesChartKeySettings, + timeSeriesChartKeyDefaultSettings, dataKey.settings); + if (keySettings.showPointLabel && keySettings.pointLabelPosition === PointLabelPosition.top) { + this.topPointLabels = true; + } + dataKey.settings = keySettings; + const datasourceData = this.ctx.data ? this.ctx.data.find(d => d.dataKey === dataKey) : null; + const namedData = datasourceData?.data ? toNamedData(datasourceData.data) : []; + const units = dataKey.units && dataKey.units.length ? dataKey.units : this.ctx.units; + const decimals = isDefinedAndNotNull(dataKey.decimals) ? dataKey.decimals : + (isDefinedAndNotNull(this.ctx.decimals) ? this.ctx.decimals : 2); + this.dataItems.push({ + id: this.nextComponentId(), + units, + decimals, + yAxisIndex: this.getYAxis(units, decimals), + dataKey, + data: namedData, + enabled: !keySettings.dataHiddenByDefault + }); + } + } + } + } + + private setupThresholds(): void { + const thresholdDatasources: Datasource[] = []; + for (const threshold of this.settings.thresholds) { + let latestDataKey: DataKey = null; + let entityDataKey: DataKey = null; + let value = null; + if (threshold.type === TimeSeriesChartThresholdType.latestKey) { + if (this.ctx.datasources.length) { + for (const datasource of this.ctx.datasources) { + latestDataKey = datasource.latestDataKeys?.find(d => + (d.type === DataKeyType.function && d.label === threshold.latestKeyName) || + (d.type !== DataKeyType.function && d.name === threshold.latestKeyName)); + if (latestDataKey) { + break; + } + } + } + if (!latestDataKey) { + continue; + } + } else if (threshold.type === TimeSeriesChartThresholdType.entity) { + const entityAliasId = this.ctx.aliasController.getEntityAliasId(threshold.entityAlias); + if (!entityAliasId) { + continue; + } + let datasource = thresholdDatasources.find(d => d.entityAliasId === entityAliasId); + entityDataKey = { + type: threshold.entityKeyType, + name: threshold.entityKey, + label: threshold.entityKey, + settings: {} + }; + if (datasource) { + datasource.dataKeys.push(entityDataKey); + } + datasource = { + type: DatasourceType.entity, + name: threshold.entityAlias, + aliasName: threshold.entityAlias, + entityAliasId, + dataKeys: [ entityDataKey ] + }; + thresholdDatasources.push(datasource); + } else { // constant + value = threshold.value; + } + const units = threshold.units && threshold.units.length ? threshold.units : this.ctx.units; + const decimals = isDefinedAndNotNull(threshold.decimals) ? threshold.decimals : + (isDefinedAndNotNull(this.ctx.decimals) ? this.ctx.decimals : 2); + const thresholdItem: TimeSeriesChartThresholdItem = { + id: this.nextComponentId(), + units, + decimals, + yAxisIndex: this.getYAxis(units, decimals), + value, + latestDataKey, + settings: threshold + }; + if (entityDataKey) { + entityDataKey.settings.thresholdItemId = thresholdItem.id; + } + this.thresholdItems.push(thresholdItem); + } + this.subscribeForEntityThresholds(thresholdDatasources); + } + + private nextComponentId(): string { + return (this.componentIndexCounter++) + ''; + } + + private getYAxis(units: string, decimals: number): number { + let yAxisIndex = this.yAxisList.findIndex(axis => axis.units === units); + if (yAxisIndex === -1) { + const yAxisId = this.yAxisList.length + ''; + const yAxis = createTimeSeriesYAxis(yAxisId, units, decimals, this.settings.yAxis, this.darkMode); + this.yAxisList.push(yAxis); + yAxisIndex = this.yAxisList.length - 1; + } + return yAxisIndex; + } + + private subscribeForEntityThresholds(datasources: Datasource[]) { + if (datasources.length) { + const thresholdsSourcesSubscriptionOptions: WidgetSubscriptionOptions = { + datasources, + useDashboardTimewindow: false, + type: widgetType.latest, + callbacks: { + onDataUpdated: (subscription) => { + let update = false; + if (subscription.data) { + for (const item of this.thresholdItems) { + if (item.settings.type === TimeSeriesChartThresholdType.entity) { + const data = subscription.data.find(d => d.dataKey.settings?.thresholdItemId === item.id); + if (data.data[0]) { + item.value = parseThresholdData(data.data[0][1]); + update = true; + } + } + } + } + if (this.timeSeriesChart && update) { + this.updateSeriesData(); + } + } + } + }; + this.ctx.subscriptionApi.createSubscription(thresholdsSourcesSubscriptionOptions, true).subscribe(); + } + } + + private drawChart() { + echartsModule.init(); + this.timeSeriesChart = echarts.init(this.chartElement, null, { + renderer: 'canvas' + }); + const noAggregation = this.ctx.defaultSubscription.timeWindowConfig?.aggregation?.type === AggregationType.NONE; + this.timeSeriesChartOptions = { + darkMode: this.darkMode, + backgroundColor: 'transparent', + tooltip: [{ + trigger: this.settings.tooltipTrigger === EChartsTooltipTrigger.axis ? 'axis' : 'item', + confine: true, + appendToBody: true, + axisPointer: { + type: noAggregation ? 'line' : 'shadow' + }, + formatter: (params: CallbackDataParams[]) => + this.settings.showTooltip ? echartsTooltipFormatter(this.renderer, this.tooltipDateFormat, + this.settings, params, 0, '', -1, this.dataItems) : undefined, + padding: [8, 12], + backgroundColor: this.settings.tooltipBackgroundColor, + borderWidth: 0, + extraCssText: `line-height: 1; backdrop-filter: blur(${this.settings.tooltipBackgroundBlur}px);` + }], + grid: [{ + top: this.minTopOffset(), + left: this.settings.dataZoom ? 5 : 0, + right: this.settings.dataZoom ? 5 : 0, + bottom: this.minBottomOffset() + }], + xAxis: [ + createTimeSeriesXAxisOption(this.settings.xAxis, this.ctx.defaultSubscription.timeWindow.minTime, + this.ctx.defaultSubscription.timeWindow.maxTime, this.darkMode) + ], + yAxis: this.yAxisList.map(axis => axis.option), + dataZoom: [ + { + type: 'inside', + disabled: !this.settings.dataZoom, + realtime: true + }, + { + type: 'slider', + show: this.settings.dataZoom, + showDetail: false, + realtime: true, + bottom: 10 + } + ] + }; + + this.timeSeriesChartOptions.xAxis[0].tbTimeWindow = this.ctx.defaultSubscription.timeWindow; + + this.timeSeriesChartOptions.series = this.updateSeries(); + if (this.updateYAxisScale(this.yAxisList)) { + this.timeSeriesChartOptions.yAxis = this.yAxisList.map(axis => axis.option); + } + + this.timeSeriesChart.setOption(this.timeSeriesChartOptions); + this.updateAxes(); + + if (this.settings.dataZoom) { + this.timeSeriesChart.on('datazoom', () => { + this.updateAxes(); + }); + } + } + + private updateSeriesData(updateScale = false): void { + this.timeSeriesChartOptions.series = this.updateSeries(); + if (updateScale && this.updateYAxisScale(this.yAxisList)) { + this.timeSeriesChartOptions.yAxis = this.yAxisList.map(axis => axis.option); + } + this.timeSeriesChart.setOption(this.timeSeriesChartOptions); + this.updateAxes(); + } + + private updateSeries(): Array { + return generateChartData(this.dataItems, this.thresholdItems, + this.ctx.timeWindow.interval, this.settings.stack, this.darkMode); + } + + private updateAxes() { + const leftAxisList = this.yAxisList.filter(axis => axis.option.position === 'left'); + let res = this.updateYAxisOffset(leftAxisList); + let leftOffset = res.offset + (!res.offset && this.settings.dataZoom ? 5 : 0); + let changed = res.changed; + const rightAxisList = this.yAxisList.filter(axis => axis.option.position === 'right'); + res = this.updateYAxisOffset(rightAxisList); + let rightOffset = res.offset + (!res.offset && this.settings.dataZoom ? 5 : 0); + changed = changed || res.changed; + let bottomOffset = this.minBottomOffset(); + const minTopOffset = this.minTopOffset(); + let topOffset = minTopOffset; + if (this.timeSeriesChartOptions.xAxis[0].show) { + const xAxisHeight = calculateXAxisHeight(this.timeSeriesChart); + if (this.timeSeriesChartOptions.xAxis[0].position === AxisPosition.bottom) { + bottomOffset += xAxisHeight; + } else { + topOffset = Math.max(minTopOffset, xAxisHeight); + } + if (this.settings.xAxis.label) { + const nameHeight = measureXAxisNameHeight(this.timeSeriesChart, this.timeSeriesChartOptions.xAxis[0].name); + if (this.timeSeriesChartOptions.xAxis[0].position === AxisPosition.bottom) { + bottomOffset += nameHeight; + } else { + topOffset = Math.max(minTopOffset, xAxisHeight + nameHeight); + } + const nameGap = xAxisHeight; + if (this.timeSeriesChartOptions.xAxis[0].nameGap !== nameGap) { + this.timeSeriesChartOptions.xAxis[0].nameGap = nameGap; + changed = true; + } + } + } + + const thresholdsOffset = calculateThresholdsOffset(this.timeSeriesChart, this.thresholdItems, this.yAxisList); + leftOffset = Math.max(leftOffset, thresholdsOffset[0]); + rightOffset = Math.max(rightOffset, thresholdsOffset[1]); + + if (this.timeSeriesChartOptions.grid[0].left !== leftOffset || + this.timeSeriesChartOptions.grid[0].right !== rightOffset || + this.timeSeriesChartOptions.grid[0].bottom !== bottomOffset || + this.timeSeriesChartOptions.grid[0].top !== topOffset) { + this.timeSeriesChartOptions.grid[0].left = leftOffset; + this.timeSeriesChartOptions.grid[0].right = rightOffset; + this.timeSeriesChartOptions.grid[0].bottom = bottomOffset; + this.timeSeriesChartOptions.grid[0].top = topOffset; + changed = true; + } + if (changed) { + this.timeSeriesChartOptions.yAxis = this.yAxisList.map(axis => axis.option); + this.timeSeriesChart.setOption(this.timeSeriesChartOptions, {replaceMerge: ['yAxis', 'xAxis', 'grid'], lazyUpdate: true}); + } + changed = this.calculateYAxisInterval(this.yAxisList); + if (changed) { + this.timeSeriesChartOptions.yAxis = this.yAxisList.map(axis => axis.option); + this.timeSeriesChart.setOption(this.timeSeriesChartOptions, {replaceMerge: ['yAxis'], lazyUpdate: true}); + } + if (this.yAxisList.length) { + const extent = getAxisExtent(this.timeSeriesChart, this.yAxisList[0].id); + const min = extent[0]; + const max = extent[1]; + if (this.yMinSubject.value !== min) { + this.yMinSubject.next(min); + } + if (this.yMaxSubject.value !== max) { + this.yMaxSubject.next(max); + } + } + } + + private updateYAxisScale(axisList: TimeSeriesChartYAxis[]): boolean { + let changed = false; + for (const yAxis of axisList) { + const scaleYAxis = this.scaleYAxis(yAxis); + if (yAxis.option.scale !== scaleYAxis) { + yAxis.option.scale = scaleYAxis; + changed = true; + } + } + return changed; + } + + private updateYAxisOffset(axisList: TimeSeriesChartYAxis[]): {offset: number; changed: boolean} { + const result = {offset: 0, changed: false}; + let width = 0; + for (const yAxis of axisList) { + const newWidth = calculateYAxisWidth(this.timeSeriesChart, yAxis.id); + if (width && newWidth) { + result.offset += 5; + } + width = newWidth; + const showLine = !!width && this.settings.yAxis.showLine; + if (yAxis.option.axisLine.show !== showLine) { + yAxis.option.axisLine.show = showLine; + result.changed = true; + } + if (yAxis.option.offset !== result.offset) { + yAxis.option.offset = result.offset; + result.changed = true; + } + if (this.settings.yAxis.label) { + if (!width) { + if (yAxis.option.name) { + yAxis.option.name = null; + result.changed = true; + } + } else { + if (!yAxis.option.name) { + yAxis.option.name = this.settings.yAxis.label; + result.changed = true; + } + const nameGap = width; + if (yAxis.option.nameGap !== nameGap) { + yAxis.option.nameGap = nameGap; + result.changed = true; + } + const nameWidth = measureYAxisNameWidth(this.timeSeriesChart, yAxis.id, this.settings.yAxis.label); + result.offset += nameWidth; + } + } + result.offset += width; + } + return result; + } + + private scaleYAxis(yAxis: TimeSeriesChartYAxis): boolean { + const yAxisIndex = this.yAxisList.indexOf(yAxis); + const axisBarDataItems = this.dataItems.filter(d => d.yAxisIndex === yAxisIndex && d.enabled && + d.data.length && d.dataKey.settings.type === TimeSeriesChartSeriesType.bar); + return !axisBarDataItems.length; + } + + private calculateYAxisInterval(axisList: TimeSeriesChartYAxis[]): boolean { + let changed = false; + for (const yAxis of axisList) { + if (yAxis.intervalCalculator) { + const axis = getYAxis(this.timeSeriesChart, yAxis.id); + if (axis) { + try { + const interval = yAxis.intervalCalculator(axis); + if ((yAxis.option as any).interval !== interval) { + (yAxis.option as any).interval = interval; + changed = true; + } + } catch (_e) {} + } + } + } + return changed; + } + + private minTopOffset(): number { + return (this.topPointLabels) ? 20 : + ((this.settings.yAxis.show && this.settings.yAxis.showTickLabels) ? 10 : 5); + } + + private minBottomOffset(): number { + return this.settings.dataZoom ? 45 : 5; + } + + private onResize() { + const shapeWidth = this.chartElement.offsetWidth; + const shapeHeight = this.chartElement.offsetHeight; + if (shapeWidth && shapeHeight) { + if (!this.timeSeriesChart) { + this.drawChart(); + } else { + const width = this.timeSeriesChart.getWidth(); + const height = this.timeSeriesChart.getHeight(); + if (width !== shapeWidth || height !== shapeHeight) { + this.timeSeriesChart.resize(); + } + } + } + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts index 03bd97dd41..0ae45d1eff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts @@ -76,6 +76,7 @@ import { CommandButtonWidgetComponent } from '@home/components/widget/lib/button import { PowerButtonWidgetComponent } from '@home/components/widget/lib/rpc/power-button-widget.component'; import { SliderWidgetComponent } from '@home/components/widget/lib/rpc/slider-widget.component'; import { ToggleButtonWidgetComponent } from '@home/components/widget/lib/button/toggle-button-widget.component'; +import { TimeSeriesChartWidgetComponent } from '@home/components/widget/lib/chart/time-series-chart-widget.component'; @NgModule({ declarations: @@ -124,7 +125,8 @@ import { ToggleButtonWidgetComponent } from '@home/components/widget/lib/button/ CommandButtonWidgetComponent, PowerButtonWidgetComponent, SliderWidgetComponent, - ToggleButtonWidgetComponent + ToggleButtonWidgetComponent, + TimeSeriesChartWidgetComponent ], imports: [ CommonModule, @@ -177,7 +179,8 @@ import { ToggleButtonWidgetComponent } from '@home/components/widget/lib/button/ CommandButtonWidgetComponent, PowerButtonWidgetComponent, SliderWidgetComponent, - ToggleButtonWidgetComponent + ToggleButtonWidgetComponent, + TimeSeriesChartWidgetComponent ], providers: [ {provide: WIDGET_COMPONENTS_MODULE_TOKEN, useValue: WidgetComponentsModule } diff --git a/ui-ngx/src/app/shared/models/color.models.ts b/ui-ngx/src/app/shared/models/color.models.ts new file mode 100644 index 0000000000..7c1d08baf8 --- /dev/null +++ b/ui-ngx/src/app/shared/models/color.models.ts @@ -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. +/// + +export interface TbColor { + light: string; + dark: string; +} + +export interface TbColorScheme { + [key: string]: TbColor; +} 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 288db8c9d2..96d8ddebf7 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3169,6 +3169,11 @@ "avg": "avg", "total": "total", "latest": "latest", + "Min": "Min", + "Max": "Max", + "Avg": "Avg", + "Total": "Total", + "Latest": "Latest", "comparison-time-ago": { "previousInterval": "(previous interval)", "customInterval": "(custom interval)", From b972fad5e073fb60131407e902a02d078e25d783 Mon Sep 17 00:00:00 2001 From: rusikv Date: Thu, 29 Feb 2024 16:50:11 +0200 Subject: [PATCH 292/397] UI: fixed RPC terminals not retrieving device name --- .../main/data/json/system/widget_types/rpc_debug_terminal.json | 2 +- .../main/data/json/system/widget_types/rpc_remote_shell.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/main/data/json/system/widget_types/rpc_debug_terminal.json b/application/src/main/data/json/system/widget_types/rpc_debug_terminal.json index eed625283a..0d3409a4b4 100644 --- a/application/src/main/data/json/system/widget_types/rpc_debug_terminal.json +++ b/application/src/main/data/json/system/widget_types/rpc_debug_terminal.json @@ -11,7 +11,7 @@ "resources": [], "templateHtml": "
    ", "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n\n", - "controllerScript": "var requestTimeout = 500;\nvar requestPersistent = false;\nvar persistentPollingInterval = 5000;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n if (self.ctx.settings.requestPersistent) {\n requestPersistent = self.ctx.settings.requestPersistent;\n }\n if (self.ctx.settings.persistentPollingInterval) {\n persistentPollingInterval = self.ctx.settings.persistentPollingInterval;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = uuidv4();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var spaceIndex = localCommand.indexOf(' ');\n if (spaceIndex === -1 && !localCommand.length) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (spaceIndex === -1) {\n spaceIndex = localCommand.length;\n }\n var name = localCommand.substr(0, spaceIndex);\n var args = localCommand.substr(spaceIndex + 1);\n if (args.length) {\n try {\n params = JSON.parse(args);\n } catch (e) {\n params = args;\n }\n }\n performRpc(this, name, params, requestUUID);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestPersistent, persistentPollingInterval, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n\nfunction uuidv4() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n \nself.onDestroy = function() {\n self.ctx.controlApi.completedCommand();\n}", + "controllerScript": "var requestTimeout = 500;\nvar requestPersistent = false;\nvar persistentPollingInterval = 5000;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetEntityName && subscription.targetEntityName.length) {\n deviceName = subscription.targetEntityName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n if (self.ctx.settings.requestPersistent) {\n requestPersistent = self.ctx.settings.requestPersistent;\n }\n if (self.ctx.settings.persistentPollingInterval) {\n persistentPollingInterval = self.ctx.settings.persistentPollingInterval;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n var requestUUID = uuidv4();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var spaceIndex = localCommand.indexOf(' ');\n if (spaceIndex === -1 && !localCommand.length) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (spaceIndex === -1) {\n spaceIndex = localCommand.length;\n }\n var name = localCommand.substr(0, spaceIndex);\n var args = localCommand.substr(spaceIndex + 1);\n if (args.length) {\n try {\n params = JSON.parse(args);\n } catch (e) {\n params = args;\n }\n }\n performRpc(this, name, params, requestUUID);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\n\nfunction performRpc(terminal, method, params, requestUUID) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout, requestPersistent, persistentPollingInterval, requestUUID).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n\nfunction uuidv4() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n \nself.onDestroy = function() {\n self.ctx.controlApi.completedCommand();\n}", "settingsSchema": "", "dataKeySettingsSchema": "{}\n", "settingsDirective": "tb-rpc-terminal-widget-settings", diff --git a/application/src/main/data/json/system/widget_types/rpc_remote_shell.json b/application/src/main/data/json/system/widget_types/rpc_remote_shell.json index de9925a054..c02ce6b3d1 100644 --- a/application/src/main/data/json/system/widget_types/rpc_remote_shell.json +++ b/application/src/main/data/json/system/widget_types/rpc_remote_shell.json @@ -11,7 +11,7 @@ "resources": [], "templateHtml": "
    ", "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n", - "controllerScript": "var requestTimeout = 500;\nvar commandStatusPollingInterval = 200;\n\nvar welcome = 'Welcome to ThingsBoard RPC remote shell.\\n';\n\nvar terminal, rpcEnabled, simulated, deviceName, cwd;\nvar commandExecuting = false;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n rpcEnabled = subscription.rpcEnabled;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n } else {\n deviceName = 'Simulated';\n simulated = true;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n \n terminal = $('#device-terminal', self.ctx.$container).terminal(\n function (command) {\n if (command && command.trim().length) {\n try {\n if (simulated) {\n this.echo(command);\n } else {\n sendCommand(this, command);\n }\n } catch(e) {\n this.error(e + '');\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: false,\n enabled: rpcEnabled,\n prompt: rpcEnabled ? currentPrompt : '',\n name: 'shell',\n pauseEvents: false,\n keydown: function (e, term) {\n if ((e.which == 67 || e.which == 68) && e.ctrlKey) { // CTRL+C || CTRL+D\n if (commandExecuting) {\n terminateCommand(term);\n return false;\n }\n }\n },\n onInit: initTerm\n }\n );\n \n};\n\nfunction initTerm(terminal) {\n terminal.echo(welcome);\n if (!rpcEnabled) {\n terminal.error('Target device is not set!\\n');\n } else {\n terminal.echo('Current target device for RPC terminal: [[b;#fff;]' + deviceName + ']\\n');\n if (!simulated) {\n terminal.pause();\n getTermInfo(terminal,\n function (remoteTermInfo) {\n if (remoteTermInfo) {\n terminal.echo('Remote platform info:');\n terminal.echo('OS: [[b;#fff;]' + remoteTermInfo.platform + ']');\n if (remoteTermInfo.release) {\n terminal.echo('OS release: [[b;#fff;]' + remoteTermInfo.release + ']');\n }\n terminal.echo('\\r');\n } else {\n terminal.echo('[[;#f00;]Unable to get remote platform info.\\nDevice is not responding.]\\n');\n }\n terminal.resume();\n });\n }\n }\n}\n\nfunction currentPrompt(callback) {\n if (cwd) {\n callback('[[b;#2196f3;]' + deviceName +']: [[b;#8bc34a;]' + cwd +']> ');\n } else {\n callback('[[b;#8bc34a;]' + deviceName +']> ');\n }\n}\n\nfunction getTermInfo(terminal, callback) {\n self.ctx.controlApi.sendTwoWayCommand('getTermInfo', null, requestTimeout).subscribe(\n function (termInfo) {\n cwd = termInfo.cwd;\n if (callback) {\n callback(termInfo);\n } \n },\n function () {\n if (callback) {\n callback(null);\n }\n }\n );\n}\n\nfunction sendCommand(terminal, command) {\n terminal.pause();\n var sendCommandRequest = {\n command: command,\n cwd: cwd\n };\n self.ctx.controlApi.sendTwoWayCommand('sendCommand', sendCommandRequest, requestTimeout).subscribe(\n function (responseBody) {\n if (responseBody && responseBody.ok) {\n commandExecuting = true;\n setTimeout( pollCommandStatus.bind(null,terminal), commandStatusPollingInterval );\n } else {\n var error = responseBody ? responseBody.error : 'Unhandled error.';\n terminal.error(error);\n terminal.resume();\n }\n },\n function () {\n onRpcError(terminal);\n }\n );\n}\n\nfunction terminateCommand(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('terminateCommand', null, requestTimeout).subscribe(\n function (responseBody) {\n if (!responseBody.ok) {\n commandExecuting = false;\n terminal.error(responseBody.error);\n terminal.resume();\n } \n },\n function () {\n onRpcError(terminal);\n }\n ); \n}\n\nfunction onRpcError(terminal) {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.resume();\n}\n\nfunction pollCommandStatus(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('getCommandStatus', null, requestTimeout).subscribe(\n function (commandStatusResponse) {\n for (var i=0;i ');\n } else {\n callback('[[b;#8bc34a;]' + deviceName +']> ');\n }\n}\n\nfunction getTermInfo(terminal, callback) {\n self.ctx.controlApi.sendTwoWayCommand('getTermInfo', null, requestTimeout).subscribe(\n function (termInfo) {\n cwd = termInfo.cwd;\n if (callback) {\n callback(termInfo);\n } \n },\n function () {\n if (callback) {\n callback(null);\n }\n }\n );\n}\n\nfunction sendCommand(terminal, command) {\n terminal.pause();\n var sendCommandRequest = {\n command: command,\n cwd: cwd\n };\n self.ctx.controlApi.sendTwoWayCommand('sendCommand', sendCommandRequest, requestTimeout).subscribe(\n function (responseBody) {\n if (responseBody && responseBody.ok) {\n commandExecuting = true;\n setTimeout( pollCommandStatus.bind(null,terminal), commandStatusPollingInterval );\n } else {\n var error = responseBody ? responseBody.error : 'Unhandled error.';\n terminal.error(error);\n terminal.resume();\n }\n },\n function () {\n onRpcError(terminal);\n }\n );\n}\n\nfunction terminateCommand(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('terminateCommand', null, requestTimeout).subscribe(\n function (responseBody) {\n if (!responseBody.ok) {\n commandExecuting = false;\n terminal.error(responseBody.error);\n terminal.resume();\n } \n },\n function () {\n onRpcError(terminal);\n }\n ); \n}\n\nfunction onRpcError(terminal) {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.resume();\n}\n\nfunction pollCommandStatus(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('getCommandStatus', null, requestTimeout).subscribe(\n function (commandStatusResponse) {\n for (var i=0;i Date: Thu, 29 Feb 2024 17:54:52 +0200 Subject: [PATCH 293/397] UI: Add ability to check dashboard state in action widget. --- ui-ngx/src/app/core/api/widget-api.models.ts | 1 + .../dashboard-page.component.ts | 1 + .../dashboard-page/dashboard-page.models.ts | 1 + .../default-state-controller.component.ts | 1 + .../entity-state-controller.component.ts | 3 + .../states/state-controller.component.ts | 8 +- .../states/states-component.directive.ts | 9 +- .../widget/lib/action/action-widget.models.ts | 39 +++++++-- .../button/command-button-widget.models.ts | 2 +- .../lib/button/toggle-button-widget.models.ts | 4 +- .../lib/rpc/power-button-widget.models.ts | 4 +- .../lib/rpc/single-switch-widget.models.ts | 4 +- .../widget/lib/rpc/slider-widget.models.ts | 2 +- ...value-action-settings-panel.component.html | 2 + .../get-value-action-settings.component.ts | 14 +++- .../components/value-input.component.ts | 84 +++++++++++++++---- .../models/action-widget-settings.models.ts | 6 +- .../assets/locale/locale.constant-en_US.json | 4 + 18 files changed, 156 insertions(+), 33 deletions(-) diff --git a/ui-ngx/src/app/core/api/widget-api.models.ts b/ui-ngx/src/app/core/api/widget-api.models.ts index 4b21a60b30..54552c714f 100644 --- a/ui-ngx/src/app/core/api/widget-api.models.ts +++ b/ui-ngx/src/app/core/api/widget-api.models.ts @@ -159,6 +159,7 @@ export interface IStateController { dashboardCtrl: IDashboardController; getStateParams(): StateParams; stateChanged(): Observable; + stateId(): Observable; getStateParamsByStateId(stateId: string): StateParams; openState(id: string, params?: StateParams, openRightLayout?: boolean): void; updateState(id?: string, params?: StateParams, openRightLayout?: boolean): void; diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index fe6364cc09..f3d0e2ee15 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -270,6 +270,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC state: null, stateController: null, stateChanged: null, + stateId: null, aliasController: null, runChangeDetection: this.runChangeDetection.bind(this) }; diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts index 0f7c3378de..2f18de2e6e 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts @@ -39,6 +39,7 @@ export interface DashboardContext { aliasController: IAliasController; stateController: IStateController; stateChanged: Observable; + stateId: Observable; runChangeDetection: () => void; } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts index 28b56da1ed..a59387fc4d 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts @@ -240,6 +240,7 @@ export class DefaultStateControllerComponent extends StateControllerComponent im private gotoState(stateId: string, update: boolean, openRightLayout?: boolean) { if (this.dashboardCtrl.dashboardCtx.state !== stateId) { this.dashboardCtrl.openDashboardState(stateId, openRightLayout); + this.stateIdSubject.next(stateId); if (this.syncStateWithQueryParam && stateId && this.statesValue[stateId]) { this.mobileService.handleDashboardStateName(this.getStateName(stateId, this.statesValue[stateId])); } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts index ee652f2095..bcf090cb8c 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts @@ -280,6 +280,9 @@ export class EntityStateControllerComponent extends StateControllerComponent imp private gotoState(stateId: string, update: boolean, openRightLayout?: boolean) { const isStateIdChanged = this.dashboardCtrl.dashboardCtx.state !== stateId; this.dashboardCtrl.openDashboardState(stateId, openRightLayout); + if (isStateIdChanged) { + this.stateIdSubject.next(stateId); + } if (this.syncStateWithQueryParam) { this.mobileService.handleDashboardStateName(this.getStateName(this.stateObject.length - 1)); } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.component.ts index f27114ff27..85663fe82a 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.component.ts @@ -17,7 +17,7 @@ import { IStateControllerComponent, StateControllerState } from '@home/components/dashboard-page/states/state-controller.models'; import { IDashboardController } from '../dashboard-page.models'; import { DashboardState } from '@app/shared/models/dashboard.models'; -import { Observable, Subject, Subscription } from 'rxjs'; +import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs'; import { NgZone, OnDestroy, OnInit, Directive } from '@angular/core'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { StatesControllerService } from '@home/components/dashboard-page/states/states-controller.service'; @@ -28,6 +28,7 @@ import { StateObject, StateParams } from '@app/core/api/widget-api.models'; export abstract class StateControllerComponent implements IStateControllerComponent, OnInit, OnDestroy { private stateChangedSubject = new Subject(); + protected stateIdSubject = new Subject(); stateObject: StateControllerState = []; dashboardCtrl: IDashboardController; preservedState: any; @@ -126,6 +127,7 @@ export abstract class StateControllerComponent implements IStateControllerCompon subscription.unsubscribe(); }); this.rxSubscriptions.length = 0; + this.stateIdSubject.complete(); this.stateChangedSubject.complete(); } @@ -152,6 +154,10 @@ export abstract class StateControllerComponent implements IStateControllerCompon return this.stateChangedSubject.asObservable(); } + public stateId(): Observable { + return this.stateIdSubject.asObservable(); + } + public openRightLayout(): void { this.dashboardCtrl.openRightLayout(); } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts index a803b5613a..9d413b7e81 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts @@ -28,7 +28,7 @@ import { DashboardState } from '@shared/models/dashboard.models'; import { IDashboardController } from '@home/components/dashboard-page/dashboard-page.models'; import { StatesControllerService } from '@home/components/dashboard-page/states/states-controller.service'; import { IStateControllerComponent } from '@home/components/dashboard-page/states/state-controller.models'; -import { Subject } from 'rxjs'; +import { BehaviorSubject, Subject } from 'rxjs'; @Directive({ // eslint-disable-next-line @angular-eslint/directive-selector @@ -64,18 +64,21 @@ export class StatesComponentDirective implements OnInit, OnDestroy, OnChanges { stateControllerComponent: IStateControllerComponent; private stateChangedSubject = new Subject(); + private stateIdSubject: BehaviorSubject; constructor(private viewContainerRef: ViewContainerRef, private statesControllerService: StatesControllerService) { } ngOnInit(): void { + this.stateIdSubject = new BehaviorSubject(this.dashboardCtrl.dashboardCtx.state); this.init(); } ngOnDestroy(): void { this.destroy(); this.stateChangedSubject.complete(); + this.stateIdSubject.complete(); } ngOnChanges(changes: SimpleChanges): void { @@ -128,9 +131,13 @@ export class StatesComponentDirective implements OnInit, OnDestroy, OnChanges { this.stateControllerComponent = this.stateControllerComponentRef.instance; this.dashboardCtrl.dashboardCtx.stateController = this.stateControllerComponent; this.dashboardCtrl.dashboardCtx.stateChanged = this.stateChangedSubject.asObservable(); + this.dashboardCtrl.dashboardCtx.stateId = this.stateIdSubject.asObservable(); this.stateControllerComponent.stateChanged().subscribe((state) => { this.stateChangedSubject.next(state); }); + this.stateControllerComponent.stateId().subscribe((stateId) => { + this.stateIdSubject.next(stateId); + }); this.stateControllerComponent.preservedState = preservedState; this.stateControllerComponent.dashboardCtrl = this.dashboardCtrl; this.stateControllerComponent.stateControllerInstanceId = stateControllerInstanceId; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/action/action-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/action/action-widget.models.ts index cac6928bac..050637468d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/action/action-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/action/action-widget.models.ts @@ -23,8 +23,8 @@ import { telemetryTypeTranslationsShort } from '@shared/models/telemetry/telemetry.models'; import { WidgetContext } from '@home/models/widget-component.models'; -import { BehaviorSubject, forkJoin, Observable, Observer, of, throwError } from 'rxjs'; -import { catchError, delay, map, share, take } from 'rxjs/operators'; +import { BehaviorSubject, forkJoin, Observable, Observer, of, Subscription, throwError } from 'rxjs'; +import { catchError, delay, map, share, take, tap } from 'rxjs/operators'; import { UtilsService } from '@core/services/utils.service'; import { AfterViewInit, ChangeDetectorRef, Directive, Input, OnDestroy, OnInit, TemplateRef } from '@angular/core'; import { @@ -186,8 +186,14 @@ export class DataToValueConverter { case DataToValueType.FUNCTION: result = data; try { - result = this.dataToValueFunction(!!data ? JSON.parse(data) : data); - } catch (e) {} + let input = data; + if (!!data) { + try { + input = JSON.parse(data); + } catch (_e) {} + } + result = this.dataToValueFunction(input); + } catch (_e) {} break; case DataToValueType.NONE: result = data; @@ -233,12 +239,16 @@ export abstract class ValueGetter extends ValueAction { return new AttributeValueGetter(ctx, settings, valueType, valueObserver); case GetValueAction.GET_TIME_SERIES: return new TimeSeriesValueGetter(ctx, settings, valueType, valueObserver); + case GetValueAction.GET_DASHBOARD_STATE: + return new DashboardStateGetter(ctx, settings, valueType, valueObserver); } } private readonly isSimulated: boolean; private readonly dataConverter: DataToValueConverter; + private getValueSubscription: Subscription; + protected constructor(protected ctx: WidgetContext, protected settings: GetValueSettings, protected valueType: ValueType, @@ -263,7 +273,10 @@ export abstract class ValueGetter extends ValueAction { throw this.handleError(err); }) ); - valueObservable.subscribe({ + if (this.getValueSubscription) { + this.getValueSubscription.unsubscribe(); + } + this.getValueSubscription = valueObservable.subscribe({ next: (value) => { this.valueObserver.next(value); }, @@ -277,6 +290,9 @@ export abstract class ValueGetter extends ValueAction { } destroy() { + if (this.getValueSubscription) { + this.getValueSubscription.unsubscribe(); + } super.destroy(); } @@ -504,6 +520,19 @@ export class TimeSeriesValueGetter extends TelemetryValueGetter extends ValueGetter { + constructor(protected ctx: WidgetContext, + protected settings: GetValueSettings, + protected valueType: ValueType, + protected valueObserver: Partial>) { + super(ctx, settings, valueType, valueObserver); + } + + protected doGetValue(): Observable { + return this.ctx.stateController.dashboardCtrl.dashboardCtx.stateId; + } +} + export class ExecuteRpcValueSetter extends ValueSetter { private readonly executeRpcSettings: RpcSettings; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/command-button-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/button/command-button-widget.models.ts index 87d4706fc8..a365e6929c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/button/command-button-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/command-button-widget.models.ts @@ -41,7 +41,7 @@ export const commandButtonDefaultSettings: CommandButtonWidgetSettings = { }, setAttribute: { key: 'state', - scope: AttributeScope.SHARED_SCOPE + scope: AttributeScope.SERVER_SCOPE }, putTimeSeries: { key: 'state' diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.models.ts index 8307a09bd3..91bc8a65b8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.models.ts @@ -92,7 +92,7 @@ export const toggleButtonDefaultSettings: ToggleButtonWidgetSettings = { }, setAttribute: { key: 'state', - scope: AttributeScope.SHARED_SCOPE + scope: AttributeScope.SERVER_SCOPE }, putTimeSeries: { key: 'state' @@ -113,7 +113,7 @@ export const toggleButtonDefaultSettings: ToggleButtonWidgetSettings = { }, setAttribute: { key: 'state', - scope: AttributeScope.SHARED_SCOPE + scope: AttributeScope.SERVER_SCOPE }, putTimeSeries: { key: 'state' diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts index 2e8ca0de6d..51a427d23b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts @@ -126,7 +126,7 @@ export const powerButtonDefaultSettings: PowerButtonWidgetSettings = { }, setAttribute: { key: 'state', - scope: AttributeScope.SHARED_SCOPE + scope: AttributeScope.SERVER_SCOPE }, putTimeSeries: { key: 'state' @@ -147,7 +147,7 @@ export const powerButtonDefaultSettings: PowerButtonWidgetSettings = { }, setAttribute: { key: 'state', - scope: AttributeScope.SHARED_SCOPE + scope: AttributeScope.SERVER_SCOPE }, putTimeSeries: { key: 'state' diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts index 7897574cac..94586c31de 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts @@ -131,7 +131,7 @@ export const singleSwitchDefaultSettings: SingleSwitchWidgetSettings = { }, setAttribute: { key: 'state', - scope: AttributeScope.SHARED_SCOPE + scope: AttributeScope.SERVER_SCOPE }, putTimeSeries: { key: 'state' @@ -152,7 +152,7 @@ export const singleSwitchDefaultSettings: SingleSwitchWidgetSettings = { }, setAttribute: { key: 'state', - scope: AttributeScope.SHARED_SCOPE + scope: AttributeScope.SERVER_SCOPE }, putTimeSeries: { key: 'state' diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.models.ts index c6fe1e290a..f6daba5da7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/slider-widget.models.ts @@ -132,7 +132,7 @@ export const sliderWidgetDefaultSettings: SliderWidgetSettings = { }, setAttribute: { key: 'state', - scope: AttributeScope.SHARED_SCOPE + scope: AttributeScope.SERVER_SCOPE }, putTimeSeries: { key: 'state' diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings-panel.component.html index faad403e9b..edb3651d38 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings-panel.component.html @@ -125,6 +125,8 @@
    {{ 'widgets.value-action.state-when-result-is' | translate:{state: (stateLabel | translate)} }}
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings.component.ts index 5ca5bf3b84..4af08a1cee 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/get-value-action-settings.component.ts @@ -28,7 +28,7 @@ import { import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { MatButton } from '@angular/material/button'; import { TbPopoverService } from '@shared/components/popover.service'; -import { GetValueAction, GetValueSettings } from '@shared/models/action-widget-settings.models'; +import { DataToValueType, GetValueAction, GetValueSettings } from '@shared/models/action-widget-settings.models'; import { TranslateService } from '@ngx-translate/core'; import { ValueType } from '@shared/models/constants'; import { @@ -170,6 +170,18 @@ export class GetValueActionSettingsComponent implements OnInit, ControlValueAcce case GetValueAction.GET_TIME_SERIES: this.displayValue = this.translate.instant('widgets.value-action.get-time-series-text', {key: this.modelValue.getTimeSeries.key}); break; + case GetValueAction.GET_DASHBOARD_STATE: + if (this.valueType === ValueType.BOOLEAN) { + const state = this.modelValue.dataToValue?.compareToValue; + if (this.modelValue.dataToValue?.type === DataToValueType.FUNCTION) { + this.displayValue = this.translate.instant('widgets.value-action.when-dashboard-state-function-is-text', {state}); + } else { + this.displayValue = this.translate.instant('widgets.value-action.when-dashboard-state-is-text', {state}); + } + } else { + this.displayValue = this.translate.instant('widgets.value-action.get-dashboard-state-text'); + } + break; } this.cd.markForCheck(); } diff --git a/ui-ngx/src/app/shared/components/value-input.component.ts b/ui-ngx/src/app/shared/components/value-input.component.ts index cce9a2400f..0479b2f0df 100644 --- a/ui-ngx/src/app/shared/components/value-input.component.ts +++ b/ui-ngx/src/app/shared/components/value-input.component.ts @@ -14,7 +14,17 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + forwardRef, + Input, + OnChanges, + OnDestroy, + OnInit, + SimpleChanges, + ViewChild +} from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgForm } from '@angular/forms'; import { resolveBreakpoint, ValueType, valueTypesMap } from '@shared/models/constants'; import { isObject } from '@core/utils'; @@ -45,7 +55,7 @@ export interface ValueInputLayout { } ] }) -export class ValueInputComponent implements OnInit, OnDestroy, ControlValueAccessor { +export class ValueInputComponent implements OnInit, OnDestroy, OnChanges, ControlValueAccessor { @Input() disabled: boolean; @@ -85,6 +95,7 @@ export class ValueInputComponent implements OnInit, OnDestroy, ControlValueAcces constructor( private breakpointObserver: BreakpointObserver, + private cd: ChangeDetectorRef, public dialog: MatDialog, ) { @@ -104,6 +115,23 @@ export class ValueInputComponent implements OnInit, OnDestroy, ControlValueAcces } } + ngOnChanges(changes: SimpleChanges): void { + for (const propName of Object.keys(changes)) { + const change = changes[propName]; + if (!change.firstChange) { + if (propName === 'valueType') { + this.showValueType = !this.valueType; + if (this.valueType) { + this.updateModelToValueType(); + } else { + this.detectValueType(); + } + this.cd.markForCheck(); + } + } + } + } + ngOnDestroy() { this._subscription.unsubscribe(); } @@ -144,19 +172,12 @@ export class ValueInputComponent implements OnInit, OnDestroy, ControlValueAcces writeValue(value: any): void { this.modelValue = value; if (this.showValueType) { - if (this.modelValue === true || this.modelValue === false) { - this.valueType = ValueType.BOOLEAN; - } else if (typeof this.modelValue === 'number') { - if (this.modelValue.toString().indexOf('.') === -1) { - this.valueType = ValueType.INTEGER; - } else { - this.valueType = ValueType.DOUBLE; - } - } else if (isObject(this.modelValue)) { - this.valueType = ValueType.JSON; - } else { - this.valueType = ValueType.STRING; - } + this.detectValueType(); + } else { + setTimeout(() => { + this.updateModelToValueType(); + this.cd.markForCheck(); + }, 0); } } @@ -185,6 +206,39 @@ export class ValueInputComponent implements OnInit, OnDestroy, ControlValueAcces this.updateView(); } + private detectValueType() { + if (this.modelValue === true || this.modelValue === false) { + this.valueType = ValueType.BOOLEAN; + } else if (typeof this.modelValue === 'number') { + if (this.modelValue.toString().indexOf('.') === -1) { + this.valueType = ValueType.INTEGER; + } else { + this.valueType = ValueType.DOUBLE; + } + } else if (isObject(this.modelValue)) { + this.valueType = ValueType.JSON; + } else { + this.valueType = ValueType.STRING; + } + } + + private updateModelToValueType() { + if (this.valueType === ValueType.BOOLEAN && typeof this.modelValue !== 'boolean') { + this.modelValue = !!this.modelValue; + this.updateView(); + } else if (this.valueType === ValueType.STRING && typeof this.modelValue !== 'string') { + this.modelValue = null; + this.updateView(); + } else if ([ValueType.DOUBLE, ValueType.INTEGER].includes(this.valueType) && typeof this.modelValue !== 'number') { + this.modelValue = null; + this.updateView(); + } else if (this.valueType === ValueType.JSON && typeof this.modelValue !== 'object') { + this.modelValue = {}; + this.inputForm.form.get('value').patchValue({}); + this.updateView(); + } + } + private _computeLayout(): Layout { if (typeof this.layout !== 'object') { return this.layout; diff --git a/ui-ngx/src/app/shared/models/action-widget-settings.models.ts b/ui-ngx/src/app/shared/models/action-widget-settings.models.ts index a019f086dd..e7b962b34f 100644 --- a/ui-ngx/src/app/shared/models/action-widget-settings.models.ts +++ b/ui-ngx/src/app/shared/models/action-widget-settings.models.ts @@ -21,7 +21,8 @@ export enum GetValueAction { DO_NOTHING = 'DO_NOTHING', EXECUTE_RPC = 'EXECUTE_RPC', GET_ATTRIBUTE = 'GET_ATTRIBUTE', - GET_TIME_SERIES = 'GET_TIME_SERIES' + GET_TIME_SERIES = 'GET_TIME_SERIES', + GET_DASHBOARD_STATE = 'GET_DASHBOARD_STATE' } export const getValueActions = Object.keys(GetValueAction) as GetValueAction[]; @@ -39,7 +40,8 @@ export const getValueActionTranslations = new Map( [GetValueAction.DO_NOTHING, 'widgets.value-action.do-nothing'], [GetValueAction.EXECUTE_RPC, 'widgets.value-action.execute-rpc'], [GetValueAction.GET_ATTRIBUTE, 'widgets.value-action.get-attribute'], - [GetValueAction.GET_TIME_SERIES, 'widgets.value-action.get-time-series'] + [GetValueAction.GET_TIME_SERIES, 'widgets.value-action.get-time-series'], + [GetValueAction.GET_DASHBOARD_STATE, 'widgets.value-action.get-dashboard-state'] ] ); 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 1134bd1e05..0428087620 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6633,10 +6633,14 @@ "get-attribute": "Get attribute", "set-attribute": "Set attribute", "get-time-series": "Get time-series", + "get-dashboard-state": "Get dashboard state", "add-time-series": "Add time-series", "execute-rpc-text": "Execute RPC method '{{methodName}}'", "get-attribute-text": "Use attribute '{{key}}'", "get-time-series-text": "Use time-series '{{key}}'", + "get-dashboard-state-text": "Use dashboard state", + "when-dashboard-state-is-text": "When dashboard state is '{{state}}'", + "when-dashboard-state-function-is-text": "When f(dashboard state) is '{{state}}'", "set-attribute-to-value-text": "Set '{{key}}' attribute to: {{value}}", "add-time-series-value-text": "Add '{{key}}' time-series value: {{value}}", "set-attribute-text": "Set '{{key}}' attribute", From c5a44bce1343e020590f8f8f3f7916511ea02271 Mon Sep 17 00:00:00 2001 From: rusikv Date: Fri, 1 Mar 2024 12:41:25 +0200 Subject: [PATCH 294/397] UI: removed targetDeviceAliasIds from presistent RPC table default config --- .../data/json/system/widget_types/persistent_rpc_table.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/data/json/system/widget_types/persistent_rpc_table.json b/application/src/main/data/json/system/widget_types/persistent_rpc_table.json index 2dadf40b85..f50d1ac5e8 100644 --- a/application/src/main/data/json/system/widget_types/persistent_rpc_table.json +++ b/application/src/main/data/json/system/widget_types/persistent_rpc_table.json @@ -15,7 +15,7 @@ "settingsSchema": "", "dataKeySettingsSchema": "{}\n", "settingsDirective": "tb-persistent-table-widget-settings", - "defaultConfig": "{\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"enableStickyAction\":true,\"enableFilter\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"enableStickyHeader\":true,\"displayColumns\":[\"rpcId\",\"messageType\",\"status\",\"method\",\"createdTime\",\"expirationTime\"],\"displayDetails\":true,\"defaultSortOrder\":\"-createdTime\",\"allowSendRequest\":true,\"allowDelete\":true},\"title\":\"Persistent RPC table\",\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px\"},\"targetDeviceAliasIds\":[]}" + "defaultConfig": "{\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"enableStickyAction\":true,\"enableFilter\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"enableStickyHeader\":true,\"displayColumns\":[\"rpcId\",\"messageType\",\"status\",\"method\",\"createdTime\",\"expirationTime\"],\"displayDetails\":true,\"defaultSortOrder\":\"-createdTime\",\"allowSendRequest\":true,\"allowDelete\":true},\"title\":\"Persistent RPC table\",\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px\"}}" }, "externalId": null, "tags": [ From 0ebd22be2d80ce5da9f62190a55062752891c812 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 1 Mar 2024 19:58:00 +0200 Subject: [PATCH 295/397] UI: Implement Time series chart widget config. --- .../widget_types/time_series_chart.json | 10 +- .../add-widget-dialog.component.ts | 3 + .../dashboard-page/edit-widget.component.ts | 3 + .../basic/basic-widget-config.module.ts | 12 +- .../aggregated-data-keys-panel.component.ts | 3 +- ...e-series-chart-basic-config.component.html | 236 +++++++++++++ ...ime-series-chart-basic-config.component.ts | 314 +++++++++++++++++ .../basic/common/data-key-row.component.html | 15 + .../basic/common/data-key-row.component.scss | 18 +- .../basic/common/data-key-row.component.ts | 44 ++- .../common/data-keys-panel.component.html | 2 + .../common/data-keys-panel.component.scss | 4 + .../basic/common/data-keys-panel.component.ts | 13 +- .../config/data-key-config.component.html | 1 + .../config/data-key-config.component.ts | 27 +- .../config/data-keys.component.models.ts | 5 +- .../widget/config/data-keys.component.ts | 15 +- .../widget/config/datasource.component.html | 3 + .../widget/config/datasource.component.ts | 6 +- .../widget/config/datasources.component.ts | 9 +- .../config/widget-config.component.models.ts | 12 +- .../aggregated-value-card-widget.component.ts | 7 +- .../value-chart-card-widget.component.ts | 7 +- .../widget/lib/chart/echarts-widget.models.ts | 9 +- .../lib/chart/time-series-chart.models.ts | 316 ++++++++++-------- .../widget/lib/chart/time-series-chart.ts | 24 +- .../components/widget/lib/maps/map-widget2.ts | 2 +- ...e-series-chart-key-settings.component.html | 36 ++ ...ime-series-chart-key-settings.component.ts | 82 +++++ .../common/legend-config.component.html | 7 +- .../common/legend-config.component.ts | 28 +- .../lib/settings/widget-settings.module.ts | 12 +- .../widget/widget-component.service.ts | 9 + .../widget/widget-config.component.ts | 9 +- .../home/models/widget-component.models.ts | 2 + .../shared/models/widget-settings.models.ts | 2 +- ui-ngx/src/app/shared/models/widget.models.ts | 2 + .../assets/locale/locale.constant-en_US.json | 23 ++ ui-ngx/src/form.scss | 21 ++ 39 files changed, 1163 insertions(+), 190 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts diff --git a/application/src/main/data/json/system/widget_types/time_series_chart.json b/application/src/main/data/json/system/widget_types/time_series_chart.json index b8cd24a151..7d2fff170f 100644 --- a/application/src/main/data/json/system/widget_types/time_series_chart.json +++ b/application/src/main/data/json/system/widget_types/time_series_chart.json @@ -11,16 +11,16 @@ "resources": [], "templateHtml": "\n", "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings(),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", "settingsSchema": "{}", "dataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}", "settingsDirective": "", - "dataKeySettingsDirective": "", + "dataKeySettingsDirective": "tb-time-series-chart-key-settings", "latestDataKeySettingsDirective": "", - "hasBasicMode": false, - "basicModeDirective": "", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false}},\"title\":\"Time series chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "hasBasicMode": true, + "basicModeDirective": "tb-time-series-chart-basic-config", + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"dd MMM yyyy HH:mm:ss\",\"lastUpdateAgo\":false,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Time series chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, "tags": [ "chart", diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts index 0d02fc956f..2089c03d5d 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/add-widget-dialog.component.ts @@ -29,6 +29,7 @@ import { WidgetConfigComponentData, WidgetInfo } from '@home/models/widget-compo import { isDefined, isDefinedAndNotNull, isString } from '@core/utils'; import { TranslateService } from '@ngx-translate/core'; import { WidgetConfigComponent } from '@home/components/widget/widget-config.component'; +import { DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; export interface AddWidgetDialogData { dashboard: Dashboard; @@ -97,6 +98,7 @@ export class AddWidgetDialogComponent extends DialogComponent + + + + + + + +
    +
    TODO: Thresholds
    +
    +
    +
    widget-config.appearance
    +
    + + {{ 'widget-config.title' | translate }} + +
    + + + + + + + +
    +
    +
    + + {{ 'widget-config.card-icon' | translate }} + +
    + + + + + + + + +
    +
    +
    +
    +
    widgets.time-series-chart.chart
    +
    + + {{ 'widgets.time-series-chart.data-zoom' | translate }} + +
    +
    + +
    + {{ 'widgets.time-series-chart.stack-mode' | translate }} +
    +
    +
    +
    +
    +
    widgets.time-series-chart.axes
    +
    + TODO: Y Axis +
    +
    + TODO: X Axis +
    +
    +
    + + + + + {{ 'widget-config.legend' | translate }} + + + + +
    +
    {{ 'legend.label' | translate }}
    +
    + + + + +
    +
    + + +
    +
    +
    +
    + + + + + {{ 'widget-config.tooltip' | translate }} + + + + +
    +
    {{ 'tooltip.trigger' | translate }}
    + + {{ 'tooltip.trigger-point' | translate }} + {{ 'tooltip.trigger-axis' | translate }} + +
    +
    +
    {{ 'tooltip.value' | translate }}
    +
    + + + + +
    +
    +
    + + {{ 'tooltip.date' | translate }} + +
    + + + + + +
    +
    +
    + +
    + {{ 'tooltip.show-date-time-interval' | translate }} +
    +
    +
    +
    +
    {{ 'tooltip.background-color' | translate }}
    + + +
    +
    +
    {{ 'tooltip.background-blur' | translate }}
    + + +
    px
    +
    +
    +
    +
    +
    +
    +
    widget-config.card-appearance
    +
    +
    {{ 'widgets.background.background' | translate }}
    + + +
    +
    +
    widget-config.show-card-buttons
    + + {{ 'fullscreen.fullscreen' | translate }} + +
    +
    +
    {{ 'widget-config.card-border-radius' | translate }}
    + + + +
    +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts new file mode 100644 index 0000000000..4387e5d52b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts @@ -0,0 +1,314 @@ +/// +/// 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, Injector } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { BasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models'; +import { WidgetConfigComponentData } from '@home/models/widget-component.models'; +import { + DataKey, + Datasource, + legendPositions, + legendPositionTranslationMap, + WidgetConfig, +} from '@shared/models/widget.models'; +import { WidgetConfigComponent } from '@home/components/widget/widget-config.component'; +import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; +import { + getTimewindowConfig, + setTimewindowConfig +} from '@home/components/widget/config/timewindow-config-panel.component'; +import { formatValue, isUndefined, mergeDeep } from '@core/utils'; +import { + cssSizeToStrSize, + DateFormatProcessor, + DateFormatSettings, + resolveCssSize +} from '@shared/models/widget-settings.models'; +import { + timeSeriesChartWidgetDefaultSettings, + TimeSeriesChartWidgetSettings +} from '@home/components/widget/lib/chart/time-series-chart-widget.models'; +import { ValueType } from '@shared/models/constants'; +import { EChartsTooltipTrigger } from '@home/components/widget/lib/chart/echarts-widget.models'; + +@Component({ + selector: 'tb-time-series-chart-basic-config', + templateUrl: './time-series-chart-basic-config.component.html', + styleUrls: ['../basic-config.scss'] +}) +export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigComponent { + + public get datasource(): Datasource { + const datasources: Datasource[] = this.timeSeriesChartWidgetConfigForm.get('datasources').value; + if (datasources && datasources.length) { + return datasources[0]; + } else { + return null; + } + } + + EChartsTooltipTrigger = EChartsTooltipTrigger; + + legendPositions = legendPositions; + + legendPositionTranslationMap = legendPositionTranslationMap; + + timeSeriesChartWidgetConfigForm: UntypedFormGroup; + + tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); + + tooltipDatePreviewFn = this._tooltipDatePreviewFn.bind(this); + + constructor(protected store: Store, + protected widgetConfigComponent: WidgetConfigComponent, + private $injector: Injector, + private fb: UntypedFormBuilder) { + super(store, widgetConfigComponent); + } + + protected configForm(): UntypedFormGroup { + return this.timeSeriesChartWidgetConfigForm; + } + + protected defaultDataKeys(configData: WidgetConfigComponentData): DataKey[] { + return [{ name: 'temperature', label: 'Temperature', type: DataKeyType.timeseries, units: '°C', decimals: 0 }]; + } + + protected onConfigSet(configData: WidgetConfigComponentData) { + const settings: TimeSeriesChartWidgetSettings = mergeDeep({} as TimeSeriesChartWidgetSettings, + timeSeriesChartWidgetDefaultSettings, configData.config.settings as TimeSeriesChartWidgetSettings); + const iconSize = resolveCssSize(configData.config.iconSize); + this.timeSeriesChartWidgetConfigForm = this.fb.group({ + timewindowConfig: [getTimewindowConfig(configData.config), []], + datasources: [configData.config.datasources, []], + series: [this.getSeries(configData.config.datasources), []], + thresholds: [settings.thresholds, []], + + showTitle: [configData.config.showTitle, []], + title: [configData.config.title, []], + titleFont: [configData.config.titleFont, []], + titleColor: [configData.config.titleColor, []], + + showIcon: [configData.config.showTitleIcon, []], + iconSize: [iconSize[0], [Validators.min(0)]], + iconSizeUnit: [iconSize[1], []], + icon: [configData.config.titleIcon, []], + iconColor: [configData.config.iconColor, []], + + dataZoom: [settings.dataZoom, []], + stack: [settings.stack, []], + + yAxis: [settings.yAxis, []], + xAxis: [settings.xAxis, []], + + showLegend: [settings.showLegend, []], + legendLabelFont: [settings.legendLabelFont, []], + legendLabelColor: [settings.legendLabelColor, []], + legendConfig: [settings.legendConfig, []], + + showTooltip: [settings.showTooltip, []], + tooltipTrigger: [settings.tooltipTrigger, []], + tooltipValueFont: [settings.tooltipValueFont, []], + tooltipValueColor: [settings.tooltipValueColor, []], + tooltipShowDate: [settings.tooltipShowDate, []], + tooltipDateFormat: [settings.tooltipDateFormat, []], + tooltipDateFont: [settings.tooltipDateFont, []], + tooltipDateColor: [settings.tooltipDateColor, []], + tooltipDateInterval: [settings.tooltipDateInterval, []], + + tooltipBackgroundColor: [settings.tooltipBackgroundColor, []], + tooltipBackgroundBlur: [settings.tooltipBackgroundBlur, []], + + background: [settings.background, []], + + cardButtons: [this.getCardButtons(configData.config), []], + borderRadius: [configData.config.borderRadius, []], + + actions: [configData.config.actions || {}, []] + }); + } + + protected prepareOutputConfig(config: any): WidgetConfigComponentData { + setTimewindowConfig(this.widgetConfig.config, config.timewindowConfig); + this.widgetConfig.config.datasources = config.datasources; + this.setSeries(config.series, this.widgetConfig.config.datasources); + + this.widgetConfig.config.showTitle = config.showTitle; + this.widgetConfig.config.title = config.title; + this.widgetConfig.config.titleFont = config.titleFont; + this.widgetConfig.config.titleColor = config.titleColor; + + this.widgetConfig.config.showTitleIcon = config.showIcon; + this.widgetConfig.config.iconSize = cssSizeToStrSize(config.iconSize, config.iconSizeUnit); + this.widgetConfig.config.titleIcon = config.icon; + this.widgetConfig.config.iconColor = config.iconColor; + + this.widgetConfig.config.settings = this.widgetConfig.config.settings || {}; + + this.widgetConfig.config.settings.thresholds = config.thresholds; + + this.widgetConfig.config.settings.dataZoom = config.dataZoom; + this.widgetConfig.config.settings.stack = config.stack; + + this.widgetConfig.config.settings.yAxis = config.yAxis; + this.widgetConfig.config.settings.xAxis = config.xAxis; + + this.widgetConfig.config.settings.showLegend = config.showLegend; + this.widgetConfig.config.settings.legendLabelFont = config.legendLabelFont; + this.widgetConfig.config.settings.legendLabelColor = config.legendLabelColor; + this.widgetConfig.config.settings.legendConfig = config.legendConfig; + + this.widgetConfig.config.settings.showTooltip = config.showTooltip; + this.widgetConfig.config.settings.tooltipTrigger = config.tooltipTrigger; + this.widgetConfig.config.settings.tooltipValueFont = config.tooltipValueFont; + this.widgetConfig.config.settings.tooltipValueColor = config.tooltipValueColor; + this.widgetConfig.config.settings.tooltipShowDate = config.tooltipShowDate; + this.widgetConfig.config.settings.tooltipDateFormat = config.tooltipDateFormat; + this.widgetConfig.config.settings.tooltipDateFont = config.tooltipDateFont; + this.widgetConfig.config.settings.tooltipDateColor = config.tooltipDateColor; + this.widgetConfig.config.settings.tooltipDateInterval = config.tooltipDateInterval; + this.widgetConfig.config.settings.tooltipBackgroundColor = config.tooltipBackgroundColor; + this.widgetConfig.config.settings.tooltipBackgroundBlur = config.tooltipBackgroundBlur; + + this.widgetConfig.config.settings.background = config.background; + + this.setCardButtons(config.cardButtons, this.widgetConfig.config); + this.widgetConfig.config.borderRadius = config.borderRadius; + + this.widgetConfig.config.actions = config.actions; + return this.widgetConfig; + } + + protected validatorTriggers(): string[] { + return ['showTitle', 'showIcon', 'showLegend', 'showTooltip', 'tooltipShowDate']; + } + + protected updateValidators(emitEvent: boolean, trigger?: string) { + const showTitle: boolean = this.timeSeriesChartWidgetConfigForm.get('showTitle').value; + const showIcon: boolean = this.timeSeriesChartWidgetConfigForm.get('showIcon').value; + const showLegend: boolean = this.timeSeriesChartWidgetConfigForm.get('showLegend').value; + const showTooltip: boolean = this.timeSeriesChartWidgetConfigForm.get('showTooltip').value; + const tooltipShowDate: boolean = this.timeSeriesChartWidgetConfigForm.get('tooltipShowDate').value; + + if (showTitle) { + this.timeSeriesChartWidgetConfigForm.get('title').enable(); + this.timeSeriesChartWidgetConfigForm.get('titleFont').enable(); + this.timeSeriesChartWidgetConfigForm.get('titleColor').enable(); + this.timeSeriesChartWidgetConfigForm.get('showIcon').enable({emitEvent: false}); + if (showIcon) { + this.timeSeriesChartWidgetConfigForm.get('iconSize').enable(); + this.timeSeriesChartWidgetConfigForm.get('iconSizeUnit').enable(); + this.timeSeriesChartWidgetConfigForm.get('icon').enable(); + this.timeSeriesChartWidgetConfigForm.get('iconColor').enable(); + } else { + this.timeSeriesChartWidgetConfigForm.get('iconSize').disable(); + this.timeSeriesChartWidgetConfigForm.get('iconSizeUnit').disable(); + this.timeSeriesChartWidgetConfigForm.get('icon').disable(); + this.timeSeriesChartWidgetConfigForm.get('iconColor').disable(); + } + } else { + this.timeSeriesChartWidgetConfigForm.get('title').disable(); + this.timeSeriesChartWidgetConfigForm.get('titleFont').disable(); + this.timeSeriesChartWidgetConfigForm.get('titleColor').disable(); + this.timeSeriesChartWidgetConfigForm.get('showIcon').disable({emitEvent: false}); + this.timeSeriesChartWidgetConfigForm.get('iconSize').disable(); + this.timeSeriesChartWidgetConfigForm.get('iconSizeUnit').disable(); + this.timeSeriesChartWidgetConfigForm.get('icon').disable(); + this.timeSeriesChartWidgetConfigForm.get('iconColor').disable(); + } + + if (showLegend) { + this.timeSeriesChartWidgetConfigForm.get('legendLabelFont').enable(); + this.timeSeriesChartWidgetConfigForm.get('legendLabelColor').enable(); + this.timeSeriesChartWidgetConfigForm.get('legendConfig').enable(); + } else { + this.timeSeriesChartWidgetConfigForm.get('legendLabelFont').disable(); + this.timeSeriesChartWidgetConfigForm.get('legendLabelColor').disable(); + this.timeSeriesChartWidgetConfigForm.get('legendConfig').disable(); + } + + if (showTooltip) { + this.timeSeriesChartWidgetConfigForm.get('tooltipTrigger').enable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipValueFont').enable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipValueColor').enable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipShowDate').enable({emitEvent: false}); + this.timeSeriesChartWidgetConfigForm.get('tooltipBackgroundColor').enable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipBackgroundBlur').enable(); + if (tooltipShowDate) { + this.timeSeriesChartWidgetConfigForm.get('tooltipDateFormat').enable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateFont').enable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateColor').enable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateInterval').enable(); + } else { + this.timeSeriesChartWidgetConfigForm.get('tooltipDateFormat').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateFont').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateColor').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateInterval').disable(); + } + } else { + this.timeSeriesChartWidgetConfigForm.get('tooltipValueFont').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipValueColor').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipShowDate').disable({emitEvent: false}); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateFormat').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateFont').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateColor').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipDateInterval').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipBackgroundColor').disable(); + this.timeSeriesChartWidgetConfigForm.get('tooltipBackgroundBlur').disable(); + } + } + + private getSeries(datasources?: Datasource[]): DataKey[] { + if (datasources && datasources.length) { + return datasources[0].dataKeys || []; + } + return []; + } + + private setSeries(series: DataKey[], datasources?: Datasource[]) { + if (datasources && datasources.length) { + datasources[0].dataKeys = series; + } + } + + private getCardButtons(config: WidgetConfig): string[] { + const buttons: string[] = []; + if (isUndefined(config.enableFullscreen) || config.enableFullscreen) { + buttons.push('fullscreen'); + } + return buttons; + } + + private setCardButtons(buttons: string[], config: WidgetConfig) { + config.enableFullscreen = buttons.includes('fullscreen'); + } + + private _tooltipValuePreviewFn(): string { + return formatValue(22, 0, '°C', false); + } + + private _tooltipDatePreviewFn(): string { + const dateFormat: DateFormatSettings = this.timeSeriesChartWidgetConfigForm.get('tooltipDateFormat').value; + const processor = DateFormatProcessor.fromSettings(this.$injector, dateFormat); + processor.update(Date.now()); + return processor.formatted; + } + + protected readonly ValueType = ValueType; +} diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html index 8b233f0b09..1c4767b963 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html @@ -158,6 +158,21 @@
    widget-config.decimals-suffix
    +
    + + + + + {{ timeSeriesChartSeriesTypeIcons.get(keyRowFormGroup.get('timeSeriesType').value) }} + + + + {{ timeSeriesChartSeriesTypeIcons.get(type) }} + {{ timeSeriesChartSeriesTypeTranslations.get(type) | translate }} + + + +
    1; } @@ -256,7 +264,8 @@ export class DataKeysPanelComponent implements ControlValueAccessor, OnInit, OnC } addKey() { - const dataKey = this.callbacks.generateDataKey('', null, this.datakeySettingsSchema); + const dataKey = this.callbacks.generateDataKey('', null, this.datakeySettingsSchema, + false, this.dataKeySettingsFunction); dataKey.label = ''; dataKey.decimals = 0; if (this.hasAdditionalLatestDataKeys) { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html index fe6c347649..37c85e173d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html @@ -197,6 +197,7 @@ [dashboard]="dashboard" [aliasController]="aliasController" [widget]="widget" + [widgetConfig]="widgetConfig" formControlName="settings">
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.ts index b120a60809..9ebe8821cf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.ts @@ -40,7 +40,7 @@ import { UtilsService } from '@core/services/utils.service'; import { TranslateService } from '@ngx-translate/core'; import { MatDialog } from '@angular/material/dialog'; import { EntityService } from '@core/http/entity.service'; -import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; +import { DataKeysCallbacks, DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { Observable, of } from 'rxjs'; import { map, mergeMap, publishReplay, refCount, tap } from 'rxjs/operators'; @@ -51,8 +51,10 @@ import { WidgetService } from '@core/http/widget.service'; import { Dashboard } from '@shared/models/dashboard.models'; import { IAliasController } from '@core/api/widget-api.models'; import { aggregationTranslations, AggregationType, ComparisonDuration } from '@shared/models/time/time.models'; -import { genNextLabel } from '@core/utils'; +import { genNextLabel, isDefinedAndNotNull } from '@core/utils'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { WidgetConfigComponentData } from '@home/models/widget-component.models'; +import { WidgetComponentService } from '@home/components/widget/widget-component.service'; @Component({ selector: 'tb-data-key-config', @@ -155,6 +157,8 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con modelValue: DataKey; + widgetConfig: WidgetConfigComponentData; + private propagateChange = null; public dataKeyFormGroup: UntypedFormGroup; @@ -180,12 +184,31 @@ export class DataKeyConfigComponent extends PageComponent implements OnInit, Con private dialog: MatDialog, private translate: TranslateService, private widgetService: WidgetService, + private widgetComponentService: WidgetComponentService, private fb: UntypedFormBuilder) { super(store); this.functionScopeVariables = this.widgetService.getWidgetScopeVariables(); } ngOnInit(): void { + + const widgetInfo = this.widgetComponentService.getInstantWidgetInfo(this.widget); + const typeParameters = widgetInfo.typeParameters; + const dataKeySettingsFunction: DataKeySettingsFunction = typeParameters?.dataKeySettingsFunction; + + this.widgetConfig = { + widgetName: widgetInfo.widgetName, + config: this.widget.config, + widgetType: this.widget.type, + typeParameters, + dataKeySettingsFunction, + settingsDirective: widgetInfo.settingsDirective, + dataKeySettingsDirective: widgetInfo.dataKeySettingsDirective, + latestDataKeySettingsDirective: widgetInfo.latestDataKeySettingsDirective, + hasBasicMode: isDefinedAndNotNull(widgetInfo.hasBasicMode) ? widgetInfo.hasBasicMode : false, + basicModeDirective: widgetInfo.basicModeDirective + } as WidgetConfigComponentData; + this.alarmKeys = []; for (const name of Object.keys(alarmFields)) { this.alarmKeys.push({ diff --git a/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.models.ts b/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.models.ts index 893631f57b..b0e80973f0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.models.ts @@ -18,8 +18,11 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKey, JsonSettingsSchema } from '@shared/models/widget.models'; import { Observable } from 'rxjs'; +export type DataKeySettingsFunction = (key: DataKey, isLatestDataKey: boolean) => any; + export interface DataKeysCallbacks { - generateDataKey: (chip: any, type: DataKeyType, datakeySettingsSchema: JsonSettingsSchema) => DataKey; + generateDataKey: (chip: any, type: DataKeyType, datakeySettingsSchema: JsonSettingsSchema, + isLatestDataKey: boolean, dataKeySettingsFunction: DataKeySettingsFunction) => DataKey; fetchEntityKeys: (entityAliasId: string, types: Array) => Observable>; fetchEntityKeysForDevice: (deviceId: string, types: Array) => Observable>; } diff --git a/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts index 800c831b67..8c2df629de 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/data-keys.component.ts @@ -52,7 +52,7 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKey, DatasourceType, JsonSettingsSchema, Widget, widgetType } from '@shared/models/widget.models'; import { IAliasController } from '@core/api/widget-api.models'; -import { DataKeysCallbacks } from './data-keys.component.models'; +import { DataKeysCallbacks, DataKeySettingsFunction } from './data-keys.component.models'; import { alarmFields } from '@shared/models/alarm.models'; import { UtilsService } from '@core/services/utils.service'; import { ErrorStateMatcher } from '@angular/material/core'; @@ -139,6 +139,10 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange @Input() optDataKeys: boolean; + @Input() + @coerceBoolean() + latestDataKeys = false; + @Input() @coerceBoolean() simpleDataKeysLabel = false; @@ -149,6 +153,9 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange @Input() datakeySettingsSchema: JsonSettingsSchema; + @Input() + datakeySettingsFunction: DataKeySettingsFunction; + @Input() dataKeySettingsDirective: string; @@ -361,7 +368,8 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange if (this.widgetType === widgetType.alarm) { this.keys = this.utils.getDefaultAlarmDataKeys(); } else if (this.isCountDatasource) { - this.keys = [this.callbacks.generateDataKey('count', DataKeyType.count, this.datakeySettingsSchema)]; + this.keys = [this.callbacks.generateDataKey('count', DataKeyType.count, this.datakeySettingsSchema, + this.latestDataKeys, this.datakeySettingsFunction)]; } else { this.keys = []; } @@ -447,7 +455,8 @@ export class DataKeysComponent implements ControlValueAccessor, OnInit, OnChange } private addFromChipValue(chip: DataKey) { - const key = this.callbacks.generateDataKey(chip.name, chip.type, this.datakeySettingsSchema); + const key = this.callbacks.generateDataKey(chip.name, chip.type, this.datakeySettingsSchema, this.latestDataKeys, + this.datakeySettingsFunction); this.addKey(key); } diff --git a/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.html b/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.html index b72f9f0e5d..13a52a295b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/datasource.component.html @@ -72,6 +72,7 @@ [aliasController]="aliasController" [datakeySettingsSchema]="dataKeySettingsSchema" [dataKeySettingsDirective]="dataKeySettingsDirective" + [datakeySettingsFunction]="dataKeySettingsFunction" [dashboard]="dashboard" [widget]="widget" [callbacks]="dataKeysCallbacks" @@ -82,10 +83,12 @@ { - const dataKey = this.constructDataKey(configData, key); + const dataKey = this.constructDataKey(configData, key, false); dataKeys.push(dataKey); }); } if (latestKeys && latestKeys.length) { latestDataKeys.length = 0; latestKeys.forEach(key => { - const dataKey = this.constructDataKey(configData, key); + const dataKey = this.constructDataKey(configData, key, true); latestDataKeys.push(dataKey); }); } } - protected constructDataKey(configData: WidgetConfigComponentData, key: DataKey): DataKey { + protected constructDataKey(configData: WidgetConfigComponentData, key: DataKey, isLatestKey: boolean): DataKey { const dataKey = - this.widgetConfigComponent.widgetConfigCallbacks.generateDataKey(key.name, key.type, configData.dataKeySettingsSchema); + this.widgetConfigComponent.widgetConfigCallbacks.generateDataKey(key.name, key.type, + configData.dataKeySettingsSchema, isLatestKey, configData.dataKeySettingsFunction); if (key.label) { dataKey.label = key.label; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts index ae7c3c5eee..3edce958f0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts @@ -148,13 +148,14 @@ export class AggregatedValueCardWidgetComponent implements OnInit, AfterViewInit if (this.ctx.defaultSubscription.firstDatasource?.dataKeys?.length) { this.lineChartDataKey = this.ctx.defaultSubscription.firstDatasource?.dataKeys[0]; this.lineChartDataKey.settings = { - showPointLabel: false, type: TimeSeriesChartSeriesType.line, lineSettings: { - smooth: false, showLine: true, + step: false, + smooth: false, lineWidth: 2, - showPoints: false + showPoints: false, + showPointLabel: false } } as TimeSeriesChartKeySettings; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts index b59098de17..f5a305a247 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts @@ -148,13 +148,14 @@ export class ValueChartCardWidgetComponent implements OnInit, AfterViewInit, OnD if (this.ctx.defaultSubscription.firstDatasource?.dataKeys?.length) { this.lineChartDataKey = this.ctx.defaultSubscription.firstDatasource?.dataKeys[0]; this.lineChartDataKey.settings = { - showPointLabel: false, type: TimeSeriesChartSeriesType.line, lineSettings: { - smooth: true, showLine: true, + step: false, + smooth: true, lineWidth: 2, - showPoints: false + showPoints: false, + showPointLabel: false } } as TimeSeriesChartKeySettings; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts index 7564bd9cab..06e8e98fd0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts @@ -44,7 +44,7 @@ import { } from 'echarts/charts'; import { LabelLayout } from 'echarts/features'; import { CanvasRenderer, SVGRenderer } from 'echarts/renderers'; -import { DataEntry, DataKey, DataSet } from '@shared/models/widget.models'; +import { DataEntry, DataKey, DataSet, LegendDirection } from '@shared/models/widget.models'; import { calculateAggIntervalWithWidgetTimeWindow, IntervalMath, @@ -304,6 +304,13 @@ export enum EChartsTooltipTrigger { axis = 'axis' } +export const tooltipTriggerTranslationMap = new Map( + [ + [ EChartsTooltipTrigger.point, 'tooltip.trigger-point' ], + [ EChartsTooltipTrigger.axis, 'tooltip.trigger-axis' ] + ] +); + export interface EChartsTooltipWidgetSettings { showTooltip: boolean; tooltipTrigger?: EChartsTooltipTrigger; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index ef8b432e46..3965f69000 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -40,11 +40,42 @@ import { import { DataKey } from '@shared/models/widget.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { TbColorScheme } from '@shared/models/color.models'; +import { DoughnutLayout } from '@home/components/widget/lib/chart/doughnut-widget.models'; -export enum PointLabelPosition { - top = 'top', - bottom = 'bottom' -} +const timeSeriesChartColorScheme: TbColorScheme = { + 'threshold.line': { + light: 'rgba(0, 0, 0, 0.76)', + dark: '#eee' + }, + 'threshold.label': { + light: 'rgba(0, 0, 0, 0.76)', + dark: '#eee' + }, + 'axis.line': { + light: 'rgba(0, 0, 0, 0.54)', + dark: '#B9B8CE' + }, + 'axis.label': { + light: 'rgba(0, 0, 0, 0.54)', + dark: '#B9B8CE' + }, + 'axis.ticks': { + light: 'rgba(0, 0, 0, 0.54)', + dark: '#B9B8CE' + }, + 'axis.tickLabel': { + light: 'rgba(0, 0, 0, 0.54)', + dark: '#B9B8CE' + }, + 'axis.splitLine': { + light: 'rgba(0, 0, 0, 0.12)', + dark: '#484753' + }, + 'series.label': { + light: 'rgba(0, 0, 0, 0.76)', + dark: '#eee' + } +}; export enum AxisPosition { left = 'left', @@ -86,19 +117,63 @@ export enum ThresholdLabelPosition { insideEndBottom = 'insideEndBottom' } +export enum TimeSeriesChartThresholdType { + constant = 'constant', + latestKey = 'latestKey', + entity = 'entity' +} + +export enum SeriesFillType { + none = 'none', + opacity = 'opacity', + gradient = 'gradient' +} + +export enum SeriesLabelPosition { + top = 'top', + bottom = 'bottom' +} + +export enum LineSeriesStepType { + start = 'start', + middle = 'middle', + end = 'end' +} + +export enum TimeSeriesChartSeriesType { + line = 'line', + bar = 'bar' +} + +export const timeSeriesChartSeriesTypes = Object.keys(TimeSeriesChartSeriesType) as TimeSeriesChartSeriesType[]; + +export const timeSeriesChartSeriesTypeTranslations = new Map( + [ + [TimeSeriesChartSeriesType.line, 'widgets.time-series-chart.series.type-line'], + [TimeSeriesChartSeriesType.bar, 'widgets.time-series-chart.series.type-bar'] + ] +); + +export const timeSeriesChartSeriesTypeIcons = new Map( + [ + [TimeSeriesChartSeriesType.line, 'mdi:chart-line'], + [TimeSeriesChartSeriesType.bar, 'mdi:chart-bar'] + ] +); + export interface TimeSeriesChartAxisSettings { show: boolean; - position: AxisPosition; label?: string; labelFont?: Font; labelColor?: string; - showLine: boolean; - lineColor: string; - showTicks: boolean; - ticksColor: string; + position: AxisPosition; showTickLabels: boolean; tickLabelFont: Font; tickLabelColor: string; + showTicks: boolean; + ticksColor: string; + showLine: boolean; + lineColor: string; showSplitLines: boolean; splitLinesColor: string; } @@ -109,24 +184,19 @@ export interface TimeSeriesChartYAxisSettings extends TimeSeriesChartAxisSetting intervalCalculator?: string; } -export enum TimeSeriesChartThresholdType { - constant = 'constant', - latestKey = 'latestKey', - entity = 'entity' -} - export interface TimeSeriesChartThreshold { type: TimeSeriesChartThresholdType; value?: number; - latestKeyName?: string; + latestKey?: string; + latestKeyType?: DataKeyType.attribute | DataKeyType.timeseries; entityAlias?: string; - entityKeyType?: DataKeyType.attribute | DataKeyType.timeseries; entityKey?: string; + entityKeyType?: DataKeyType.attribute | DataKeyType.timeseries; units?: string; decimals?: number; - lineWidth: number; - lineType: TimeSeriesChartLineType; lineColor: string; + lineType: TimeSeriesChartLineType; + lineWidth: number; startSymbol: TimeSeriesChartShape; startSymbolSize: number; endSymbol: TimeSeriesChartShape; @@ -137,48 +207,13 @@ export interface TimeSeriesChartThreshold { labelColor: string; } -const timeSeriesChartColorScheme: TbColorScheme = { - 'threshold.line': { - light: 'rgba(0, 0, 0, 0.76)', - dark: '#eee' - }, - 'threshold.label': { - light: 'rgba(0, 0, 0, 0.76)', - dark: '#eee' - }, - 'axis.line': { - light: 'rgba(0, 0, 0, 0.54)', - dark: '#B9B8CE' - }, - 'axis.label': { - light: 'rgba(0, 0, 0, 0.54)', - dark: '#B9B8CE' - }, - 'axis.ticks': { - light: 'rgba(0, 0, 0, 0.54)', - dark: '#B9B8CE' - }, - 'axis.tickLabel': { - light: 'rgba(0, 0, 0, 0.54)', - dark: '#B9B8CE' - }, - 'axis.splitLine': { - light: 'rgba(0, 0, 0, 0.12)', - dark: '#484753' - }, - 'series.pointLabel': { - light: 'rgba(0, 0, 0, 0.76)', - dark: '#eee' - } -}; - export const timeSeriesChartThresholdDefaultSettings: TimeSeriesChartThreshold = { type: TimeSeriesChartThresholdType.constant, units: '', decimals: 0, - lineWidth: 1, - lineType: TimeSeriesChartLineType.solid, lineColor: timeSeriesChartColorScheme['threshold.line'].light, + lineType: TimeSeriesChartLineType.solid, + lineWidth: 1, startSymbol: TimeSeriesChartShape.none, startSymbolSize: 5, endSymbol: TimeSeriesChartShape.arrow, @@ -197,22 +232,21 @@ export const timeSeriesChartThresholdDefaultSettings: TimeSeriesChartThreshold = }; export interface TimeSeriesChartSettings extends EChartsTooltipWidgetSettings { + thresholds: TimeSeriesChartThreshold[]; darkMode: boolean; dataZoom: boolean; stack: boolean; - thresholds: TimeSeriesChartThreshold[]; - xAxis: TimeSeriesChartAxisSettings; yAxis: TimeSeriesChartYAxisSettings; + xAxis: TimeSeriesChartAxisSettings; } export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { + thresholds: [], darkMode: false, dataZoom: true, stack: false, - thresholds: [], - xAxis: { + yAxis: { show: true, - position: AxisPosition.bottom, label: '', labelFont: { family: 'Roboto', @@ -223,26 +257,26 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { lineHeight: '1' }, labelColor: timeSeriesChartColorScheme['axis.label'].light, - showLine: true, - lineColor: timeSeriesChartColorScheme['axis.line'].light, - showTicks: true, - ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, + position: AxisPosition.left, showTickLabels: true, tickLabelFont: { family: 'Roboto', - size: 10, + size: 12, sizeUnit: 'px', style: 'normal', weight: '400', lineHeight: '1' }, tickLabelColor: timeSeriesChartColorScheme['axis.tickLabel'].light, + showTicks: true, + ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, + showLine: true, + lineColor: timeSeriesChartColorScheme['axis.line'].light, showSplitLines: true, splitLinesColor: timeSeriesChartColorScheme['axis.splitLine'].light }, - yAxis: { + xAxis: { show: true, - position: AxisPosition.left, label: '', labelFont: { family: 'Roboto', @@ -253,20 +287,21 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { lineHeight: '1' }, labelColor: timeSeriesChartColorScheme['axis.label'].light, - showLine: true, - lineColor: timeSeriesChartColorScheme['axis.line'].light, - showTicks: true, - ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, + position: AxisPosition.bottom, showTickLabels: true, tickLabelFont: { family: 'Roboto', - size: 12, + size: 10, sizeUnit: 'px', style: 'normal', weight: '400', lineHeight: '1' }, tickLabelColor: timeSeriesChartColorScheme['axis.tickLabel'].light, + showTicks: true, + ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, + showLine: true, + lineColor: timeSeriesChartColorScheme['axis.line'].light, showSplitLines: true, splitLinesColor: timeSeriesChartColorScheme['axis.splitLine'].light }, @@ -282,7 +317,6 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { }, tooltipValueColor: 'rgba(0, 0, 0, 0.76)', tooltipShowDate: true, - tooltipDateInterval: true, tooltipDateFormat: simpleDateFormat('dd MMM yyyy HH:mm:ss'), tooltipDateFont: { family: 'Roboto', @@ -293,16 +327,11 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { lineHeight: '16px' }, tooltipDateColor: 'rgba(0, 0, 0, 0.76)', + tooltipDateInterval: true, tooltipBackgroundColor: 'rgba(255, 255, 255, 0.76)', tooltipBackgroundBlur: 4 }; -export enum SeriesFillType { - none = 'none', - opacity = 'opacity', - gradient = 'gradient' -} - export interface SeriesFillSettings { type: SeriesFillType; opacity: number; @@ -313,36 +342,36 @@ export interface SeriesFillSettings { } export interface LineSeriesSettings { - step: false | 'start' | 'end' | 'middle'; - smooth: boolean; showLine: boolean; - lineWidth: number; + step: boolean; + stepType: LineSeriesStepType; + smooth: boolean; lineType: TimeSeriesChartLineType; - fillAreaSettings: SeriesFillSettings; + lineWidth: number; showPoints: boolean; + showPointLabel: boolean; + pointLabelPosition: SeriesLabelPosition; + pointLabelFont: Font; + pointLabelColor: string; pointShape: TimeSeriesChartShape; pointSize: number; + fillAreaSettings: SeriesFillSettings; } export interface BarSeriesSettings { showBorder: boolean; borderWidth: number; borderRadius: number; + showLabel: boolean; + labelPosition: SeriesLabelPosition; + labelFont: Font; + labelColor: string; backgroundSettings: SeriesFillSettings; } -export enum TimeSeriesChartSeriesType { - line = 'line', - bar = 'bar' -} - export interface TimeSeriesChartKeySettings { - dataHiddenByDefault: boolean; showInLegend: boolean; - showPointLabel: boolean; - pointLabelPosition: PointLabelPosition; - pointLabelFont: Font; - pointLabelColor: string; + dataHiddenByDefault: boolean; type: TimeSeriesChartSeriesType; lineSettings: LineSeriesSettings; barSettings: BarSeriesSettings; @@ -351,24 +380,28 @@ export interface TimeSeriesChartKeySettings { export const timeSeriesChartKeyDefaultSettings: TimeSeriesChartKeySettings = { showInLegend: true, dataHiddenByDefault: false, - showPointLabel: false, - pointLabelPosition: PointLabelPosition.top, - pointLabelFont: { - family: 'Roboto', - size: 11, - sizeUnit: 'px', - style: 'normal', - weight: '400', - lineHeight: '1' - }, - pointLabelColor: timeSeriesChartColorScheme['series.pointLabel'].light, type: TimeSeriesChartSeriesType.line, lineSettings: { + showLine: true, step: false, + stepType: LineSeriesStepType.start, smooth: false, - showLine: true, - lineWidth: 2, lineType: TimeSeriesChartLineType.solid, + lineWidth: 2, + showPoints: false, + showPointLabel: false, + pointLabelPosition: SeriesLabelPosition.top, + pointLabelFont: { + family: 'Roboto', + size: 11, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '1' + }, + pointLabelColor: timeSeriesChartColorScheme['series.label'].light, + pointShape: TimeSeriesChartShape.emptyCircle, + pointSize: 4, fillAreaSettings: { type: SeriesFillType.none, opacity: 0.4, @@ -376,15 +409,23 @@ export const timeSeriesChartKeyDefaultSettings: TimeSeriesChartKeySettings = { start: 100, end: 0 } - }, - showPoints: false, - pointShape: TimeSeriesChartShape.emptyCircle, - pointSize: 4 + } }, barSettings: { showBorder: false, borderWidth: 2, borderRadius: 0, + showLabel: false, + labelPosition: SeriesLabelPosition.top, + labelFont: { + family: 'Roboto', + size: 11, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '1' + }, + labelColor: timeSeriesChartColorScheme['series.label'].light, backgroundSettings: { type: SeriesFillType.none, opacity: 0.4, @@ -707,21 +748,23 @@ export const updateDarkMode = (options: EChartsOption, settings: TimeSeriesChart } for (const item of dataItems) { if (item.dataKey.settings.type === TimeSeriesChartSeriesType.line) { + const lineSettings = item.dataKey.settings as LineSeriesSettings; if (item.option.label?.show) { - item.option.label.rich.value.color = prepareChartThemeColor(item.dataKey.settings.pointLabelColor, darkMode, 'series.pointLabel'); + item.option.label.rich.value.color = prepareChartThemeColor(lineSettings.pointLabelColor, darkMode, 'series.label'); } if (Array.isArray(options.series)) { const series = options.series.find(s => s.id === item.id); if (series) { if (series.label?.show) { - series.label.rich.value.color = prepareChartThemeColor(item.dataKey.settings.pointLabelColor, darkMode, 'series.pointLabel'); + series.label.rich.value.color = prepareChartThemeColor(lineSettings.pointLabelColor, darkMode, 'series.label'); } } } } else { if (item.barRenderContext?.labelOption?.show) { - item.barRenderContext.labelOption.rich.value.color = prepareChartThemeColor(item.dataKey.settings.pointLabelColor, - darkMode, 'series.pointLabel'); + const barSettings = item.dataKey.settings as BarSeriesSettings; + item.barRenderContext.labelOption.rich.value.color = prepareChartThemeColor(barSettings.labelColor, + darkMode, 'series.label'); } } } @@ -747,21 +790,6 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem, const dataKey = item.dataKey; const settings: TimeSeriesChartKeySettings = dataKey.settings; const seriesColor = item.dataKey.color; - let pointLabelStyle: ComponentStyle = {}; - if (settings.showPointLabel) { - pointLabelStyle = createChartTextStyle(settings.pointLabelFont, settings.pointLabelColor, darkMode, 'series.pointLabel'); - } - const label: SeriesLabelOption = { - show: settings.showPointLabel, - position: settings.pointLabelPosition, - formatter: (params): string => { - const value = formatValue(params.value[1], item.decimals, item.units, false); - return `{value|${value}}`; - }, - rich: { - value: pointLabelStyle - } - }; seriesOption = { id: item.id, dataGroupId: item.id, @@ -788,8 +816,9 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem, const lineSettings = settings.lineSettings; const lineSeriesOption = seriesOption as LineSeriesOption; lineSeriesOption.type = 'line'; - lineSeriesOption.label = label; - lineSeriesOption.step = lineSettings.step; + lineSeriesOption.label = createSeriesLabelOption(item, lineSettings.showPointLabel, + lineSettings.pointLabelFont, lineSettings.pointLabelColor, lineSettings.pointLabelPosition, darkMode); + lineSeriesOption.step = lineSettings.step ? lineSettings.stepType : false; lineSeriesOption.smooth = lineSettings.smooth; lineSeriesOption.lineStyle = { width: lineSettings.showLine ? lineSettings.lineWidth : 0, @@ -825,7 +854,8 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem, barVisualSettings.color = createLinearOpacityGradient(seriesColor, barSettings.backgroundSettings.gradient); } item.barRenderContext.visualSettings = barVisualSettings; - item.barRenderContext.labelOption = label; + item.barRenderContext.labelOption = createSeriesLabelOption(item, barSettings.showLabel, + barSettings.labelFont, barSettings.labelColor, barSettings.labelPosition, darkMode); barSeriesOption.renderItem = (params, api) => renderTimeSeriesBar(params, api, item.barRenderContext); } @@ -834,6 +864,26 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem, return seriesOption; }; +const createSeriesLabelOption = (item: TimeSeriesChartDataItem, show: boolean, + labelFont: Font, labelColor: string, position: SeriesLabelPosition, + darkMode: boolean): SeriesLabelOption => { + let labelStyle: ComponentStyle = {}; + if (show) { + labelStyle = createChartTextStyle(labelFont, labelColor, darkMode, 'series.label'); + } + return { + show, + position, + formatter: (params): string => { + const value = formatValue(params.value[1], item.decimals, item.units, false); + return `{value|${value}}`; + }, + rich: { + value: labelStyle + } + }; +}; + const createChartTextStyle = (font: Font, color: string, darkMode: boolean, colorKey?: string): ComponentStyle => { const style = textStyle(font); delete style.lineHeight; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 48c2dfaf57..c36327fec6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -21,6 +21,7 @@ import { createTimeSeriesXAxisOption, createTimeSeriesYAxis, generateChartData, + parseThresholdData, SeriesLabelPosition, TimeSeriesChartDataItem, timeSeriesChartDefaultSettings, timeSeriesChartKeyDefaultSettings, @@ -30,8 +31,6 @@ import { TimeSeriesChartThresholdItem, TimeSeriesChartThresholdType, TimeSeriesChartYAxis, - parseThresholdData, - PointLabelPosition, updateDarkMode } from '@home/components/widget/lib/chart/time-series-chart.models'; import { ResizeObserver } from '@juggle/resize-observer'; @@ -60,9 +59,20 @@ import { BehaviorSubject } from 'rxjs'; import { AggregationType } from '@shared/models/time/time.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; +import { DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; export class TbTimeSeriesChart { + public static dataKeySettings(): DataKeySettingsFunction { + return (key, isLatestDataKey) => { + if (!isLatestDataKey) { + return mergeDeep({} as TimeSeriesChartKeySettings, + timeSeriesChartKeyDefaultSettings); + } + return null; + }; + } + private readonly shapeResize$: ResizeObserver; private dataItems: TimeSeriesChartDataItem[] = []; @@ -247,7 +257,10 @@ export class TbTimeSeriesChart { for (const dataKey of dataKeys) { const keySettings = mergeDeep({} as TimeSeriesChartKeySettings, timeSeriesChartKeyDefaultSettings, dataKey.settings); - if (keySettings.showPointLabel && keySettings.pointLabelPosition === PointLabelPosition.top) { + if ((keySettings.type === TimeSeriesChartSeriesType.line && keySettings.lineSettings.showPointLabel && + keySettings.lineSettings.pointLabelPosition === SeriesLabelPosition.top) || + (keySettings.type === TimeSeriesChartSeriesType.bar && keySettings.barSettings.showLabel && + keySettings.barSettings.labelPosition === SeriesLabelPosition.top)) { this.topPointLabels = true; } dataKey.settings = keySettings; @@ -280,8 +293,9 @@ export class TbTimeSeriesChart { if (this.ctx.datasources.length) { for (const datasource of this.ctx.datasources) { latestDataKey = datasource.latestDataKeys?.find(d => - (d.type === DataKeyType.function && d.label === threshold.latestKeyName) || - (d.type !== DataKeyType.function && d.name === threshold.latestKeyName)); + (d.type === DataKeyType.function && d.label === threshold.latestKey) || + (d.type !== DataKeyType.function && d.name === threshold.latestKey && + d.type === threshold.latestKeyType)); if (latestDataKey) { break; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts index a760d1ece1..a46e6a8427 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/map-widget2.ts @@ -298,6 +298,6 @@ export class MapWidgetController implements MapWidgetInterface { } } -export let TbMapWidgetV2: MapWidgetStaticInterface = MapWidgetController; +export const TbMapWidgetV2: MapWidgetStaticInterface = MapWidgetController; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html new file mode 100644 index 0000000000..b1d5d3d302 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html @@ -0,0 +1,36 @@ + + +
    +
    widgets.time-series-chart.series.legend-settings
    + +
    + {{ 'widgets.time-series-chart.series.show-in-legend' | translate }} +
    +
    + +
    + {{ 'widgets.time-series-chart.series.hidden-by-default' | translate }} +
    +
    +
    +
    +
    widgets.time-series-chart.series.series-type
    + TODO: +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts new file mode 100644 index 0000000000..8f266fa9b6 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts @@ -0,0 +1,82 @@ +/// +/// 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 { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models'; +import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { mergeDeep } from '@core/utils'; +import { + timeSeriesChartKeyDefaultSettings, + TimeSeriesChartKeySettings +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { WidgetConfigComponentData } from '@home/models/widget-component.models'; + +@Component({ + selector: 'tb-time-series-chart-key-settings', + templateUrl: './time-series-chart-key-settings.component.html', + styleUrls: ['./../widget-settings.scss'] +}) +export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent { + + timeSeriesChartKeySettingsForm: UntypedFormGroup; + + constructor(protected store: Store, + private fb: UntypedFormBuilder) { + super(store); + } + + protected settingsForm(): UntypedFormGroup { + return this.timeSeriesChartKeySettingsForm; + } + + protected onWidgetConfigSet(widgetConfig: WidgetConfigComponentData) { + const params = widgetConfig.typeParameters as any; + // const timeSeriesChartType = params.timeSeriesChartType; + } + + protected defaultSettings(): WidgetSettings { + return mergeDeep({} as TimeSeriesChartKeySettings, + timeSeriesChartKeyDefaultSettings); + } + + protected onSettingsSet(settings: WidgetSettings) { + const seriesSettings = settings as TimeSeriesChartKeySettings; + this.timeSeriesChartKeySettingsForm = this.fb.group({ + showInLegend: [seriesSettings.showInLegend, []], + dataHiddenByDefault: [seriesSettings.dataHiddenByDefault, []], + type: [seriesSettings.type, []], + lineSettings: [settings.lineSettings, []], + barSettings: [settings.barSettings, []] + }); + } + + protected validatorTriggers(): string[] { + return ['showInLegend']; + } + + protected updateValidators(_emitEvent: boolean) { + const showInLegend: boolean = this.timeSeriesChartKeySettingsForm.get('showInLegend').value; + if (showInLegend) { + this.timeSeriesChartKeySettingsForm.get('dataHiddenByDefault').enable(); + } else { + this.timeSeriesChartKeySettingsForm.get('dataHiddenByDefault').patchValue(false, {emitEvent: false}); + this.timeSeriesChartKeySettingsForm.get('dataHiddenByDefault').disable(); + } + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.html index 44ab1d0bad..3dd5e08860 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.html @@ -16,7 +16,7 @@ --> -
    +
    {{ 'legend.direction' | translate }}
    @@ -31,8 +31,9 @@ + [disabled]="!hideDirection && + legendConfigForm.get('direction').value === legendDirection.row && + (pos === legendPosition.left || pos === legendPosition.right)"> {{ legendPositionTranslations.get(legendPosition[pos]) | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts index cf7b3d4e29..8b065247f3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/legend-config.component.ts @@ -25,6 +25,7 @@ import { legendPositionTranslationMap } from '@shared/models/widget.models'; import { Subscription } from 'rxjs'; +import { coerceBoolean } from '@shared/decorators/coercion'; // @dynamic @Component({ @@ -43,6 +44,10 @@ export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAcc @Input() disabled: boolean; + @Input() + @coerceBoolean() + hideDirection = false; + legendConfigForm: UntypedFormGroup; legendDirection = LegendDirection; legendDirections = Object.keys(LegendDirection); @@ -60,15 +65,17 @@ export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAcc ngOnInit(): void { this.legendConfigForm = this.fb.group({ - direction: [null, []], position: [null, []], showValues: [[], []], sortDataKeys: [null, []] }); - this.legendSettingsFormDirectionChanges$ = this.legendConfigForm.get('direction').valueChanges + if (!this.hideDirection) { + this.legendConfigForm.addControl('direction', this.fb.control([null, []])); + this.legendSettingsFormDirectionChanges$ = this.legendConfigForm.get('direction').valueChanges .subscribe((direction: LegendDirection) => { this.onDirectionChanged(direction); }); + } this.legendSettingsFormChanges$ = this.legendConfigForm.valueChanges.subscribe( () => this.legendConfigUpdated() ); @@ -114,23 +121,30 @@ export class LegendConfigComponent implements OnInit, OnDestroy, ControlValueAcc writeValue(legendConfig: LegendConfig): void { if (legendConfig) { - this.legendConfigForm.patchValue({ - direction: legendConfig.direction, + const value: any = { position: legendConfig.position, showValues: this.getShowValues(legendConfig), sortDataKeys: isDefined(legendConfig.sortDataKeys) ? legendConfig.sortDataKeys : false - }, {emitEvent: false}); + }; + if (!this.hideDirection) { + value.direction = legendConfig.direction; + } + this.legendConfigForm.patchValue(value, {emitEvent: false}); + } + if (!this.hideDirection) { + this.onDirectionChanged(legendConfig?.direction); } - this.onDirectionChanged(legendConfig.direction); } private legendConfigUpdated() { const configValue = this.legendConfigForm.value; const legendConfig: Partial = { - direction: configValue.direction, position: configValue.position, sortDataKeys: configValue.sortDataKeys }; + if (!this.hideDirection) { + legendConfig.direction = configValue.direction; + } this.setShowValues(configValue.showValues, legendConfig); this.propagateChange(legendConfig); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts index 2943b4cc09..4183a06db2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts @@ -330,6 +330,9 @@ import { import { ToggleButtonWidgetSettingsComponent } from '@home/components/widget/lib/settings/button/toggle-button-widget-settings.component'; +import { + TimeSeriesChartKeySettingsComponent +} from '@home/components/widget/lib/settings/chart/time-series-chart-key-settings.component'; @NgModule({ declarations: [ @@ -448,7 +451,8 @@ import { CommandButtonWidgetSettingsComponent, PowerButtonWidgetSettingsComponent, SliderWidgetSettingsComponent, - ToggleButtonWidgetSettingsComponent + ToggleButtonWidgetSettingsComponent, + TimeSeriesChartKeySettingsComponent ], imports: [ CommonModule, @@ -572,7 +576,8 @@ import { CommandButtonWidgetSettingsComponent, PowerButtonWidgetSettingsComponent, SliderWidgetSettingsComponent, - ToggleButtonWidgetSettingsComponent + ToggleButtonWidgetSettingsComponent, + TimeSeriesChartKeySettingsComponent ] }) export class WidgetSettingsModule { @@ -663,5 +668,6 @@ export const widgetSettingsComponentsMap: {[key: string]: Type { + (window as any).TbTimeSeriesChart = mod.TbTimeSeriesChart; + })) + ); widgetModulesTasks.push(from(import('@home/components/widget/lib/analogue-compass')).pipe( tap((mod) => { (window as any).TbAnalogueCompass = mod.TbAnalogueCompass; @@ -577,6 +583,9 @@ export class WidgetComponentService { if (!isFunction(result.typeParameters.defaultLatestDataKeysFunction)) { result.typeParameters.defaultLatestDataKeysFunction = null; } + if (!isFunction(result.typeParameters.dataKeySettingsFunction)) { + result.typeParameters.dataKeySettingsFunction = null; + } if (isUndefined(result.typeParameters.displayRpcMessageToast)) { result.typeParameters.displayRpcMessageToast = true; } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts index 49e4e2ea59..5ace8ac616 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-config.component.ts @@ -84,6 +84,7 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { basicWidgetConfigComponentsMap } from '@home/components/widget/config/basic/basic-widget-config.module'; import { TimewindowConfigData } from '@home/components/widget/config/timewindow-config-panel.component'; import Timeout = NodeJS.Timeout; +import { DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; const emptySettingsSchema: JsonSchema = { type: 'object', @@ -734,7 +735,8 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe } } - public generateDataKey(chip: any, type: DataKeyType, datakeySettingsSchema: JsonSettingsSchema): DataKey { + public generateDataKey(chip: any, type: DataKeyType, datakeySettingsSchema: JsonSettingsSchema, + isLatestDataKey: boolean, dataKeySettingsFunction: DataKeySettingsFunction): DataKey { if (isObject(chip)) { (chip as DataKey)._hash = Math.random(); return chip; @@ -767,6 +769,11 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe } if (datakeySettingsSchema && isDefined(datakeySettingsSchema.schema)) { result.settings = this.utils.generateObjectFromJsonSchema(datakeySettingsSchema.schema); + } else if (dataKeySettingsFunction) { + const settings = dataKeySettingsFunction(result, isLatestDataKey); + if (settings) { + result.settings = settings; + } } return result; } diff --git a/ui-ngx/src/app/modules/home/models/widget-component.models.ts b/ui-ngx/src/app/modules/home/models/widget-component.models.ts index 2ea34377d6..26e5fd4057 100644 --- a/ui-ngx/src/app/modules/home/models/widget-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/widget-component.models.ts @@ -102,6 +102,7 @@ import { ImagePipe, MillisecondsToTimeStringPipe, TelemetrySubscriber } from '@a import { UserId } from '@shared/models/id/user-id'; import { UserSettingsService } from '@core/http/user-settings.service'; import { DynamicComponentModule } from '@core/services/dynamic-component-factory.service'; +import { DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; export interface IWidgetAction { name: string; @@ -549,6 +550,7 @@ export interface WidgetConfigComponentData { settingsSchema: JsonSettingsSchema; dataKeySettingsSchema: JsonSettingsSchema; latestDataKeySettingsSchema: JsonSettingsSchema; + dataKeySettingsFunction: DataKeySettingsFunction; settingsDirective: string; dataKeySettingsDirective: string; latestDataKeySettingsDirective: string; diff --git a/ui-ngx/src/app/shared/models/widget-settings.models.ts b/ui-ngx/src/app/shared/models/widget-settings.models.ts index 8e60c0d9cb..1e2e0d2415 100644 --- a/ui-ngx/src/app/shared/models/widget-settings.models.ts +++ b/ui-ngx/src/app/shared/models/widget-settings.models.ts @@ -348,7 +348,7 @@ export const customDateFormat = (format: string): DateFormatSettings => ({ custom: true }); -export const dateFormats = ['MMM dd yyyy HH:mm', 'dd MMM yyyy HH:mm', 'yyyy MMM dd HH:mm', +export const dateFormats = ['MMM dd yyyy HH:mm', 'dd MMM yyyy HH:mm', 'dd MMM yyyy HH:mm:ss', 'yyyy MMM dd HH:mm', 'MM/dd/yyyy HH:mm', 'dd/MM/yyyy HH:mm', 'yyyy/MM/dd HH:mm:ss', 'yyyy-MM-dd HH:mm:ss', 'yyyy-MM-dd HH:mm:ss.SSS'] .map(f => simpleDateFormat(f)).concat([lastUpdateAgoDateFormat(), customDateFormat('EEE, MMMM dd, yyyy')]); diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 5f4ca8f7be..a164d8d3ec 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -43,6 +43,7 @@ import { WidgetConfigComponentData } from '@home/models/widget-component.models' import { ComponentStyle, Font, TimewindowStyle } from '@shared/models/widget-settings.models'; import { NULL_UUID } from '@shared/models/id/has-uuid'; import { HasTenantId } from '@shared/models/entity.models'; +import { DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; export enum widgetType { timeseries = 'timeseries', @@ -184,6 +185,7 @@ export interface WidgetTypeParameters { hideDataSettings?: boolean; defaultDataKeysFunction?: (configComponent: any, configData: any) => DataKey[]; defaultLatestDataKeysFunction?: (configComponent: any, configData: any) => DataKey[]; + dataKeySettingsFunction?: DataKeySettingsFunction; displayRpcMessageToast?: boolean; } 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 eacf783c53..a36847b334 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4334,8 +4334,13 @@ "preview": "Preview" }, "tooltip": { + "trigger": "Trigger", + "trigger-point": "Point", + "trigger-axis": "Axis", "value": "Value", "date": "Date", + "show-date-time-interval": "Show date time interval", + "show-date-time-interval-hint": "Show date time interval according to the data aggregation.", "background-color": "Background color", "background-blur": "Background blur" }, @@ -6590,6 +6595,24 @@ "table-tabs": "Table tabs", "show-cell-actions-menu-mobile": "Show cell actions dropdown menu in mobile mode" }, + "time-series-chart": { + "chart": "Chart", + "data-zoom": "Data zoom", + "stack-mode": "Stack mode", + "stack-mode-hint": "Stacks series on the chart. The series with the same unit would be put on top of each other.", + "axes": "Axes", + "series": { + "legend-settings": "Legend settings", + "show-in-legend": "Show in legend", + "show-in-legend-hint": "Show series name and data in legend.", + "hidden-by-default": "Hidden by default", + "hidden-by-default-hint": "Make series hidden in legend by default.", + "series-type": "Series type", + "type": "Type", + "type-line": "Line", + "type-bar": "Bar" + } + }, "wind-speed-direction": { "layout": "Layout", "layout-default": "Default", diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index 524a4e86ac..c3e2599bd9 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -467,6 +467,17 @@ } } } + &.fixed-height { + .mat-mdc-form-field-infix { + max-height: 40px; + .mat-mdc-select { + max-height: 24px; + .mat-mdc-select-trigger { + max-height: 24px; + } + } + } + } } .tb-form-table { @@ -670,4 +681,14 @@ } } } + + .mat-mdc-option { + &.flex { + .mdc-list-item__primary-text { + display: flex; + align-items: center; + justify-content: flex-start; + } + } + } } From 19f5c427e3ebddaa7e9b5670deb9a176cf3ae71e Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 4 Mar 2024 10:04:33 +0200 Subject: [PATCH 296/397] UI: Fixed incorrect cache when open preview public image --- .../src/app/shared/components/image/image-dialog.component.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui-ngx/src/app/shared/components/image/image-dialog.component.ts b/ui-ngx/src/app/shared/components/image/image-dialog.component.ts index b140c6bf32..40e7d2ec89 100644 --- a/ui-ngx/src/app/shared/components/image/image-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/image/image-dialog.component.ts @@ -66,7 +66,7 @@ export class ImageDialogComponent extends this.image = data.image; this.readonly = data.readonly; this.imagePreviewData = { - url: this.image.public ? this.image.publicLink : this.image.link + url: this.image.link }; } @@ -155,8 +155,6 @@ export class ImageDialogComponent extends let url; if (result.base64) { url = result.base64; - } else if (this.image.public) { - url = `${this.image.publicLink}?ts=${new Date().getTime()}`; } else { url = this.image.link; } From fc06a77943dacfd23c68a942acaaeed660f0d7e7 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 4 Mar 2024 16:56:29 +0200 Subject: [PATCH 297/397] UI: Implement time-series chart key settings form. --- .../lib/chart/time-series-chart.models.ts | 55 ++++++ .../widget/lib/chart/time-series-chart.ts | 3 +- ...e-series-chart-bar-settings.component.html | 65 ++++++ ...ime-series-chart-bar-settings.component.ts | 148 ++++++++++++++ ...-series-chart-fill-settings.component.html | 53 +++++ ...me-series-chart-fill-settings.component.ts | 143 ++++++++++++++ ...e-series-chart-key-settings.component.html | 14 +- ...ime-series-chart-key-settings.component.ts | 26 ++- ...-series-chart-line-settings.component.html | 111 +++++++++++ ...me-series-chart-line-settings.component.ts | 187 ++++++++++++++++++ .../lib/settings/widget-settings.module.ts | 19 +- .../assets/locale/locale.constant-en_US.json | 52 ++++- 12 files changed, 864 insertions(+), 12 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-fill-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-fill-settings.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index 3965f69000..c9209b06b4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -96,12 +96,38 @@ export enum TimeSeriesChartShape { none = 'none' } +export const timeSeriesChartShapes = Object.keys(TimeSeriesChartShape) as TimeSeriesChartShape[]; + +export const timeSeriesChartShapeTranslations = new Map( + [ + [TimeSeriesChartShape.emptyCircle, 'widgets.time-series-chart.shape-empty-circle'], + [TimeSeriesChartShape.circle, 'widgets.time-series-chart.shape-circle'], + [TimeSeriesChartShape.rect, 'widgets.time-series-chart.shape-rect'], + [TimeSeriesChartShape.roundRect, 'widgets.time-series-chart.shape-round-rect'], + [TimeSeriesChartShape.triangle, 'widgets.time-series-chart.shape-triangle'], + [TimeSeriesChartShape.diamond, 'widgets.time-series-chart.shape-diamond'], + [TimeSeriesChartShape.pin, 'widgets.time-series-chart.shape-pin'], + [TimeSeriesChartShape.arrow, 'widgets.time-series-chart.shape-arrow'], + [TimeSeriesChartShape.none, 'widgets.time-series-chart.shape-none'] + ] +); + export enum TimeSeriesChartLineType { solid = 'solid', dashed = 'dashed', dotted = 'dotted' } +export const timeSeriesLineTypes = Object.keys(TimeSeriesChartLineType) as TimeSeriesChartLineType[]; + +export const timeSeriesLineTypeTranslations = new Map( + [ + [TimeSeriesChartLineType.solid, 'widgets.time-series-chart.line-type-solid'], + [TimeSeriesChartLineType.dashed, 'widgets.time-series-chart.line-type-dashed'], + [TimeSeriesChartLineType.dotted, 'widgets.time-series-chart.line-type-dotted'] + ] +); + export enum ThresholdLabelPosition { start = 'start', middle = 'middle', @@ -129,17 +155,46 @@ export enum SeriesFillType { gradient = 'gradient' } +export const seriesFillTypes = Object.keys(SeriesFillType) as SeriesFillType[]; + +export const seriesFillTypeTranslations = new Map( + [ + [SeriesFillType.none, 'widgets.time-series-chart.series.fill-type-none'], + [SeriesFillType.opacity, 'widgets.time-series-chart.series.fill-type-opacity'], + [SeriesFillType.gradient, 'widgets.time-series-chart.series.fill-type-gradient'] + ] +); + export enum SeriesLabelPosition { top = 'top', bottom = 'bottom' } +export const seriesLabelPositions = Object.keys(SeriesLabelPosition) as SeriesLabelPosition[]; + +export const seriesLabelPositionTranslations = new Map( + [ + [SeriesLabelPosition.top, 'widgets.time-series-chart.series.label-position-top'], + [SeriesLabelPosition.bottom, 'widgets.time-series-chart.series.label-position-bottom'] + ] +); + export enum LineSeriesStepType { start = 'start', middle = 'middle', end = 'end' } +export const lineSeriesStepTypes = Object.keys(LineSeriesStepType) as LineSeriesStepType[]; + +export const lineSeriesStepTypeTranslations = new Map( + [ + [LineSeriesStepType.start, 'widgets.time-series-chart.series.line.step-type-start'], + [LineSeriesStepType.middle, 'widgets.time-series-chart.series.line.step-type-middle'], + [LineSeriesStepType.end, 'widgets.time-series-chart.series.line.step-type-end'] + ] +); + export enum TimeSeriesChartSeriesType { line = 'line', bar = 'bar' diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index c36327fec6..08761fbe36 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -259,8 +259,7 @@ export class TbTimeSeriesChart { timeSeriesChartKeyDefaultSettings, dataKey.settings); if ((keySettings.type === TimeSeriesChartSeriesType.line && keySettings.lineSettings.showPointLabel && keySettings.lineSettings.pointLabelPosition === SeriesLabelPosition.top) || - (keySettings.type === TimeSeriesChartSeriesType.bar && keySettings.barSettings.showLabel && - keySettings.barSettings.labelPosition === SeriesLabelPosition.top)) { + (keySettings.type === TimeSeriesChartSeriesType.bar && keySettings.barSettings.showLabel)) { this.topPointLabels = true; } dataKey.settings = keySettings; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.html new file mode 100644 index 0000000000..a62157dba5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.html @@ -0,0 +1,65 @@ + + +
    + + {{ 'widgets.time-series-chart.series.bar.show-border' | translate }} + +
    +
    +
    widgets.time-series-chart.series.bar.border-width
    + + + +
    +
    +
    widgets.time-series-chart.series.bar.border-radius
    + + + +
    +
    + +
    + {{ 'widgets.time-series-chart.series.bar.label' | translate }} +
    +
    +
    + + + + {{ seriesLabelPositionTranslations.get(position) | translate }} + + + + + + + +
    +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.ts new file mode 100644 index 0000000000..b42cec925a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.ts @@ -0,0 +1,148 @@ +/// +/// 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, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormGroup, + Validators +} from '@angular/forms'; +import { + BarSeriesSettings, + seriesLabelPositions, + seriesLabelPositionTranslations +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { merge } from 'rxjs'; +import { formatValue, isDefinedAndNotNull } from '@core/utils'; +import { DataKeyConfigComponent } from '@home/components/widget/config/data-key-config.component'; + +@Component({ + selector: 'tb-time-series-chart-bar-settings', + templateUrl: './time-series-chart-bar-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartBarSettingsComponent), + multi: true + } + ] +}) +export class TimeSeriesChartBarSettingsComponent implements OnInit, ControlValueAccessor { + + seriesLabelPositions = seriesLabelPositions; + + seriesLabelPositionTranslations = seriesLabelPositionTranslations; + + labelPreviewFn = this._labelPreviewFn.bind(this); + + @Input() + disabled: boolean; + + private modelValue: BarSeriesSettings; + + private propagateChange = null; + + public barSettingsFormGroup: UntypedFormGroup; + + constructor(protected store: Store, + private dataKeyConfigComponent: DataKeyConfigComponent, + private fb: UntypedFormBuilder) { + } + + ngOnInit(): void { + this.barSettingsFormGroup = this.fb.group({ + showBorder: [null, []], + borderWidth: [null, [Validators.min(0)]], + borderRadius: [null, [Validators.min(0)]], + showLabel: [null, []], + labelPosition: [null, []], + labelFont: [null, []], + labelColor: [null, []], + backgroundSettings: [null, []] + }); + this.barSettingsFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + }); + merge(this.barSettingsFormGroup.get('showBorder').valueChanges, + this.barSettingsFormGroup.get('showLabel').valueChanges) + .subscribe(() => { + this.updateValidators(); + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(_fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.barSettingsFormGroup.disable({emitEvent: false}); + } else { + this.barSettingsFormGroup.enable({emitEvent: false}); + this.updateValidators(); + } + } + + writeValue(value: BarSeriesSettings): void { + this.modelValue = value; + this.barSettingsFormGroup.patchValue( + value, {emitEvent: false} + ); + this.updateValidators(); + } + + private updateValidators() { + const showBorder: boolean = this.barSettingsFormGroup.get('showBorder').value; + const showLabel: boolean = this.barSettingsFormGroup.get('showLabel').value; + if (showBorder) { + this.barSettingsFormGroup.get('borderWidth').enable({emitEvent: false}); + } else { + this.barSettingsFormGroup.get('borderWidth').disable({emitEvent: false}); + } + if (showLabel) { + this.barSettingsFormGroup.get('labelPosition').enable({emitEvent: false}); + this.barSettingsFormGroup.get('labelFont').enable({emitEvent: false}); + this.barSettingsFormGroup.get('labelColor').enable({emitEvent: false}); + } else { + this.barSettingsFormGroup.get('labelPosition').disable({emitEvent: false}); + this.barSettingsFormGroup.get('labelFont').disable({emitEvent: false}); + this.barSettingsFormGroup.get('labelColor').disable({emitEvent: false}); + } + } + + private updateModel() { + this.modelValue = this.barSettingsFormGroup.getRawValue(); + this.propagateChange(this.modelValue); + } + + private _labelPreviewFn(): string { + const dataKey = this.dataKeyConfigComponent.modelValue; + const widgetConfig = this.dataKeyConfigComponent.widgetConfig; + const units = dataKey.units && dataKey.units.length ? dataKey.units : widgetConfig.config.units; + const decimals = isDefinedAndNotNull(dataKey.decimals) ? dataKey.decimals : + (isDefinedAndNotNull(widgetConfig.config.decimals) ? widgetConfig.config.decimals : 2); + return formatValue(22, decimals, units, false); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-fill-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-fill-settings.component.html new file mode 100644 index 0000000000..934f985483 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-fill-settings.component.html @@ -0,0 +1,53 @@ + + +
    +
    +
    {{ title | translate }}
    + + {{ seriesFillTypeTranslationMap.get(type) | translate }} + +
    + +
    +
    widgets.time-series-chart.series.opacity
    + + + +
    +
    + +
    +
    widgets.time-series-chart.series.gradient-stops
    +
    +
    widgets.time-series-chart.series.gradient-start
    + + + +
    widgets.time-series-chart.series.gradient-end
    + + + +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-fill-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-fill-settings.component.ts new file mode 100644 index 0000000000..44cc870f5b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-fill-settings.component.ts @@ -0,0 +1,143 @@ +/// +/// 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, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormGroup, + Validators +} from '@angular/forms'; +import { + SeriesFillSettings, + SeriesFillType, + seriesFillTypes, + seriesFillTypeTranslations +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; + +@Component({ + selector: 'tb-time-series-chart-fill-settings', + templateUrl: './time-series-chart-fill-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartFillSettingsComponent), + multi: true + } + ] +}) +export class TimeSeriesChartFillSettingsComponent implements OnInit, ControlValueAccessor { + + seriesFillTypes = seriesFillTypes; + + seriesFillTypeTranslationMap: Map = new Map([]); + + SeriesFillType = SeriesFillType; + + @Input() + disabled: boolean; + + @Input() + title = 'widgets.time-series-chart.series.fill'; + + @Input() + fillNoneTitle = 'widgets.time-series-chart.series.fill-type-none'; + + private modelValue: SeriesFillSettings; + + private propagateChange = null; + + public fillSettingsFormGroup: UntypedFormGroup; + + constructor(protected store: Store, + private fb: UntypedFormBuilder) { + } + + ngOnInit(): void { + this.fillSettingsFormGroup = this.fb.group({ + type: [null, []], + opacity: [null, [Validators.min(0), Validators.max(100)]], + gradient: this.fb.group({ + start: [null, [Validators.min(0), Validators.max(100)]], + end: [null, [Validators.min(0), Validators.max(100)]] + }) + }); + this.fillSettingsFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + }); + this.fillSettingsFormGroup.get('type').valueChanges.subscribe(() => { + this.updateValidators(); + }); + for (const type of seriesFillTypes) { + let translation: string; + if (type === SeriesFillType.none) { + translation = this.fillNoneTitle; + } else { + translation = seriesFillTypeTranslations.get(type); + } + this.seriesFillTypeTranslationMap.set(type, translation); + } + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(_fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.fillSettingsFormGroup.disable({emitEvent: false}); + } else { + this.fillSettingsFormGroup.enable({emitEvent: false}); + this.updateValidators(); + } + } + + writeValue(value: SeriesFillSettings): void { + this.modelValue = value; + this.fillSettingsFormGroup.patchValue( + value, {emitEvent: false} + ); + this.updateValidators(); + } + + private updateValidators() { + const type: SeriesFillType = this.fillSettingsFormGroup.get('type').value; + if (type === SeriesFillType.none) { + this.fillSettingsFormGroup.get('opacity').disable({emitEvent: false}); + this.fillSettingsFormGroup.get('gradient').disable({emitEvent: false}); + } else if (type === SeriesFillType.opacity) { + this.fillSettingsFormGroup.get('opacity').enable({emitEvent: false}); + this.fillSettingsFormGroup.get('gradient').disable({emitEvent: false}); + } else if (type === SeriesFillType.gradient) { + this.fillSettingsFormGroup.get('opacity').disable({emitEvent: false}); + this.fillSettingsFormGroup.get('gradient').enable({emitEvent: false}); + } + } + + private updateModel() { + const value: SeriesFillSettings = this.fillSettingsFormGroup.getRawValue(); + this.modelValue = value; + this.propagateChange(this.modelValue); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html index b1d5d3d302..313894d7df 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html @@ -30,7 +30,17 @@
    -
    widgets.time-series-chart.series.series-type
    - TODO: +
    +
    widgets.time-series-chart.series.series-type
    + + {{ timeSeriesChartSeriesTypeTranslations.get(type) | translate }} + +
    + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts index 8f266fa9b6..24fb200b0b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts @@ -22,7 +22,10 @@ import { AppState } from '@core/core.state'; import { mergeDeep } from '@core/utils'; import { timeSeriesChartKeyDefaultSettings, - TimeSeriesChartKeySettings + TimeSeriesChartKeySettings, + TimeSeriesChartSeriesType, + timeSeriesChartSeriesTypes, + timeSeriesChartSeriesTypeTranslations } from '@home/components/widget/lib/chart/time-series-chart.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models'; @@ -33,6 +36,12 @@ import { WidgetConfigComponentData } from '@home/models/widget-component.models' }) export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent { + TimeSeriesChartSeriesType = TimeSeriesChartSeriesType; + + timeSeriesChartSeriesTypes = timeSeriesChartSeriesTypes; + + timeSeriesChartSeriesTypeTranslations = timeSeriesChartSeriesTypeTranslations; + timeSeriesChartKeySettingsForm: UntypedFormGroup; constructor(protected store: Store, @@ -60,23 +69,30 @@ export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent showInLegend: [seriesSettings.showInLegend, []], dataHiddenByDefault: [seriesSettings.dataHiddenByDefault, []], type: [seriesSettings.type, []], - lineSettings: [settings.lineSettings, []], - barSettings: [settings.barSettings, []] + lineSettings: [seriesSettings.lineSettings, []], + barSettings: [seriesSettings.barSettings, []] }); } protected validatorTriggers(): string[] { - return ['showInLegend']; + return ['showInLegend', 'type']; } protected updateValidators(_emitEvent: boolean) { const showInLegend: boolean = this.timeSeriesChartKeySettingsForm.get('showInLegend').value; + const type: TimeSeriesChartSeriesType = this.timeSeriesChartKeySettingsForm.get('type').value; if (showInLegend) { this.timeSeriesChartKeySettingsForm.get('dataHiddenByDefault').enable(); } else { this.timeSeriesChartKeySettingsForm.get('dataHiddenByDefault').patchValue(false, {emitEvent: false}); this.timeSeriesChartKeySettingsForm.get('dataHiddenByDefault').disable(); } + if (type === TimeSeriesChartSeriesType.line) { + this.timeSeriesChartKeySettingsForm.get('lineSettings').enable(); + this.timeSeriesChartKeySettingsForm.get('barSettings').disable(); + } else if (type === TimeSeriesChartSeriesType.bar) { + this.timeSeriesChartKeySettingsForm.get('lineSettings').disable(); + this.timeSeriesChartKeySettingsForm.get('barSettings').enable(); + } } - } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.html new file mode 100644 index 0000000000..298997c4f9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.html @@ -0,0 +1,111 @@ + + +
    +
    widgets.time-series-chart.series.line.line
    +
    + + {{ 'widgets.time-series-chart.series.line.show-line' | translate }} + +
    +
    + + {{ 'widgets.time-series-chart.series.line.step-line' | translate }} + + + + + {{ lineSeriesStepTypeTranslations.get(stepType) | translate }} + + + +
    +
    + + {{ 'widgets.time-series-chart.series.line.smooth-line' | translate }} + +
    +
    +
    widgets.time-series-chart.line-type
    + + + + {{ timeSeriesLineTypeTranslations.get(lineType) | translate }} + + + +
    +
    +
    widgets.time-series-chart.line-width
    + + + +
    +
    +
    +
    widgets.time-series-chart.series.point.points
    +
    + + {{ 'widgets.time-series-chart.series.point.show-points' | translate }} + +
    +
    + +
    + {{ 'widgets.time-series-chart.series.point.point-label' | translate }} +
    +
    +
    + + + + {{ seriesLabelPositionTranslations.get(position) | translate }} + + + + + + + +
    +
    +
    +
    widgets.time-series-chart.series.point.point-shape
    + + + + {{ timeSeriesChartShapeTranslations.get(shape) | translate }} + + + +
    +
    +
    widgets.time-series-chart.series.point.point-size
    + + + +
    +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts new file mode 100644 index 0000000000..46a75edc08 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts @@ -0,0 +1,187 @@ +/// +/// 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, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormGroup, + Validators +} from '@angular/forms'; +import { + LineSeriesSettings, + lineSeriesStepTypes, + lineSeriesStepTypeTranslations, + seriesLabelPositions, + seriesLabelPositionTranslations, + timeSeriesChartShapes, + timeSeriesChartShapeTranslations, + timeSeriesLineTypes, + timeSeriesLineTypeTranslations +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { merge } from 'rxjs'; +import { formatValue, isDefinedAndNotNull } from '@core/utils'; +import { DataKeyConfigComponent } from '@home/components/widget/config/data-key-config.component'; + +@Component({ + selector: 'tb-time-series-chart-line-settings', + templateUrl: './time-series-chart-line-settings.component.html', + styleUrls: ['./../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartLineSettingsComponent), + multi: true + } + ] +}) +export class TimeSeriesChartLineSettingsComponent implements OnInit, ControlValueAccessor { + + lineSeriesStepTypes = lineSeriesStepTypes; + + lineSeriesStepTypeTranslations = lineSeriesStepTypeTranslations; + + timeSeriesLineTypes = timeSeriesLineTypes; + + timeSeriesLineTypeTranslations = timeSeriesLineTypeTranslations; + + seriesLabelPositions = seriesLabelPositions; + + seriesLabelPositionTranslations = seriesLabelPositionTranslations; + + timeSeriesChartShapes = timeSeriesChartShapes; + + timeSeriesChartShapeTranslations = timeSeriesChartShapeTranslations; + + pointLabelPreviewFn = this._pointLabelPreviewFn.bind(this); + + @Input() + disabled: boolean; + + private modelValue: LineSeriesSettings; + + private propagateChange = null; + + public lineSettingsFormGroup: UntypedFormGroup; + + constructor(protected store: Store, + private dataKeyConfigComponent: DataKeyConfigComponent, + private fb: UntypedFormBuilder) { + } + + ngOnInit(): void { + this.lineSettingsFormGroup = this.fb.group({ + showLine: [null, []], + step: [null, []], + stepType: [null, []], + smooth: [null, []], + lineType: [null, []], + lineWidth: [null, [Validators.min(0)]], + showPoints: [null, []], + showPointLabel: [null, []], + pointLabelPosition: [null, []], + pointLabelFont: [null, []], + pointLabelColor: [null, []], + pointShape: [null, []], + pointSize: [null, [Validators.min(0)]], + fillAreaSettings: [null, []] + }); + this.lineSettingsFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + }); + merge(this.lineSettingsFormGroup.get('showLine').valueChanges, + this.lineSettingsFormGroup.get('step').valueChanges, + this.lineSettingsFormGroup.get('showPointLabel').valueChanges) + .subscribe(() => { + this.updateValidators(); + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(_fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.lineSettingsFormGroup.disable({emitEvent: false}); + } else { + this.lineSettingsFormGroup.enable({emitEvent: false}); + this.updateValidators(); + } + } + + writeValue(value: LineSeriesSettings): void { + this.modelValue = value; + this.lineSettingsFormGroup.patchValue( + value, {emitEvent: false} + ); + this.updateValidators(); + } + + private updateValidators() { + const showLine: boolean = this.lineSettingsFormGroup.get('showLine').value; + const step: boolean = this.lineSettingsFormGroup.get('step').value; + const showPointLabel: boolean = this.lineSettingsFormGroup.get('showPointLabel').value; + if (showLine) { + this.lineSettingsFormGroup.get('step').enable({emitEvent: false}); + if (step) { + this.lineSettingsFormGroup.get('stepType').enable({emitEvent: false}); + this.lineSettingsFormGroup.get('smooth').disable({emitEvent: false}); + } else { + this.lineSettingsFormGroup.get('stepType').disable({emitEvent: false}); + this.lineSettingsFormGroup.get('smooth').enable({emitEvent: false}); + } + this.lineSettingsFormGroup.get('lineType').enable({emitEvent: false}); + this.lineSettingsFormGroup.get('lineWidth').enable({emitEvent: false}); + } else { + this.lineSettingsFormGroup.get('step').disable({emitEvent: false}); + this.lineSettingsFormGroup.get('stepType').disable({emitEvent: false}); + this.lineSettingsFormGroup.get('smooth').disable({emitEvent: false}); + this.lineSettingsFormGroup.get('lineType').disable({emitEvent: false}); + this.lineSettingsFormGroup.get('lineWidth').disable({emitEvent: false}); + } + if (showPointLabel) { + this.lineSettingsFormGroup.get('pointLabelPosition').enable({emitEvent: false}); + this.lineSettingsFormGroup.get('pointLabelFont').enable({emitEvent: false}); + this.lineSettingsFormGroup.get('pointLabelColor').enable({emitEvent: false}); + } else { + this.lineSettingsFormGroup.get('pointLabelPosition').disable({emitEvent: false}); + this.lineSettingsFormGroup.get('pointLabelFont').disable({emitEvent: false}); + this.lineSettingsFormGroup.get('pointLabelColor').disable({emitEvent: false}); + } + } + + private updateModel() { + this.modelValue = this.lineSettingsFormGroup.getRawValue(); + this.propagateChange(this.modelValue); + } + + private _pointLabelPreviewFn(): string { + const dataKey = this.dataKeyConfigComponent.modelValue; + const widgetConfig = this.dataKeyConfigComponent.widgetConfig; + const units = dataKey.units && dataKey.units.length ? dataKey.units : widgetConfig.config.units; + const decimals = isDefinedAndNotNull(dataKey.decimals) ? dataKey.decimals : + (isDefinedAndNotNull(widgetConfig.config.decimals) ? widgetConfig.config.decimals : 2); + return formatValue(22, decimals, units, false); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts index 4183a06db2..6cc766f2ab 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts @@ -333,6 +333,15 @@ import { import { TimeSeriesChartKeySettingsComponent } from '@home/components/widget/lib/settings/chart/time-series-chart-key-settings.component'; +import { + TimeSeriesChartLineSettingsComponent +} from '@home/components/widget/lib/settings/chart/time-series-chart-line-settings.component'; +import { + TimeSeriesChartFillSettingsComponent +} from '@home/components/widget/lib/settings/chart/time-series-chart-fill-settings.component'; +import { + TimeSeriesChartBarSettingsComponent +} from '@home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component'; @NgModule({ declarations: [ @@ -452,7 +461,10 @@ import { PowerButtonWidgetSettingsComponent, SliderWidgetSettingsComponent, ToggleButtonWidgetSettingsComponent, - TimeSeriesChartKeySettingsComponent + TimeSeriesChartKeySettingsComponent, + TimeSeriesChartLineSettingsComponent, + TimeSeriesChartBarSettingsComponent, + TimeSeriesChartFillSettingsComponent ], imports: [ CommonModule, @@ -577,7 +589,10 @@ import { PowerButtonWidgetSettingsComponent, SliderWidgetSettingsComponent, ToggleButtonWidgetSettingsComponent, - TimeSeriesChartKeySettingsComponent + TimeSeriesChartKeySettingsComponent, + TimeSeriesChartLineSettingsComponent, + TimeSeriesChartBarSettingsComponent, + TimeSeriesChartFillSettingsComponent ] }) export class WidgetSettingsModule { 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 a36847b334..1e3370ab84 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6601,6 +6601,20 @@ "stack-mode": "Stack mode", "stack-mode-hint": "Stacks series on the chart. The series with the same unit would be put on top of each other.", "axes": "Axes", + "line-type": "Line type", + "line-type-solid": "Solid", + "line-type-dashed": "Dashed", + "line-type-dotted": "Dotted", + "line-width": "Line width", + "shape-empty-circle": "Empty circle", + "shape-circle": "Circle", + "shape-rect": "Rectangle", + "shape-round-rect": "Rounded rectangle", + "shape-triangle": "Triangle", + "shape-diamond": "Diamond", + "shape-pin": "Pin", + "shape-arrow": "Arrow", + "shape-none": "None", "series": { "legend-settings": "Legend settings", "show-in-legend": "Show in legend", @@ -6610,7 +6624,43 @@ "series-type": "Series type", "type": "Type", "type-line": "Line", - "type-bar": "Bar" + "type-bar": "Bar", + "label-position-top": "Top", + "label-position-bottom": "Bottom", + "fill": "Fill", + "background": "Background", + "fill-type-none": "None", + "fill-type-solid": "Solid", + "fill-type-opacity": "Opacity", + "fill-type-gradient": "Gradient", + "opacity": "Opacity", + "gradient-stops": "Gradient stops", + "gradient-start": "start", + "gradient-end": "end", + "line": { + "line": "Line", + "show-line": "Show line", + "step-line": "Step line", + "step-type-start": "Start", + "step-type-middle": "Middle", + "step-type-end": "End", + "smooth-line": "Smooth line" + }, + "point": { + "points": "Points", + "show-points": "Show points", + "point-label": "Point label", + "point-label-hint": "Display label with value over the series point.", + "point-shape": "Point shape", + "point-size": "Point size" + }, + "bar": { + "show-border": "Show border", + "border-width": "Border width", + "border-radius": "Border radius", + "label": "Label", + "label-hint": "Display label with value over the bar." + } } }, "wind-speed-direction": { From 02c9fe3f820b48dc2a20bcbc84405f07980af15c Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 4 Mar 2024 18:08:32 +0200 Subject: [PATCH 298/397] Deep copy of object before to inlineImageForEdge in order to correctly work with cached values --- .../rpc/constructor/asset/AssetMsgConstructorV1.java | 5 +++-- .../dashboard/DashboardMsgConstructorV1.java | 5 +++-- .../rpc/constructor/device/DeviceMsgConstructorV1.java | 5 +++-- .../rpc/constructor/widget/WidgetMsgConstructorV1.java | 10 ++++++---- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java index acdd3f506a..02318b1aaa 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java @@ -63,7 +63,8 @@ public class AssetMsgConstructorV1 extends BaseAssetMsgConstructor { @Override public AssetProfileUpdateMsg constructAssetProfileUpdatedMsg(UpdateMsgType msgType, AssetProfile assetProfile) { - imageService.inlineImageForEdge(assetProfile); + AssetProfile copy = JacksonUtil.clone(assetProfile); + imageService.inlineImageForEdge(copy); AssetProfileUpdateMsg.Builder builder = AssetProfileUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(assetProfile.getId().getId().getMostSignificantBits()) @@ -81,7 +82,7 @@ public class AssetMsgConstructorV1 extends BaseAssetMsgConstructor { builder.setDescription(assetProfile.getDescription()); } if (assetProfile.getImage() != null) { - builder.setImage(ByteString.copyFrom(assetProfile.getImage().getBytes(StandardCharsets.UTF_8))); + builder.setImage(ByteString.copyFrom(copy.getImage().getBytes(StandardCharsets.UTF_8))); } if (assetProfile.getDefaultEdgeRuleChainId() != null) { builder.setDefaultRuleChainIdMSB(assetProfile.getDefaultEdgeRuleChainId().getId().getMostSignificantBits()) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java index 3df0d6563f..f94b165e2d 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java @@ -33,7 +33,8 @@ public class DashboardMsgConstructorV1 extends BaseDashboardMsgConstructor { @Override public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) { - imageService.inlineImagesForEdge(dashboard); + Dashboard copy = JacksonUtil.clone(dashboard); + imageService.inlineImagesForEdge(copy); DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(dashboard.getId().getId().getMostSignificantBits()) @@ -45,7 +46,7 @@ public class DashboardMsgConstructorV1 extends BaseDashboardMsgConstructor { builder.setAssignedCustomers(JacksonUtil.toString(dashboard.getAssignedCustomers())); } if (dashboard.getImage() != null) { - builder.setImage(dashboard.getImage()); + builder.setImage(copy.getImage()); } if (dashboard.getMobileOrder() != null) { builder.setMobileOrder(dashboard.getMobileOrder()); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java index 35c07abc5a..3c6552f9d3 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java @@ -95,7 +95,8 @@ public class DeviceMsgConstructorV1 extends BaseDeviceMsgConstructor { @Override public DeviceProfileUpdateMsg constructDeviceProfileUpdatedMsg(UpdateMsgType msgType, DeviceProfile deviceProfile) { - imageService.inlineImageForEdge(deviceProfile); + DeviceProfile copy = JacksonUtil.clone(deviceProfile); + imageService.inlineImageForEdge(copy); DeviceProfileUpdateMsg.Builder builder = DeviceProfileUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(deviceProfile.getId().getId().getMostSignificantBits()) @@ -120,7 +121,7 @@ public class DeviceMsgConstructorV1 extends BaseDeviceMsgConstructor { builder.setProvisionDeviceKey(deviceProfile.getProvisionDeviceKey()); } if (deviceProfile.getImage() != null) { - builder.setImage(ByteString.copyFrom(deviceProfile.getImage().getBytes(StandardCharsets.UTF_8))); + builder.setImage(ByteString.copyFrom(copy.getImage().getBytes(StandardCharsets.UTF_8))); } if (deviceProfile.getFirmwareId() != null) { builder.setFirmwareIdMSB(deviceProfile.getFirmwareId().getId().getMostSignificantBits()) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/widget/WidgetMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/widget/WidgetMsgConstructorV1.java index 92fdb32fee..068378bea6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/widget/WidgetMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/widget/WidgetMsgConstructorV1.java @@ -43,7 +43,8 @@ public class WidgetMsgConstructorV1 extends BaseWidgetMsgConstructor { @Override public WidgetsBundleUpdateMsg constructWidgetsBundleUpdateMsg(UpdateMsgType msgType, WidgetsBundle widgetsBundle, List widgets) { - imageService.inlineImageForEdge(widgetsBundle); + WidgetsBundle copy = JacksonUtil.clone(widgetsBundle); + imageService.inlineImageForEdge(copy); WidgetsBundleUpdateMsg.Builder builder = WidgetsBundleUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(widgetsBundle.getId().getId().getMostSignificantBits()) @@ -51,7 +52,7 @@ public class WidgetMsgConstructorV1 extends BaseWidgetMsgConstructor { .setTitle(widgetsBundle.getTitle()) .setAlias(widgetsBundle.getAlias()); if (widgetsBundle.getImage() != null) { - builder.setImage(ByteString.copyFrom(widgetsBundle.getImage().getBytes(StandardCharsets.UTF_8))); + builder.setImage(ByteString.copyFrom(copy.getImage().getBytes(StandardCharsets.UTF_8))); } if (widgetsBundle.getDescription() != null) { builder.setDescription(widgetsBundle.getDescription()); @@ -68,7 +69,8 @@ public class WidgetMsgConstructorV1 extends BaseWidgetMsgConstructor { @Override public WidgetTypeUpdateMsg constructWidgetTypeUpdateMsg(UpdateMsgType msgType, WidgetTypeDetails widgetTypeDetails, EdgeVersion edgeVersion) { - imageService.inlineImagesForEdge(widgetTypeDetails); + WidgetTypeDetails copy = JacksonUtil.clone(widgetTypeDetails); + imageService.inlineImagesForEdge(copy); WidgetTypeUpdateMsg.Builder builder = WidgetTypeUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(widgetTypeDetails.getId().getId().getMostSignificantBits()) @@ -93,7 +95,7 @@ public class WidgetMsgConstructorV1 extends BaseWidgetMsgConstructor { builder.setIsSystem(true); } if (widgetTypeDetails.getImage() != null) { - builder.setImage(widgetTypeDetails.getImage()); + builder.setImage(copy.getImage()); } if (widgetTypeDetails.getDescription() != null) { if (EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_6_0) && From 0c09de5dc19fe3d974708fe2cbb940125cd531dc Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 4 Mar 2024 18:14:23 +0200 Subject: [PATCH 299/397] UI: Implement time series chart axes settings. --- ...e-series-chart-basic-config.component.html | 16 +- .../lib/chart/time-series-chart.models.ts | 11 ++ ...-series-chart-axis-settings.component.html | 122 ++++++++++++ ...me-series-chart-axis-settings.component.ts | 179 ++++++++++++++++++ .../common/widget-settings-common.module.ts | 9 +- .../assets/locale/locale.constant-en_US.json | 21 ++ ui-ngx/src/form.scss | 3 + 7 files changed, 352 insertions(+), 9 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html index 26f0f222d9..4fd7de467f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html @@ -100,13 +100,15 @@
    -
    widgets.time-series-chart.axes
    -
    - TODO: Y Axis -
    -
    - TODO: X Axis -
    +
    widgets.time-series-chart.axis.axes
    + + + +
    ( + [ + [AxisPosition.left, 'widgets.time-series-chart.axis.position-left'], + [AxisPosition.right, 'widgets.time-series-chart.axis.position-right'], + [AxisPosition.top, 'widgets.time-series-chart.axis.position-top'], + [AxisPosition.bottom, 'widgets.time-series-chart.axis.position-bottom'] + ] +); + export enum TimeSeriesChartShape { emptyCircle = 'emptyCircle', circle = 'circle', diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html new file mode 100644 index 0000000000..8a77a92b19 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html @@ -0,0 +1,122 @@ + + +
    + + + + + {{ axisTitle | translate }} + + + + +
    +
    widgets.time-series-chart.axis.label
    +
    + + + + + + + +
    +
    +
    +
    widgets.time-series-chart.axis.position
    + + + + {{ timeSeriesAxisPositionTranslations.get(position) | translate }} + + + +
    +
    + +
    widgets.time-series-chart.axis.tick-labels
    +
    +
    + + + + +
    +
    +
    + + {{ 'widgets.time-series-chart.axis.show-ticks' | translate }} + + + +
    +
    + + {{ 'widgets.time-series-chart.axis.show-line' | translate }} + + + +
    +
    + +
    + {{ 'widgets.time-series-chart.axis.show-split-lines' | translate }} +
    +
    + + +
    +
    +
    +
    +
    +
    widgets.time-series-chart.axis.scale
    +
    +
    widgets.time-series-chart.axis.scale-min
    + + + +
    widgets.time-series-chart.axis.scale-max
    + + + +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts new file mode 100644 index 0000000000..2ae330c276 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts @@ -0,0 +1,179 @@ +/// +/// 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, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { + AxisPosition, + timeSeriesAxisPositionTranslations, + TimeSeriesChartAxisSettings, + TimeSeriesChartYAxisSettings +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { merge } from 'rxjs'; + +@Component({ + selector: 'tb-time-series-chart-axis-settings', + templateUrl: './time-series-chart-axis-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartAxisSettingsComponent), + multi: true + } + ] +}) +export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValueAccessor { + + settingsExpanded = false; + + axisTitle: string; + + axisPositions: AxisPosition[]; + + timeSeriesAxisPositionTranslations = timeSeriesAxisPositionTranslations; + + @Input() + disabled: boolean; + + @Input() + axisType: 'xAxis' | 'yAxis' = 'xAxis'; + + private modelValue: TimeSeriesChartAxisSettings | TimeSeriesChartYAxisSettings; + + private propagateChange = null; + + public axisSettingsFormGroup: UntypedFormGroup; + + constructor(protected store: Store, + private fb: UntypedFormBuilder) { + } + + ngOnInit(): void { + + this.axisTitle = this.axisType === 'xAxis' ? 'widgets.time-series-chart.axis.x-axis' : 'widgets.time-series-chart.axis.y-axis'; + + this.axisPositions = this.axisType === 'xAxis' ? [AxisPosition.top, AxisPosition.bottom] : + [AxisPosition.left, AxisPosition.right]; + + this.axisSettingsFormGroup = this.fb.group({ + show: [null, []], + label: [null, []], + labelFont: [null, []], + labelColor: [null, []], + position: [null, []], + showTickLabels: [null, []], + tickLabelFont: [null, []], + tickLabelColor: [null, []], + showTicks: [null, []], + ticksColor: [null, []], + showLine: [null, []], + lineColor: [null, []], + showSplitLines: [null, []], + splitLinesColor: [null, []] + }); + if (this.axisType === 'yAxis') { + this.axisSettingsFormGroup.addControl('min', this.fb.control(null, [])); + this.axisSettingsFormGroup.addControl('max', this.fb.control(null, [])); + } + this.axisSettingsFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + }); + merge(this.axisSettingsFormGroup.get('show').valueChanges, + this.axisSettingsFormGroup.get('showTickLabels').valueChanges, + this.axisSettingsFormGroup.get('showTicks').valueChanges, + this.axisSettingsFormGroup.get('showLine').valueChanges, + this.axisSettingsFormGroup.get('showSplitLines').valueChanges) + .subscribe(() => { + this.updateValidators(); + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(_fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.axisSettingsFormGroup.disable({emitEvent: false}); + } else { + this.axisSettingsFormGroup.enable({emitEvent: false}); + this.updateValidators(); + } + } + + writeValue(value: TimeSeriesChartAxisSettings | TimeSeriesChartYAxisSettings): void { + this.modelValue = value; + this.axisSettingsFormGroup.patchValue( + value, {emitEvent: false} + ); + this.updateValidators(); + this.axisSettingsFormGroup.get('show').valueChanges.subscribe((show) => { + this.settingsExpanded = show; + }); + } + + private updateValidators() { + const show: boolean = this.axisSettingsFormGroup.get('show').value; + const showTickLabels: boolean = this.axisSettingsFormGroup.get('showTickLabels').value; + const showTicks: boolean = this.axisSettingsFormGroup.get('showTicks').value; + const showLine: boolean = this.axisSettingsFormGroup.get('showLine').value; + const showSplitLines: boolean = this.axisSettingsFormGroup.get('showSplitLines').value; + if (show) { + this.axisSettingsFormGroup.enable({emitEvent: false}); + if (showTickLabels) { + this.axisSettingsFormGroup.get('tickLabelFont').enable({emitEvent: false}); + this.axisSettingsFormGroup.get('tickLabelColor').enable({emitEvent: false}); + } else { + this.axisSettingsFormGroup.get('tickLabelFont').disable({emitEvent: false}); + this.axisSettingsFormGroup.get('tickLabelColor').disable({emitEvent: false}); + } + if (showTicks) { + this.axisSettingsFormGroup.get('ticksColor').enable({emitEvent: false}); + } else { + this.axisSettingsFormGroup.get('ticksColor').disable({emitEvent: false}); + } + if (showLine) { + this.axisSettingsFormGroup.get('lineColor').enable({emitEvent: false}); + } else { + this.axisSettingsFormGroup.get('lineColor').disable({emitEvent: false}); + } + if (showSplitLines) { + this.axisSettingsFormGroup.get('splitLinesColor').enable({emitEvent: false}); + } else { + this.axisSettingsFormGroup.get('splitLinesColor').disable({emitEvent: false}); + } + } else { + this.axisSettingsFormGroup.disable({emitEvent: false}); + this.axisSettingsFormGroup.get('show').enable({emitEvent: false}); + if (this.axisType === 'yAxis') { + this.axisSettingsFormGroup.get('min').enable({emitEvent: false}); + this.axisSettingsFormGroup.get('max').enable({emitEvent: false}); + } + } + } + + private updateModel() { + this.modelValue = this.axisSettingsFormGroup.getRawValue(); + this.propagateChange(this.modelValue); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts index e39c079f75..a7922dfdc4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts @@ -92,6 +92,9 @@ import { import { WidgetButtonCustomStylePanelComponent } from '@home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component'; +import { + TimeSeriesChartAxisSettingsComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component'; @NgModule({ declarations: [ @@ -127,7 +130,8 @@ import { WidgetActionSettingsPanelComponent, WidgetButtonAppearanceComponent, WidgetButtonCustomStyleComponent, - WidgetButtonCustomStylePanelComponent + WidgetButtonCustomStylePanelComponent, + TimeSeriesChartAxisSettingsComponent ], imports: [ CommonModule, @@ -167,7 +171,8 @@ import { WidgetActionSettingsPanelComponent, WidgetButtonAppearanceComponent, WidgetButtonCustomStyleComponent, - WidgetButtonCustomStylePanelComponent + WidgetButtonCustomStylePanelComponent, + TimeSeriesChartAxisSettingsComponent ], providers: [ ColorSettingsComponentService, 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 1e3370ab84..4a05e1c3c1 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6615,6 +6615,27 @@ "shape-pin": "Pin", "shape-arrow": "Arrow", "shape-none": "None", + "axis": { + "axes": "Axes", + "x-axis": "X axis", + "y-axis": "Y axis", + "label": "Label", + "position": "Position", + "position-left": "Left", + "position-right": "Right", + "position-top": "Top", + "position-bottom": "Bottom", + "tick-labels": "Tick labels", + "show-ticks": "Show ticks", + "show-line": "Show line", + "show-split-lines": "Show split lines", + "show-split-lines-x-axis-hint": "If enabled, the vertical lines on the chart will be shown.", + "show-split-lines-y-axis-hint": "If enabled, the horizontal lines on the chart will be shown.", + "scale": "Scale", + "scale-min": "min", + "scale-max": "max", + "scale-auto": "Auto" + }, "series": { "legend-settings": "Legend settings", "show-in-legend": "Show in legend", diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index c3e2599bd9..dfe6667afd 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -55,6 +55,9 @@ &.no-padding-bottom { padding-bottom: 0; } + &.no-padding-top { + padding-top: 0; + } &.no-padding { padding: 0; } From 2bd5b1765c20f2065a0165b870aec524f163a2db Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Tue, 5 Mar 2024 10:35:04 +0200 Subject: [PATCH 300/397] Improve copy of image for edge --- .../constructor/asset/AssetMsgConstructorV1.java | 7 ++++--- .../dashboard/DashboardMsgConstructorV1.java | 7 ++++--- .../constructor/device/DeviceMsgConstructorV1.java | 7 ++++--- .../constructor/widget/WidgetMsgConstructorV1.java | 13 +++++++------ 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java index 02318b1aaa..524edbb5a5 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/asset/AssetMsgConstructorV1.java @@ -63,8 +63,8 @@ public class AssetMsgConstructorV1 extends BaseAssetMsgConstructor { @Override public AssetProfileUpdateMsg constructAssetProfileUpdatedMsg(UpdateMsgType msgType, AssetProfile assetProfile) { - AssetProfile copy = JacksonUtil.clone(assetProfile); - imageService.inlineImageForEdge(copy); + assetProfile = JacksonUtil.clone(assetProfile); + imageService.inlineImageForEdge(assetProfile); AssetProfileUpdateMsg.Builder builder = AssetProfileUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(assetProfile.getId().getId().getMostSignificantBits()) @@ -82,7 +82,7 @@ public class AssetMsgConstructorV1 extends BaseAssetMsgConstructor { builder.setDescription(assetProfile.getDescription()); } if (assetProfile.getImage() != null) { - builder.setImage(ByteString.copyFrom(copy.getImage().getBytes(StandardCharsets.UTF_8))); + builder.setImage(ByteString.copyFrom(assetProfile.getImage().getBytes(StandardCharsets.UTF_8))); } if (assetProfile.getDefaultEdgeRuleChainId() != null) { builder.setDefaultRuleChainIdMSB(assetProfile.getDefaultEdgeRuleChainId().getId().getMostSignificantBits()) @@ -90,4 +90,5 @@ public class AssetMsgConstructorV1 extends BaseAssetMsgConstructor { } return builder.build(); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java index f94b165e2d..ec2d216a03 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/dashboard/DashboardMsgConstructorV1.java @@ -33,8 +33,8 @@ public class DashboardMsgConstructorV1 extends BaseDashboardMsgConstructor { @Override public DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) { - Dashboard copy = JacksonUtil.clone(dashboard); - imageService.inlineImagesForEdge(copy); + dashboard = JacksonUtil.clone(dashboard); + imageService.inlineImagesForEdge(dashboard); DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(dashboard.getId().getId().getMostSignificantBits()) @@ -46,11 +46,12 @@ public class DashboardMsgConstructorV1 extends BaseDashboardMsgConstructor { builder.setAssignedCustomers(JacksonUtil.toString(dashboard.getAssignedCustomers())); } if (dashboard.getImage() != null) { - builder.setImage(copy.getImage()); + builder.setImage(dashboard.getImage()); } if (dashboard.getMobileOrder() != null) { builder.setMobileOrder(dashboard.getMobileOrder()); } return builder.build(); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java index 3c6552f9d3..0e8b7452de 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/device/DeviceMsgConstructorV1.java @@ -95,8 +95,8 @@ public class DeviceMsgConstructorV1 extends BaseDeviceMsgConstructor { @Override public DeviceProfileUpdateMsg constructDeviceProfileUpdatedMsg(UpdateMsgType msgType, DeviceProfile deviceProfile) { - DeviceProfile copy = JacksonUtil.clone(deviceProfile); - imageService.inlineImageForEdge(copy); + deviceProfile = JacksonUtil.clone(deviceProfile); + imageService.inlineImageForEdge(deviceProfile); DeviceProfileUpdateMsg.Builder builder = DeviceProfileUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(deviceProfile.getId().getId().getMostSignificantBits()) @@ -121,7 +121,7 @@ public class DeviceMsgConstructorV1 extends BaseDeviceMsgConstructor { builder.setProvisionDeviceKey(deviceProfile.getProvisionDeviceKey()); } if (deviceProfile.getImage() != null) { - builder.setImage(ByteString.copyFrom(copy.getImage().getBytes(StandardCharsets.UTF_8))); + builder.setImage(ByteString.copyFrom(deviceProfile.getImage().getBytes(StandardCharsets.UTF_8))); } if (deviceProfile.getFirmwareId() != null) { builder.setFirmwareIdMSB(deviceProfile.getFirmwareId().getId().getMostSignificantBits()) @@ -141,4 +141,5 @@ public class DeviceMsgConstructorV1 extends BaseDeviceMsgConstructor { } return builder.build(); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/widget/WidgetMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/widget/WidgetMsgConstructorV1.java index 068378bea6..0201f6276b 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/widget/WidgetMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/widget/WidgetMsgConstructorV1.java @@ -43,8 +43,8 @@ public class WidgetMsgConstructorV1 extends BaseWidgetMsgConstructor { @Override public WidgetsBundleUpdateMsg constructWidgetsBundleUpdateMsg(UpdateMsgType msgType, WidgetsBundle widgetsBundle, List widgets) { - WidgetsBundle copy = JacksonUtil.clone(widgetsBundle); - imageService.inlineImageForEdge(copy); + widgetsBundle = JacksonUtil.clone(widgetsBundle); + imageService.inlineImageForEdge(widgetsBundle); WidgetsBundleUpdateMsg.Builder builder = WidgetsBundleUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(widgetsBundle.getId().getId().getMostSignificantBits()) @@ -52,7 +52,7 @@ public class WidgetMsgConstructorV1 extends BaseWidgetMsgConstructor { .setTitle(widgetsBundle.getTitle()) .setAlias(widgetsBundle.getAlias()); if (widgetsBundle.getImage() != null) { - builder.setImage(ByteString.copyFrom(copy.getImage().getBytes(StandardCharsets.UTF_8))); + builder.setImage(ByteString.copyFrom(widgetsBundle.getImage().getBytes(StandardCharsets.UTF_8))); } if (widgetsBundle.getDescription() != null) { builder.setDescription(widgetsBundle.getDescription()); @@ -69,8 +69,8 @@ public class WidgetMsgConstructorV1 extends BaseWidgetMsgConstructor { @Override public WidgetTypeUpdateMsg constructWidgetTypeUpdateMsg(UpdateMsgType msgType, WidgetTypeDetails widgetTypeDetails, EdgeVersion edgeVersion) { - WidgetTypeDetails copy = JacksonUtil.clone(widgetTypeDetails); - imageService.inlineImagesForEdge(copy); + widgetTypeDetails = JacksonUtil.clone(widgetTypeDetails); + imageService.inlineImagesForEdge(widgetTypeDetails); WidgetTypeUpdateMsg.Builder builder = WidgetTypeUpdateMsg.newBuilder() .setMsgType(msgType) .setIdMSB(widgetTypeDetails.getId().getId().getMostSignificantBits()) @@ -95,7 +95,7 @@ public class WidgetMsgConstructorV1 extends BaseWidgetMsgConstructor { builder.setIsSystem(true); } if (widgetTypeDetails.getImage() != null) { - builder.setImage(copy.getImage()); + builder.setImage(widgetTypeDetails.getImage()); } if (widgetTypeDetails.getDescription() != null) { if (EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_6_0) && @@ -111,4 +111,5 @@ public class WidgetMsgConstructorV1 extends BaseWidgetMsgConstructor { } return builder.build(); } + } From 4e759dd4251ed1d003d8509243368b2a7bb89a46 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Mon, 4 Mar 2024 13:14:29 +0100 Subject: [PATCH 301/397] fixed lwm2m uplink executor lock --- .../lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index f8ff5c70a0..174d7d4f59 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java @@ -480,7 +480,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl CountDownLatch latch = new CountDownLatch(targetIds.size()); targetIds.forEach(versionedId -> sendReadRequest(lwM2MClient, versionedId, new TbLwM2MLatchCallback<>(latch, new TbLwM2MReadCallback(this, logService, lwM2MClient, versionedId)))); - latch.await(); + latch.await(config.getTimeout(), TimeUnit.MILLISECONDS); } catch (InterruptedException e) { log.error("[{}] Failed to await Read requests!", lwM2MClient.getEndpoint(), e); } catch (Exception e) { From ad99379f9025a9a1efe1d3323e93f09a26260335 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Mon, 4 Mar 2024 16:19:35 +0100 Subject: [PATCH 302/397] fixed possible lock in sendObserveRequests --- .../lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java index 174d7d4f59..8ba6815e30 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/uplink/DefaultLwM2mUplinkMsgHandler.java @@ -498,7 +498,7 @@ public class DefaultLwM2mUplinkMsgHandler extends LwM2MExecutorAwareService impl targetIds.forEach(targetId -> sendObserveRequest(lwM2MClient, targetId, new TbLwM2MLatchCallback<>(latch, new TbLwM2MObserveCallback(this, logService, lwM2MClient, targetId)))); - latch.await(); + latch.await(config.getTimeout(), TimeUnit.MILLISECONDS); } catch (InterruptedException e) { log.error("[{}] Failed to await Observe requests!", lwM2MClient.getEndpoint(), e); } catch (Exception e) { From 23812e1149b7b74a005d3bcc4ca7860d2ffa9124 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 5 Mar 2024 17:13:53 +0200 Subject: [PATCH 303/397] changed type of ThingsboardErrorResponse timestamp from Date to long --- .../ThingsboardErrorController.java | 56 +++++++++++++++++++ .../exception/ThingsboardErrorResponse.java | 6 +- 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 application/src/main/java/org/thingsboard/server/controller/ThingsboardErrorController.java diff --git a/application/src/main/java/org/thingsboard/server/controller/ThingsboardErrorController.java b/application/src/main/java/org/thingsboard/server/controller/ThingsboardErrorController.java new file mode 100644 index 0000000000..b70edcba45 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/controller/ThingsboardErrorController.java @@ -0,0 +1,56 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.web.servlet.error.ErrorController; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.RequestMapping; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.exception.ThingsboardErrorResponse; + +import javax.servlet.RequestDispatcher; +import javax.servlet.http.HttpServletRequest; + +@Slf4j +@ControllerAdvice +public class ThingsboardErrorController implements ErrorController { + + public static final String PATH_NOT_FOUND_ERROR_DESCRIPTION = "Path is not found."; + public static final String GENERAL_ERROR_DESCRIPTION = "Something went wrong! Our Engineers are on it"; + + @RequestMapping("/error") + public ResponseEntity handleError(HttpServletRequest request) { + Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.APPLICATION_JSON); + + if (status != null) { + int statusCode = Integer.parseInt(status.toString()); + + if(statusCode == HttpStatus.NOT_FOUND.value()) { + return new ResponseEntity<>(ThingsboardErrorResponse.of(PATH_NOT_FOUND_ERROR_DESCRIPTION, ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND), httpHeaders, HttpStatus.NOT_FOUND); + } + } + return new ResponseEntity<>(ThingsboardErrorResponse.of(GENERAL_ERROR_DESCRIPTION, ThingsboardErrorCode.GENERAL, HttpStatus.INTERNAL_SERVER_ERROR), httpHeaders, HttpStatus.INTERNAL_SERVER_ERROR); + } + +} diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java index 26084ad077..513aff6891 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponse.java @@ -33,13 +33,13 @@ public class ThingsboardErrorResponse { // Error code private final ThingsboardErrorCode errorCode; - private final Date timestamp; + private final long timestamp; protected ThingsboardErrorResponse(final String message, final ThingsboardErrorCode errorCode, HttpStatus status) { this.message = message; this.errorCode = errorCode; this.status = status; - this.timestamp = new java.util.Date(); + this.timestamp = System.currentTimeMillis(); } public static ThingsboardErrorResponse of(final String message, final ThingsboardErrorCode errorCode, HttpStatus status) { @@ -75,7 +75,7 @@ public class ThingsboardErrorResponse { } @ApiModelProperty(position = 4, value = "Timestamp", accessMode = ApiModelProperty.AccessMode.READ_ONLY) - public Date getTimestamp() { + public long getTimestamp() { return timestamp; } } From b91c1ba288dd5ce22a1cd837f34a36752f82928e Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 5 Mar 2024 19:26:04 +0200 Subject: [PATCH 304/397] UI: Implement thresholds config for Time series chart. --- ...e-series-chart-basic-config.component.html | 10 +- .../basic/common/data-key-row.component.html | 146 +------ .../basic/common/data-key-row.component.scss | 26 +- .../basic/common/data-key-row.component.ts | 235 +---------- .../lib/chart/time-series-chart.models.ts | 95 ++++- ...e-series-chart-bar-settings.component.html | 2 + ...-series-chart-line-settings.component.html | 2 + ...-series-chart-axis-settings.component.html | 4 + ...-series-chart-threshold-row.component.html | 107 +++++ ...-series-chart-threshold-row.component.scss | 64 +++ ...me-series-chart-threshold-row.component.ts | 261 ++++++++++++ ...rt-threshold-settings-panel.component.html | 121 ++++++ ...rt-threshold-settings-panel.component.scss | 47 +++ ...hart-threshold-settings-panel.component.ts | 139 ++++++ ...ries-chart-thresholds-panel.component.html | 47 +++ ...ries-chart-thresholds-panel.component.scss | 47 +++ ...series-chart-thresholds-panel.component.ts | 213 ++++++++++ .../common/data-key-input.component.html | 152 +++++++ .../common/data-key-input.component.scss | 46 ++ .../common/data-key-input.component.ts | 398 ++++++++++++++++++ .../common/entity-alias-input.component.html | 49 +++ .../common/entity-alias-input.component.scss | 20 + .../common/entity-alias-input.component.ts | 156 +++++++ .../common/widget-settings-common.module.ts | 25 +- .../assets/locale/locale.constant-en_US.json | 31 ++ 25 files changed, 2049 insertions(+), 394 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html index 4fd7de467f..14cf0c7e11 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html @@ -39,9 +39,13 @@ [entityAliasId]="datasource?.entityAliasId" formControlName="series"> -
    -
    TODO: Thresholds
    -
    + +
    widget-config.appearance
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html index 1c4767b963..3ef6891808 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html @@ -22,123 +22,19 @@ {{ 'datakey.latest' | translate }} - - - -
    -
    -
    - - notifications - - - timeline - -
    -
    - - - -
    -
    - - -
    -
    - -
    - - - - - notifications - - - timeline - - - - - -
    -
    - entity.no-keys-found -
    - - - {{ translate.get('entity.no-key-matching', - {key: truncate.transform(keySearchText, true, 6, '...')}) | async }} - - - entity.create-new-key - - - {{'entity.create-new-key' | translate }} - notifications - - - timeline - - -
    -
    -
    -
    + + @@ -193,19 +89,3 @@
    - - - f() - - - - - - - - {{ modelValue?.aggregationType }}({{ modelValue?.name }}) - - - {{modelValue?.name}} - - diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss index 198fa64518..be91ff173c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss @@ -16,37 +16,13 @@ @import '../../../../../../../../scss/constants'; .tb-data-key-row { - .mat-mdc-form-field.tb-inline-field.tb-key-field { - .mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) { - padding-left: 8px; - padding-right: 0; - .mat-mdc-form-field-infix { - padding-top: 0; - padding-bottom: 6px; - .mdc-evolution-chip-set .mdc-evolution-chip { - margin: 0; - } - input.mat-mdc-chip-input { - height: 32px; - margin-left: 0; - } - } - } - .mat-mdc-chip.mat-mdc-standard-chip.tb-datakey-chip { - .tb-attribute-chip { - .tb-chip-labels { - background: transparent; - } - } - } - } .tb-source-field { width: 108px; min-width: 108px; } - .tb-key-field { + .tb-data-key-input { flex: 1; min-width: 150px; @media #{$mat-gt-sm} { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts index d862a51566..b2710db346 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts @@ -17,15 +17,11 @@ import { ChangeDetectorRef, Component, - ElementRef, EventEmitter, forwardRef, Input, - OnChanges, OnInit, Output, - SimpleChanges, - ViewChild, ViewEncapsulation } from '@angular/core'; import { @@ -49,15 +45,8 @@ import { widgetType } from '@shared/models/widget.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; -import { AggregationType } from '@shared/models/time/time.models'; -import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; -import { MatChipGrid, MatChipInputEvent } from '@angular/material/chips'; import { DataKeysCallbacks, DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; -import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autocomplete'; -import { Observable, of } from 'rxjs'; -import { filter, map, mergeMap, publishReplay, refCount, share, tap } from 'rxjs/operators'; -import { TranslateService } from '@ngx-translate/core'; -import { TruncatePipe } from '@shared/pipe/truncate.pipe'; +import { merge } from 'rxjs'; import { DataKeyConfigDialogComponent, DataKeyConfigDialogData @@ -66,8 +55,6 @@ import { deepClone } from '@core/utils'; import { Dashboard } from '@shared/models/dashboard.models'; import { IAliasController } from '@core/api/widget-api.models'; import { coerceBoolean } from '@shared/decorators/coercion'; -import { alarmFields } from '@shared/models/alarm.models'; -import { UtilsService } from '@core/services/utils.service'; import { TimeSeriesChartKeySettings, TimeSeriesChartSeriesType, @@ -101,22 +88,12 @@ export const dataKeyRowValidator = (control: AbstractControl): ValidationErrors ], encapsulation: ViewEncapsulation.None }) -export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChanges { - - dataKeyTypes = DataKeyType; - widgetTypes = widgetType; +export class DataKeyRowComponent implements ControlValueAccessor, OnInit { timeSeriesChartSeriesTypes = timeSeriesChartSeriesTypes; timeSeriesChartSeriesTypeTranslations = timeSeriesChartSeriesTypeTranslations; timeSeriesChartSeriesTypeIcons = timeSeriesChartSeriesTypeIcons; - separatorKeysCodes: number[] = [ENTER, COMMA, SEMICOLON]; - - @ViewChild('keyInput') keyInput: ElementRef; - @ViewChild('keyAutocomplete') matAutocomplete: MatAutocomplete; - @ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger; - @ViewChild('chipList') chipList: MatChipGrid; - @Input() disabled: boolean; @@ -181,23 +158,13 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan @Output() keyRemoved = new EventEmitter(); - keysFormControl: UntypedFormControl; - keyFormControl: UntypedFormControl; keyRowFormGroup: UntypedFormGroup; modelValue: DataKey; - filteredKeys: Observable>; - - keySearchText = ''; - - alarmKeys: Array; - functionTypeKeys: Array; - - private latestKeySearchTextResult: Array = null; - private keyFetchObservable$: Observable> = null; + generateDataKey = this._generateDataKey.bind(this); get widgetType(): widgetType { return this.widgetConfigComponent.widgetType; @@ -256,29 +223,11 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan constructor(private fb: UntypedFormBuilder, private dialog: MatDialog, private cd: ChangeDetectorRef, - public translate: TranslateService, - public truncate: TruncatePipe, - private utils: UtilsService, private widgetConfigComponent: WidgetConfigComponent) { } ngOnInit() { - this.alarmKeys = []; - for (const name of Object.keys(alarmFields)) { - this.alarmKeys.push({ - name, - type: DataKeyType.alarm - }); - } - this.functionTypeKeys = []; - for (const type of this.utils.getPredefinedFunctionsList()) { - this.functionTypeKeys.push({ - name: type, - type: DataKeyType.function - }); - } - this.keyFormControl = this.fb.control(''); - this.keysFormControl = this.fb.control([], this.required ? [Validators.required] : []); + this.keyFormControl = this.fb.control(null, this.required ? [Validators.required] : []); this.keyRowFormGroup = this.fb.group({ label: [null, []], color: [null, []], @@ -287,59 +236,13 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan }); if (this.hasAdditionalLatestDataKeys) { this.keyRowFormGroup.addControl('latest', this.fb.control(false)); - this.keyRowFormGroup.valueChanges.subscribe( - () => this.clearKeySearchCache() - ); } if (this.showTimeSeriesType) { this.keyRowFormGroup.addControl('timeSeriesType', this.fb.control(null)); } - this.keyRowFormGroup.valueChanges.subscribe( + merge(this.keyFormControl.valueChanges, this.keyRowFormGroup.valueChanges).subscribe( () => this.updateModel() ); - this.filteredKeys = this.keyFormControl.valueChanges - .pipe( - tap((value: string | DataKey) => { - if (value && typeof value !== 'string') { - this.addKeyFromChipValue(value); - } else if (value === null) { - this.clearKeyChip(this.keyInput.nativeElement.value); - } - }), - filter((value) => typeof value === 'string'), - map((value) => value ? (typeof value === 'string' ? value : value.name) : ''), - mergeMap(name => this.fetchKeys(name) ), - share() - ); - } - - private reset() { - if (this.keyInput) { - this.keyInput.nativeElement.value = ''; - } - this.keyFormControl.patchValue('', {emitEvent: false}); - this.latestKeySearchTextResult = null; - } - - ngOnChanges(changes: SimpleChanges): void { - for (const propName of Object.keys(changes)) { - const change = changes[propName]; - if (!change.firstChange && change.currentValue !== change.previousValue) { - if (['deviceId', 'entityAliasId'].includes(propName)) { - this.clearKeySearchCache(); - } else if (['datasourceType'].includes(propName)) { - if ([DatasourceType.device, DatasourceType.entity].includes(change.previousValue) && - [DatasourceType.device, DatasourceType.entity].includes(change.currentValue)) { - this.clearKeySearchCache(); - } else { - this.clearKeySearchCache(); - setTimeout(() => { - this.reset(); - }, 1); - } - } - } - } } registerOnChange(fn: any): void { @@ -352,10 +255,10 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; if (isDisabled) { - this.keysFormControl.disable({emitEvent: false}); + this.keyFormControl.disable({emitEvent: false}); this.keyRowFormGroup.disable({emitEvent: false}); } else { - this.keysFormControl.enable({emitEvent: false}); + this.keyFormControl.enable({emitEvent: false}); this.keyRowFormGroup.enable({emitEvent: false}); } } @@ -382,36 +285,10 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan timeSeriesType }, {emitEvent: false}); } - this.keysFormControl.patchValue(this.modelValue ? [this.modelValue] : [], {emitEvent: false}); + this.keyFormControl.patchValue(deepClone(this.modelValue), {emitEvent: false}); this.cd.markForCheck(); } - dataKeyHasAggregation(): boolean { - return this.widgetConfigComponent.widgetType === widgetType.latest && this.modelValue?.type === DataKeyType.timeseries - && this.modelValue?.aggregationType && this.modelValue?.aggregationType !== AggregationType.NONE; - } - - dataKeyHasPostprocessing(): boolean { - return !!this.modelValue?.postFuncBody; - } - - displayKeyFn(key?: DataKey): string | undefined { - return key ? key.name : undefined; - } - - createKey(name: string, dataKeyType: DataKeyType = this.dataKeyType) { - this.addKeyFromChipValue({name: name ? name.trim() : '', type: dataKeyType}); - } - - addKey(event: MatChipInputEvent): void { - const value = event.value; - if ((value || '').trim() && this.dataKeyType) { - this.addKeyFromChipValue({name: value.trim(), type: this.dataKeyType}); - } else { - this.clearKeyChip(); - } - } - editKey(advanced = false) { this.dialog.open(DataKeyConfigDialogComponent, { @@ -451,104 +328,20 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit, OnChan }); } - removeKey() { - this.modelValue = null; - this.updateModel(); - this.clearKeyChip(); - } - - textIsNotEmpty(text: string): boolean { - return text && text.length > 0; - } - - clearKeyChip(value: string = '', focus = true) { - this.autocomplete.closePanel(); - this.keyInput.nativeElement.value = value; - this.keyFormControl.patchValue(value, {emitEvent: focus}); - if (focus) { - setTimeout(() => { - this.keyInput.nativeElement.blur(); - this.keyInput.nativeElement.focus(); - }, 0); - } - } - - onKeyInputFocus() { - if (!this.modelValue?.type) { - this.keyFormControl.updateValueAndValidity({onlySelf: true, emitEvent: true}); - } - } - - private fetchKeys(searchText?: string): Observable> { - if (this.keySearchText !== searchText || this.latestKeySearchTextResult === null) { - this.keySearchText = searchText; - const dataKeyFilter = this.createDataKeyFilter(this.keySearchText); - return this.getKeys().pipe( - map(name => name.filter(dataKeyFilter)), - tap(res => this.latestKeySearchTextResult = res) - ); - } - return of(this.latestKeySearchTextResult); - } - - private getKeys(): Observable> { - if (this.keyFetchObservable$ === null) { - let fetchObservable: Observable>; - if (this.datasourceType === DatasourceType.function) { - const targetKeysList = this.widgetType === widgetType.alarm ? this.alarmKeys : this.functionTypeKeys; - fetchObservable = of(targetKeysList); - } else if (this.datasourceType === DatasourceType.entity && this.entityAliasId || - this.datasourceType === DatasourceType.device && this.deviceId) { - const dataKeyTypes = [DataKeyType.timeseries]; - if (this.isLatestDataKeys || this.widgetType === widgetType.latest || this.widgetType === widgetType.alarm) { - dataKeyTypes.push(DataKeyType.attribute); - dataKeyTypes.push(DataKeyType.entityField); - if (this.widgetType === widgetType.alarm) { - dataKeyTypes.push(DataKeyType.alarm); - } - } - if (this.datasourceType === DatasourceType.device) { - fetchObservable = this.callbacks.fetchEntityKeysForDevice(this.deviceId, dataKeyTypes); - } else { - fetchObservable = this.callbacks.fetchEntityKeys(this.entityAliasId, dataKeyTypes); - } - } else { - fetchObservable = of([]); - } - this.keyFetchObservable$ = fetchObservable.pipe( - publishReplay(1), - refCount() - ); - } - return this.keyFetchObservable$; - } - - private createDataKeyFilter(query: string): (key: DataKey) => boolean { - const lowercaseQuery = query.toLowerCase(); - return key => key.name.toLowerCase().startsWith(lowercaseQuery); - } - - private addKeyFromChipValue(chip: DataKey) { - this.modelValue = this.callbacks.generateDataKey(chip.name, chip.type, this.dataKeySettingsSchema, this.isLatestDataKeys, + private _generateDataKey(key: DataKey): DataKey { + key = this.callbacks.generateDataKey(key.name, key.type, this.dataKeySettingsSchema, this.isLatestDataKeys, this.dataKeySettingsFunction); if (!this.keyRowFormGroup.get('label').value) { - this.keyRowFormGroup.get('label').patchValue(this.modelValue.label, {emitEvent: false}); + this.keyRowFormGroup.get('label').patchValue(key.label, {emitEvent: false}); } if (this.showTimeSeriesType) { - this.keyRowFormGroup.get('timeSeriesType').patchValue(this.modelValue.settings?.type, {emitEvent: false}); + this.keyRowFormGroup.get('timeSeriesType').patchValue(key.settings?.type, {emitEvent: false}); } - this.updateModel(); - this.clearKeyChip('', false); - } - - private clearKeySearchCache() { - this.keySearchText = ''; - this.keyFetchObservable$ = null; - this.latestKeySearchTextResult = null; + return key; } private updateModel() { - this.keysFormControl.patchValue(this.modelValue ? [this.modelValue] : [], {emitEvent: false}); + this.modelValue = this.keyFormControl.value; if (this.modelValue !== null) { const value: DataKey = this.keyRowFormGroup.value; this.modelValue = {...this.modelValue, ...value}; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index 6b2e3a5c6b..dfcd1aaced 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -25,7 +25,7 @@ import { import { ComponentStyle, Font, simpleDateFormat, textStyle } from '@shared/models/widget-settings.models'; import { XAXisOption, YAXisOption } from 'echarts/types/dist/shared'; import { CustomSeriesOption, LineSeriesOption } from 'echarts/charts'; -import { formatValue, isDefinedAndNotNull, parseFunction } from '@core/utils'; +import { formatValue, isDefinedAndNotNull, isUndefinedOrNull, parseFunction } from '@core/utils'; import { LinearGradientObject } from 'zrender/lib/graphic/LinearGradient'; import tinycolor from 'tinycolor2'; import Axis2D from 'echarts/types/src/coord/cartesian/Axis2D'; @@ -40,7 +40,8 @@ import { import { DataKey } from '@shared/models/widget.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { TbColorScheme } from '@shared/models/color.models'; -import { DoughnutLayout } from '@home/components/widget/lib/chart/doughnut-widget.models'; +import { AbstractControl, ValidationErrors } from '@angular/forms'; +import { MarkLine2DDataItemOption } from 'echarts/types/src/component/marker/MarkLineModel'; const timeSeriesChartColorScheme: TbColorScheme = { 'threshold.line': { @@ -154,12 +155,41 @@ export enum ThresholdLabelPosition { insideEndBottom = 'insideEndBottom' } +export const timeSeriesThresholdLabelPositions = Object.keys(ThresholdLabelPosition) as ThresholdLabelPosition[]; + +export const timeSeriesThresholdLabelPositionTranslations = new Map( + [ + [ThresholdLabelPosition.start, 'widgets.time-series-chart.threshold.label-position-start'], + [ThresholdLabelPosition.middle, 'widgets.time-series-chart.threshold.label-position-middle'], + [ThresholdLabelPosition.end, 'widgets.time-series-chart.threshold.label-position-end'], + [ThresholdLabelPosition.insideStart, 'widgets.time-series-chart.threshold.label-position-inside-start'], + [ThresholdLabelPosition.insideStartTop, 'widgets.time-series-chart.threshold.label-position-inside-start-top'], + [ThresholdLabelPosition.insideStartBottom, 'widgets.time-series-chart.threshold.label-position-inside-start-bottom'], + [ThresholdLabelPosition.insideMiddle, 'widgets.time-series-chart.threshold.label-position-inside-middle'], + [ThresholdLabelPosition.insideMiddleTop, 'widgets.time-series-chart.threshold.label-position-inside-middle-top'], + [ThresholdLabelPosition.insideMiddleBottom, 'widgets.time-series-chart.threshold.label-position-inside-middle-bottom'], + [ThresholdLabelPosition.insideEnd, 'widgets.time-series-chart.threshold.label-position-inside-end'], + [ThresholdLabelPosition.insideEndTop, 'widgets.time-series-chart.threshold.label-position-inside-end-top'], + [ThresholdLabelPosition.insideEndBottom, 'widgets.time-series-chart.threshold.label-position-inside-end-bottom'] + ] +); + export enum TimeSeriesChartThresholdType { constant = 'constant', latestKey = 'latestKey', entity = 'entity' } +export const timeSeriesThresholdTypes = Object.keys(TimeSeriesChartThresholdType) as TimeSeriesChartThresholdType[]; + +export const timeSeriesThresholdTypeTranslations = new Map( + [ + [TimeSeriesChartThresholdType.constant, 'widgets.time-series-chart.threshold.type-constant'], + [TimeSeriesChartThresholdType.latestKey, 'widgets.time-series-chart.threshold.type-latest-key'], + [TimeSeriesChartThresholdType.entity, 'widgets.time-series-chart.threshold.type-entity'] + ] +); + export enum SeriesFillType { none = 'none', opacity = 'opacity', @@ -273,6 +303,40 @@ export interface TimeSeriesChartThreshold { labelColor: string; } +export const timeSeriesChartThresholdValid = (threshold: TimeSeriesChartThreshold): boolean => { + if (!threshold.type) { + return false; + } + switch (threshold.type) { + case TimeSeriesChartThresholdType.constant: + if (isUndefinedOrNull(threshold.value)) { + return false; + } + break; + case TimeSeriesChartThresholdType.latestKey: + if (!threshold.latestKey || !threshold.latestKeyType) { + return false; + } + break; + case TimeSeriesChartThresholdType.entity: + if (!threshold.entityAlias || !threshold.entityKey || !threshold.entityKeyType) { + return false; + } + break; + } + return true; +}; + +export const timeSeriesChartThresholdValidator = (control: AbstractControl): ValidationErrors | null => { + const threshold: TimeSeriesChartThreshold = control.value; + if (!timeSeriesChartThresholdValid(threshold)) { + return { + threshold: true + }; + } + return null; +}; + export const timeSeriesChartThresholdDefaultSettings: TimeSeriesChartThreshold = { type: TimeSeriesChartThresholdType.constant, units: '', @@ -709,8 +773,6 @@ const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[], }, markLine: { animation: true, - symbol: [item.settings.startSymbol, item.settings.endSymbol], - symbolSize: [item.settings.startSymbolSize, item.settings.endSymbolSize], lineStyle: { width: item.settings.lineWidth, color: prepareChartThemeColor(item.settings.lineColor, darkMode, 'threshold.line'), @@ -737,14 +799,10 @@ const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[], seriesOption.markLine.data = []; if (Array.isArray(item.value)) { for (const val of item.value) { - seriesOption.markLine.data.push({ - yAxis: val - }); + seriesOption.markLine.data.push(createThresholdData(val, item)); } } else { - seriesOption.markLine.data.push({ - yAxis: item.value - }); + seriesOption.markLine.data.push(createThresholdData(item.value, item)); } series.push(seriesOption); } @@ -752,6 +810,23 @@ const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[], return series; }; +const createThresholdData = (val: string | number, item: TimeSeriesChartThresholdItem): MarkLine2DDataItemOption => [ + { + xAxis: 'min', + yAxis: val, + value: val, + symbol: item.settings.startSymbol, + symbolSize: item.settings.startSymbolSize + }, + { + xAxis: 'max', + yAxis: val, + value: val, + symbol: item.settings.endSymbol, + symbolSize: item.settings.endSymbolSize + } + ]; + const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], timeInterval: Interval, stack: boolean, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.html index a62157dba5..447784091e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-bar-settings.component.html @@ -49,6 +49,8 @@ +
    +
    + + + + {{ timeSeriesThresholdTypeTranslations.get(type) | translate }} + + + + + +
    +
    + + + + warning + + + + + + +
    +
    + + +
    +
    + + +
    +
    + + + +
    +
    +
    + +
    + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.scss new file mode 100644 index 0000000000..2a7dafc5f1 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.scss @@ -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. + */ +.tb-time-series-threshold-row { + .tb-threshold-source-field { + flex: 1; + min-width: 200px; + display: flex; + align-items: center; + flex-direction: row; + gap: 12px; + } + + .tb-threshold-type-field { + flex: 1; + } + + .tb-entity-alias-input { + flex: 1; + } + + .tb-threshold-key-value-field { + flex: 1; + min-width: 150px; + .tb-inline-field, .tb-data-key-input { + flex: 1; + } + } + + .tb-threshold-key-value-field, .tb-color-field, .tb-units-field, .tb-decimals-field { + display: flex; + flex-direction: row; + place-content: center; + align-items: center; + } + + .tb-units-field { + width: 80px; + min-width: 80px; + } + + .tb-color-field { + width: 40px; + min-width: 40px; + } + + .tb-decimals-field { + width: 60px; + min-width: 60px; + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts new file mode 100644 index 0000000000..e93969f795 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.ts @@ -0,0 +1,261 @@ +/// +/// 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 { + ChangeDetectorRef, + Component, + EventEmitter, + forwardRef, + Input, + OnInit, + Output, + Renderer2, + ViewContainerRef, + ViewEncapsulation +} from '@angular/core'; +import { + ControlValueAccessor, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, + Validators +} from '@angular/forms'; +import { + TimeSeriesChartThreshold, + TimeSeriesChartThresholdType, + timeSeriesThresholdTypes, + timeSeriesThresholdTypeTranslations +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { + TimeSeriesChartThresholdsPanelComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component'; +import { IAliasController } from '@core/api/widget-api.models'; +import { DataKey, Datasource, DatasourceType, WidgetConfig } from '@shared/models/widget.models'; +import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; +import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; +import { MatButton } from '@angular/material/button'; +import { TbPopoverService } from '@shared/components/popover.service'; +import { deepClone } from '@core/utils'; +import { + TimeSeriesChartThresholdSettingsPanelComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component'; + +@Component({ + selector: 'tb-time-series-chart-threshold-row', + templateUrl: './time-series-chart-threshold-row.component.html', + styleUrls: ['./time-series-chart-threshold-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartThresholdRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None +}) +export class TimeSeriesChartThresholdRowComponent implements ControlValueAccessor, OnInit { + + DataKeyType = DataKeyType; + + DatasourceType = DatasourceType; + + TimeSeriesChartThresholdType = TimeSeriesChartThresholdType; + + timeSeriesThresholdTypes = timeSeriesThresholdTypes; + + timeSeriesThresholdTypeTranslations = timeSeriesThresholdTypeTranslations; + + get aliasController(): IAliasController { + return this.thresholdsPanel.aliasController; + } + + get dataKeyCallbacks(): DataKeysCallbacks { + return this.thresholdsPanel.dataKeyCallbacks; + } + + get datasource(): Datasource { + return this.thresholdsPanel.datasource; + } + + get widgetConfig(): WidgetConfig { + return this.thresholdsPanel.widgetConfig; + } + + @Input() + disabled: boolean; + + @Output() + thresholdRemoved = new EventEmitter(); + + thresholdFormGroup: UntypedFormGroup; + + modelValue: TimeSeriesChartThreshold; + + latestKeyFormControl: UntypedFormControl; + + entityKeyFormControl: UntypedFormControl; + + private propagateChange = (_val: any) => {}; + + constructor(private fb: UntypedFormBuilder, + private popoverService: TbPopoverService, + private renderer: Renderer2, + private viewContainerRef: ViewContainerRef, + private thresholdsPanel: TimeSeriesChartThresholdsPanelComponent, + private cd: ChangeDetectorRef) { + } + + ngOnInit() { + this.thresholdFormGroup = this.fb.group({ + type: [null, []], + value: [null, [Validators.required]], + entityAlias: [null, [Validators.required]], + lineColor: [null, []], + units: [null, []], + decimals: [null, []] + }); + this.latestKeyFormControl = this.fb.control(null, [Validators.required]); + this.entityKeyFormControl = this.fb.control(null, [Validators.required]); + this.thresholdFormGroup.valueChanges.subscribe( + () => this.updateModel() + ); + this.latestKeyFormControl.valueChanges.subscribe( + () => this.updateModel() + ); + this.entityKeyFormControl.valueChanges.subscribe( + () => this.updateModel() + ); + this.thresholdFormGroup.get('type').valueChanges.subscribe(() => { + this.updateValidators(); + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.thresholdFormGroup.disable({emitEvent: false}); + this.latestKeyFormControl.disable({emitEvent: false}); + this.entityKeyFormControl.disable({emitEvent: false}); + } else { + this.thresholdFormGroup.enable({emitEvent: false}); + this.updateValidators(); + } + } + + writeValue(value: TimeSeriesChartThreshold): void { + this.modelValue = value; + this.thresholdFormGroup.patchValue( + { + type: value.type, + value: value.value, + entityAlias: value.entityAlias, + lineColor: value.lineColor, + units: value.units, + decimals: value.decimals, + }, {emitEvent: false} + ); + if (value.type === TimeSeriesChartThresholdType.latestKey) { + this.latestKeyFormControl.patchValue({ + type: value.latestKeyType, + name: value.latestKey + }, {emitEvent: false}); + } else if (value.type === TimeSeriesChartThresholdType.entity) { + this.entityKeyFormControl.patchValue({ + type: value.entityKeyType, + name: value.entityKey + }, {emitEvent: false}); + } + this.updateValidators(); + this.cd.markForCheck(); + } + + editThreshold($event: Event, matButton: MatButton) { + if ($event) { + $event.stopPropagation(); + } + const trigger = matButton._elementRef.nativeElement; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const ctx: any = { + thresholdSettings: deepClone(this.modelValue), + widgetConfig: this.widgetConfig + }; + const thresholdSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, TimeSeriesChartThresholdSettingsPanelComponent, ['leftOnly', 'leftTopOnly', 'leftBottomOnly'], true, null, + ctx, + {}, + {}, {}, true); + thresholdSettingsPanelPopover.tbComponentRef.instance.popover = thresholdSettingsPanelPopover; + thresholdSettingsPanelPopover.tbComponentRef.instance.thresholdSettingsApplied.subscribe((thresholdSettings) => { + thresholdSettingsPanelPopover.hide(); + this.modelValue = {...this.modelValue, ...thresholdSettings}; + this.thresholdFormGroup.patchValue( + {lineColor: this.modelValue.lineColor}, + {emitEvent: false}); + this.propagateChange(this.modelValue); + }); + } + } + + private updateValidators() { + const type: TimeSeriesChartThresholdType = this.thresholdFormGroup.get('type').value; + if (type === TimeSeriesChartThresholdType.constant) { + this.thresholdFormGroup.get('value').enable({emitEvent: false}); + this.thresholdFormGroup.get('entityAlias').disable({emitEvent: false}); + this.latestKeyFormControl.disable({emitEvent: false}); + this.entityKeyFormControl.disable({emitEvent: false}); + } else if (type === TimeSeriesChartThresholdType.latestKey) { + this.thresholdFormGroup.get('value').disable({emitEvent: false}); + this.thresholdFormGroup.get('entityAlias').disable({emitEvent: false}); + this.latestKeyFormControl.enable({emitEvent: false}); + this.entityKeyFormControl.disable({emitEvent: false}); + } else if (type === TimeSeriesChartThresholdType.entity) { + this.thresholdFormGroup.get('value').disable({emitEvent: false}); + this.thresholdFormGroup.get('entityAlias').enable({emitEvent: false}); + this.latestKeyFormControl.disable({emitEvent: false}); + this.entityKeyFormControl.enable({emitEvent: false}); + } + } + + private updateModel() { + const value = this.thresholdFormGroup.value; + this.modelValue.type = value.type; + this.modelValue.value = value.value; + this.modelValue.entityAlias = value.entityAlias; + this.modelValue.lineColor = value.lineColor; + this.modelValue.units = value.units; + this.modelValue.decimals = value.decimals; + if (value.type === TimeSeriesChartThresholdType.latestKey) { + const latestKey: DataKey = this.latestKeyFormControl.value; + this.modelValue.latestKey = latestKey?.name; + this.modelValue.latestKeyType = (latestKey?.type as any); + } else if (value.type === TimeSeriesChartThresholdType.entity) { + const entityKey: DataKey = this.entityKeyFormControl.value; + this.modelValue.entityKey = entityKey?.name; + this.modelValue.entityKeyType = (entityKey?.type as any); + } + this.propagateChange(this.modelValue); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.html new file mode 100644 index 0000000000..db4cc27bc9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.html @@ -0,0 +1,121 @@ + +
    +
    {{ 'widgets.time-series-chart.threshold.threshold-settings' | translate }}
    +
    +
    +
    widgets.time-series-chart.threshold.line-appearance
    +
    +
    widgets.time-series-chart.threshold.line-color
    + + +
    +
    +
    widgets.time-series-chart.line-type
    + + + + {{ timeSeriesLineTypeTranslations.get(lineType) | translate }} + + + +
    +
    +
    widgets.time-series-chart.line-width
    + + + +
    +
    +
    widgets.time-series-chart.threshold.start-symbol
    +
    + + + + {{ timeSeriesChartShapeTranslations.get(shape) | translate }} + + + +
    widgets.time-series-chart.threshold.symbol-size
    + + + +
    +
    +
    +
    widgets.time-series-chart.threshold.end-symbol
    +
    + + + + {{ timeSeriesChartShapeTranslations.get(shape) | translate }} + + + +
    widgets.time-series-chart.threshold.symbol-size
    + + + +
    +
    +
    + + {{ 'widgets.time-series-chart.threshold.label' | translate }} + +
    + + + + {{ timeSeriesThresholdLabelPositionTranslations.get(position) | translate }} + + + + + + + +
    +
    +
    +
    +
    + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.scss new file mode 100644 index 0000000000..260b199854 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.scss @@ -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 '../../../../../../../../../scss/constants'; + +.tb-threshold-settings-panel { + width: 530px; + display: flex; + flex-direction: column; + gap: 16px; + @media #{$mat-lt-md} { + width: 90vw; + } + .tb-threshold-settings-panel-content { + display: flex; + flex-direction: column; + gap: 16px; + overflow: auto; + } + .tb-threshold-settings-title { + font-size: 16px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0.25px; + color: rgba(0, 0, 0, 0.87); + } + .tb-threshold-settings-panel-buttons { + height: 40px; + display: flex; + flex-direction: row; + gap: 16px; + justify-content: flex-end; + align-items: flex-end; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts new file mode 100644 index 0000000000..a93a1c0181 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.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, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; +import { TbPopoverComponent } from '@shared/components/popover.component'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { + TimeSeriesChartShape, + timeSeriesChartShapes, + timeSeriesChartShapeTranslations, + TimeSeriesChartThreshold, + timeSeriesLineTypes, + timeSeriesLineTypeTranslations, + timeSeriesThresholdLabelPositions, + timeSeriesThresholdLabelPositionTranslations +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { merge } from 'rxjs'; +import { WidgetConfig } from '@shared/models/widget.models'; +import { formatValue, isDefinedAndNotNull } from '@core/utils'; + +@Component({ + selector: 'tb-time-series-chart-threshold-settings-panel', + templateUrl: './time-series-chart-threshold-settings-panel.component.html', + providers: [], + styleUrls: ['./time-series-chart-threshold-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class TimeSeriesChartThresholdSettingsPanelComponent implements OnInit { + + timeSeriesLineTypes = timeSeriesLineTypes; + + timeSeriesLineTypeTranslations = timeSeriesLineTypeTranslations; + + timeSeriesChartShapes = timeSeriesChartShapes; + + timeSeriesChartShapeTranslations = timeSeriesChartShapeTranslations; + + timeSeriesThresholdLabelPositions = timeSeriesThresholdLabelPositions; + + timeSeriesThresholdLabelPositionTranslations = timeSeriesThresholdLabelPositionTranslations; + + labelPreviewFn = this._labelPreviewFn.bind(this); + + @Input() + thresholdSettings: Partial; + + @Input() + widgetConfig: WidgetConfig; + + @Input() + popover: TbPopoverComponent; + + @Output() + thresholdSettingsApplied = new EventEmitter>(); + + thresholdSettingsFormGroup: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + } + + ngOnInit(): void { + this.thresholdSettingsFormGroup = this.fb.group( + { + lineColor: [this.thresholdSettings.lineColor, []], + lineType: [this.thresholdSettings.lineType, []], + lineWidth: [this.thresholdSettings.lineWidth, [Validators.min(0)]], + startSymbol: [this.thresholdSettings.startSymbol, []], + startSymbolSize: [this.thresholdSettings.startSymbolSize, [Validators.min(0)]], + endSymbol: [this.thresholdSettings.endSymbol, []], + endSymbolSize: [this.thresholdSettings.endSymbolSize, [Validators.min(0)]], + showLabel: [this.thresholdSettings.showLabel, []], + labelPosition: [this.thresholdSettings.labelPosition, []], + labelFont: [this.thresholdSettings.labelFont, []], + labelColor: [this.thresholdSettings.labelColor, []] + } + ); + merge(this.thresholdSettingsFormGroup.get('showLabel').valueChanges, + this.thresholdSettingsFormGroup.get('startSymbol').valueChanges, + this.thresholdSettingsFormGroup.get('endSymbol').valueChanges).subscribe(() => { + this.updateValidators(); + }); + this.updateValidators(); + } + + cancel() { + this.popover?.hide(); + } + + applyThresholdSettings() { + const thresholdSettings = this.thresholdSettingsFormGroup.getRawValue(); + this.thresholdSettingsApplied.emit(thresholdSettings); + } + + private updateValidators() { + const showLabel: boolean = this.thresholdSettingsFormGroup.get('showLabel').value; + const startSymbol: TimeSeriesChartShape = this.thresholdSettingsFormGroup.get('startSymbol').value; + const endSymbol: TimeSeriesChartShape = this.thresholdSettingsFormGroup.get('endSymbol').value; + if (showLabel) { + this.thresholdSettingsFormGroup.get('labelPosition').enable({emitEvent: false}); + this.thresholdSettingsFormGroup.get('labelFont').enable({emitEvent: false}); + this.thresholdSettingsFormGroup.get('labelColor').enable({emitEvent: false}); + } else { + this.thresholdSettingsFormGroup.get('labelPosition').disable({emitEvent: false}); + this.thresholdSettingsFormGroup.get('labelFont').disable({emitEvent: false}); + this.thresholdSettingsFormGroup.get('labelColor').disable({emitEvent: false}); + } + if (startSymbol === TimeSeriesChartShape.none) { + this.thresholdSettingsFormGroup.get('startSymbolSize').disable({emitEvent: false}); + } else { + this.thresholdSettingsFormGroup.get('startSymbolSize').enable({emitEvent: false}); + } + if (endSymbol === TimeSeriesChartShape.none) { + this.thresholdSettingsFormGroup.get('endSymbolSize').disable({emitEvent: false}); + } else { + this.thresholdSettingsFormGroup.get('endSymbolSize').enable({emitEvent: false}); + } + } + + private _labelPreviewFn(): string { + const units = this.thresholdSettings.units && this.thresholdSettings.units.length ? + this.thresholdSettings.units : this.widgetConfig.units; + const decimals = isDefinedAndNotNull(this.thresholdSettings.decimals) ? this.thresholdSettings.decimals : + (isDefinedAndNotNull(this.widgetConfig.decimals) ? this.widgetConfig.decimals : 2); + return formatValue(22, decimals, units, false); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.html new file mode 100644 index 0000000000..811106fc7b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.html @@ -0,0 +1,47 @@ + +
    +
    {{ 'widgets.time-series-chart.threshold.thresholds' | translate }}
    +
    +
    +
    widgets.time-series-chart.threshold.source
    +
    widgets.time-series-chart.threshold.key-value
    +
    widgets.color.color
    +
    widget-config.units-short
    +
    widget-config.decimals-short
    +
    +
    +
    +
    + + +
    +
    +
    +
    + +
    +
    + + {{ 'widgets.time-series-chart.threshold.no-thresholds' | translate }} + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.scss new file mode 100644 index 0000000000..d1f1ec6eed --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.scss @@ -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. + */ +.tb-time-series-thresholds-panel { + .tb-form-table-header-cell { + &.tb-threshold-source-header { + flex: 1; + min-width: 200px; + } + &.tb-threshold-key-value-header { + flex: 1; + min-width: 150px; + } + + &.tb-units-header { + width: 80px; + min-width: 80px; + } + + &.tb-color-header { + width: 40px; + min-width: 40px; + } + + &.tb-decimals-header { + width: 60px; + min-width: 60px; + } + + &.tb-actions-header { + width: 80px; + min-width: 80px; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts new file mode 100644 index 0000000000..40db98ba4b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.ts @@ -0,0 +1,213 @@ +/// +/// 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, ViewEncapsulation } from '@angular/core'; +import { + AbstractControl, + ControlValueAccessor, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + UntypedFormArray, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, + Validator +} from '@angular/forms'; +import { + TimeSeriesChartThreshold, + timeSeriesChartThresholdDefaultSettings, + TimeSeriesChartThresholdType, + timeSeriesChartThresholdValid, + timeSeriesChartThresholdValidator +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { mergeDeep } from '@core/utils'; +import { IAliasController } from '@core/api/widget-api.models'; +import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; +import { DataKey, Datasource, WidgetConfig } from '@shared/models/widget.models'; +import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; + +@Component({ + selector: 'tb-time-series-chart-thresholds-panel', + templateUrl: './time-series-chart-thresholds-panel.component.html', + styleUrls: ['./time-series-chart-thresholds-panel.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartThresholdsPanelComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TimeSeriesChartThresholdsPanelComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None +}) +export class TimeSeriesChartThresholdsPanelComponent implements ControlValueAccessor, OnInit, Validator { + + @Input() + disabled: boolean; + + @Input() + aliasController: IAliasController; + + @Input() + dataKeyCallbacks: DataKeysCallbacks; + + @Input() + datasource: Datasource; + + @Input() + widgetConfig: WidgetConfig; + + thresholdsFormGroup: UntypedFormGroup; + + private propagateChange = (_val: any) => {}; + + constructor(private fb: UntypedFormBuilder) { + } + + ngOnInit() { + this.thresholdsFormGroup = this.fb.group({ + thresholds: [this.fb.array([]), []] + }); + this.thresholdsFormGroup.valueChanges.subscribe( + () => { + let thresholds: TimeSeriesChartThreshold[] = this.thresholdsFormGroup.get('thresholds').value; + if (thresholds) { + thresholds = thresholds.filter(t => timeSeriesChartThresholdValid(t)); + } + this.updateLatestDataKeys(thresholds); + this.propagateChange(thresholds); + } + ); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.thresholdsFormGroup.disable({emitEvent: false}); + } else { + this.thresholdsFormGroup.enable({emitEvent: false}); + } + } + + writeValue(value: TimeSeriesChartThreshold[] | undefined): void { + const thresholds = this.checkLatestDataKeys(value || []); + this.thresholdsFormGroup.setControl('thresholds', this.prepareThresholdsFormArray(thresholds), {emitEvent: false}); + } + + public validate(c: UntypedFormControl) { + const valid = this.thresholdsFormGroup.valid; + return valid ? null : { + thresholds: { + valid: false, + }, + }; + } + + thresholdsFormArray(): UntypedFormArray { + return this.thresholdsFormGroup.get('thresholds') as UntypedFormArray; + } + + trackByThreshold(index: number, thresholdControl: AbstractControl): any { + return thresholdControl; + } + + removeThreshold(index: number) { + (this.thresholdsFormGroup.get('thresholds') as UntypedFormArray).removeAt(index); + } + + addThreshold() { + const threshold = mergeDeep({} as TimeSeriesChartThreshold, + timeSeriesChartThresholdDefaultSettings); + const thresholdsArray = this.thresholdsFormGroup.get('thresholds') as UntypedFormArray; + const thresholdControl = this.fb.control(threshold, [timeSeriesChartThresholdValidator]); + thresholdsArray.push(thresholdControl); + } + + private prepareThresholdsFormArray(thresholds: TimeSeriesChartThreshold[] | undefined): UntypedFormArray { + const thresholdsControls: Array = []; + if (thresholds) { + thresholds.forEach((threshold) => { + thresholdsControls.push(this.fb.control(threshold, [timeSeriesChartThresholdValidator])); + }); + } + return this.fb.array(thresholdsControls); + } + + private checkLatestDataKeys(thresholds: TimeSeriesChartThreshold[]): TimeSeriesChartThreshold[] { + const result: TimeSeriesChartThreshold[] = []; + const latestKeys = this.datasource?.latestDataKeys || []; + for (const threshold of thresholds) { + if (threshold.type === TimeSeriesChartThresholdType.latestKey) { + const found = latestKeys.find(k => this.isThresholdKey(k, threshold)); + if (found) { + result.push(threshold); + } + } else { + result.push(threshold); + } + } + return result; + } + + private updateLatestDataKeys(thresholds: TimeSeriesChartThreshold[]) { + if (this.datasource) { + let latestKeys = this.datasource.latestDataKeys; + if (!latestKeys) { + latestKeys = []; + this.datasource.latestDataKeys = latestKeys; + } + const existingThresholdKeys = latestKeys.filter(k => k.settings?.__thresholdKey === true); + const foundThresholdKeys: DataKey[] = []; + for (const threshold of thresholds) { + if (threshold.type === TimeSeriesChartThresholdType.latestKey) { + const found = existingThresholdKeys.find(k => this.isThresholdKey(k, threshold)); + if (!found) { + const newKey = this.dataKeyCallbacks.generateDataKey(threshold.latestKey, threshold.latestKeyType, + null, true, null); + newKey.settings.__thresholdKey = true; + latestKeys.push(newKey); + } else if (foundThresholdKeys.indexOf(found) === -1) { + foundThresholdKeys.push(found); + } + } + } + const toRemove = existingThresholdKeys.filter(k => foundThresholdKeys.indexOf(k) === -1); + for (const key of toRemove) { + const index = latestKeys.indexOf(key); + if (index > -1) { + latestKeys.splice(index, 1); + } + } + } + } + + private isThresholdKey(d: DataKey, threshold: TimeSeriesChartThreshold): boolean { + return (d.type === DataKeyType.function && d.label === threshold.latestKey) || + (d.type !== DataKeyType.function && d.name === threshold.latestKey && + d.type === threshold.latestKeyType); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.html new file mode 100644 index 0000000000..072c637641 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.html @@ -0,0 +1,152 @@ + + + + +
    +
    +
    + + notifications + + + timeline + +
    +
    + + + +
    +
    + + +
    +
    + +
    + + + + + notifications + + + timeline + + + + + +
    +
    + entity.no-keys-found +
    + + + {{ translate.get('entity.no-key-matching', + {key: truncate.transform(keySearchText, true, 6, '...')}) | async }} + + + entity.create-new-key + + + {{'entity.create-new-key' | translate }} + notifications + + + timeline + + +
    +
    +
    +
    + + + f() + + + + + + + + {{ modelValue?.aggregationType }}({{ modelValue?.name }}) + + + {{modelValue?.name}} + + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.scss new file mode 100644 index 0000000000..6d443d0057 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.scss @@ -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. + */ +.tb-data-key-input { + .mat-mdc-form-field.tb-inline-field.tb-key-field { + width: 100%; + .mat-mdc-text-field-wrapper:not(.mdc-text-field--outlined) { + padding-left: 8px; + padding-right: 0; + + .mat-mdc-form-field-infix { + padding-top: 0; + padding-bottom: 6px; + + .mdc-evolution-chip-set .mdc-evolution-chip { + margin: 0; + } + + input.mat-mdc-chip-input { + height: 32px; + margin-left: 0; + } + } + } + + .mat-mdc-chip.mat-mdc-standard-chip.tb-datakey-chip { + .tb-attribute-chip { + .tb-chip-labels { + background: transparent; + } + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.ts new file mode 100644 index 0000000000..04908bdd7b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.ts @@ -0,0 +1,398 @@ +/// +/// 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 { + ChangeDetectorRef, + Component, + ElementRef, + EventEmitter, + forwardRef, + HostBinding, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges, + ViewChild, + ViewEncapsulation +} from '@angular/core'; +import { + ControlValueAccessor, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormControl, + Validators +} from '@angular/forms'; +import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; +import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; +import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autocomplete'; +import { MatChipGrid, MatChipInputEvent } from '@angular/material/chips'; +import { coerceBoolean } from '@shared/decorators/coercion'; +import { DataKey, DatasourceType, widgetType } from '@shared/models/widget.models'; +import { Observable, of } from 'rxjs'; +import { MatDialog } from '@angular/material/dialog'; +import { TranslateService } from '@ngx-translate/core'; +import { TruncatePipe } from '@shared/pipe/truncate.pipe'; +import { UtilsService } from '@core/services/utils.service'; +import { alarmFields } from '@shared/models/alarm.models'; +import { filter, map, mergeMap, publishReplay, refCount, share, tap } from 'rxjs/operators'; +import { AggregationType } from '@shared/models/time/time.models'; +import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; +import { IAliasController } from '@core/api/widget-api.models'; + +@Component({ + selector: 'tb-data-key-input', + templateUrl: './data-key-input.component.html', + styleUrls: ['./data-key-input.component.scss', '../../../config/data-keys.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DataKeyInputComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None +}) +export class DataKeyInputComponent implements ControlValueAccessor, OnInit, OnChanges { + + @HostBinding('class') + hostClass = 'tb-data-key-input'; + + DataKeyType = DataKeyType; + + separatorKeysCodes: number[] = [ENTER, COMMA, SEMICOLON]; + + @ViewChild('keyInput') keyInput: ElementRef; + @ViewChild('keyAutocomplete') matAutocomplete: MatAutocomplete; + @ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger; + @ViewChild('chipList') chipList: MatChipGrid; + + @Input() + disabled: boolean; + + @Input() + @coerceBoolean() + required = false; + + @Input() + @coerceBoolean() + isLatestDataKeys = false; + + @Input() + @coerceBoolean() + editable = true; + + @Input() + datasourceType: DatasourceType; + + @Input() + entityAliasId: string; + + @Input() + entityAlias: string; + + @Input() + deviceId: string; + + @Input() + widgetType: widgetType; + + @Input() + callbacks: DataKeysCallbacks; + + @Input() + aliasController: IAliasController; + + @Input() + dataKeyType: DataKeyType; + + @Input() + dataKeyTypes: DataKeyType[]; + + @Input() + generateKey: (key: DataKey) => DataKey = (key) => key; + + @Output() + keyEdit = new EventEmitter(); + + keysFormControl: UntypedFormControl; + + keyFormControl: UntypedFormControl; + + modelValue: DataKey; + + filteredKeys: Observable>; + + keySearchText = ''; + + alarmKeys: Array; + functionTypeKeys: Array; + + allowedDataKeyTypes: DataKeyType[] = []; + + private latestKeySearchTextResult: Array = null; + private keyFetchObservable$: Observable> = null; + + get isEntityDatasource(): boolean { + return [DatasourceType.device, DatasourceType.entity].includes(this.datasourceType); + } + + private propagateChange = (_val: any) => {}; + + constructor(private fb: UntypedFormBuilder, + private dialog: MatDialog, + private cd: ChangeDetectorRef, + public translate: TranslateService, + public truncate: TruncatePipe, + private utils: UtilsService) { + } + + ngOnInit() { + this.alarmKeys = []; + for (const name of Object.keys(alarmFields)) { + this.alarmKeys.push({ + name, + type: DataKeyType.alarm + }); + } + this.functionTypeKeys = []; + for (const type of this.utils.getPredefinedFunctionsList()) { + this.functionTypeKeys.push({ + name: type, + type: DataKeyType.function + }); + } + this.keyFormControl = this.fb.control(''); + this.keysFormControl = this.fb.control([], this.required ? [Validators.required] : []); + this.filteredKeys = this.keyFormControl.valueChanges + .pipe( + tap((value: string | DataKey) => { + if (value && typeof value !== 'string') { + this.addKeyFromChipValue(value); + } else if (value === null) { + this.clearKeyChip(this.keyInput.nativeElement.value); + } + }), + filter((value) => typeof value === 'string'), + map((value) => value ? (typeof value === 'string' ? value : value.name) : ''), + mergeMap(name => this.fetchKeys(name) ), + share() + ); + this.updateAllowedDataKeys(); + } + + private updateAllowedDataKeys() { + this.allowedDataKeyTypes.length = 0; + if (this.dataKeyTypes?.length) { + this.allowedDataKeyTypes = this.allowedDataKeyTypes.concat(this.dataKeyTypes); + } else { + this.allowedDataKeyTypes = [DataKeyType.timeseries]; + if (this.isLatestDataKeys || this.widgetType === widgetType.latest || this.widgetType === widgetType.alarm) { + this.allowedDataKeyTypes.push(DataKeyType.attribute); + this.allowedDataKeyTypes.push(DataKeyType.entityField); + if (this.widgetType === widgetType.alarm) { + this.allowedDataKeyTypes.push(DataKeyType.alarm); + } + } + } + } + + private reset() { + if (this.keyInput) { + this.keyInput.nativeElement.value = ''; + } + this.keyFormControl.patchValue('', {emitEvent: false}); + this.latestKeySearchTextResult = null; + } + + ngOnChanges(changes: SimpleChanges): void { + for (const propName of Object.keys(changes)) { + const change = changes[propName]; + if (!change.firstChange && change.currentValue !== change.previousValue) { + if (['deviceId', 'entityAliasId', 'entityAlias', 'isLatestDataKeys'].includes(propName)) { + this.clearKeySearchCache(); + if (propName === 'isLatestDataKeys') { + this.updateAllowedDataKeys(); + if (!this.isLatestDataKeys) { + if (this.widgetType === widgetType.timeseries && + this.modelValue?.type && + this.modelValue.type !== DataKeyType.timeseries) { + setTimeout(() => { + this.modelValue = null; + this.updateModel(); + this.clearKeyChip('', false); + }, 1); + } + } + } + } else if (['datasourceType'].includes(propName)) { + if ([DatasourceType.device, DatasourceType.entity].includes(change.previousValue) && + [DatasourceType.device, DatasourceType.entity].includes(change.currentValue)) { + this.clearKeySearchCache(); + } else { + this.clearKeySearchCache(); + setTimeout(() => { + this.reset(); + }, 1); + } + } + } + } + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.keysFormControl.disable({emitEvent: false}); + } else { + this.keysFormControl.enable({emitEvent: false}); + } + } + + writeValue(value: DataKey): void { + this.modelValue = (value?.name && value?.type) ? value : null; + this.keysFormControl.patchValue(this.modelValue ? [this.modelValue] : [], {emitEvent: false}); + this.cd.markForCheck(); + } + + dataKeyHasAggregation(): boolean { + return this.widgetType === widgetType.latest && this.modelValue?.type === DataKeyType.timeseries + && this.modelValue?.aggregationType && this.modelValue?.aggregationType !== AggregationType.NONE; + } + + dataKeyHasPostprocessing(): boolean { + return !!this.modelValue?.postFuncBody; + } + + displayKeyFn(key?: DataKey): string | undefined { + return key ? key.name : undefined; + } + + createKey(name: string, dataKeyType: DataKeyType = this.dataKeyType) { + this.addKeyFromChipValue({name: name ? name.trim() : '', type: dataKeyType}); + } + + addKey(event: MatChipInputEvent): void { + const value = event.value; + if ((value || '').trim() && this.dataKeyType) { + this.addKeyFromChipValue({name: value.trim(), type: this.dataKeyType}); + } else { + this.clearKeyChip(); + } + } + + editKey() { + this.keyEdit.emit(this.modelValue); + } + + removeKey() { + this.modelValue = null; + this.updateModel(); + this.clearKeyChip(); + } + + textIsNotEmpty(text: string): boolean { + return text && text.length > 0; + } + + clearKeyChip(value: string = '', focus = true) { + this.autocomplete.closePanel(); + this.keyInput.nativeElement.value = value; + this.keyFormControl.patchValue(value, {emitEvent: focus}); + if (focus) { + setTimeout(() => { + this.keyInput.nativeElement.blur(); + this.keyInput.nativeElement.focus(); + }, 0); + } + } + + onKeyInputFocus() { + if (!this.modelValue?.type) { + this.keyFormControl.updateValueAndValidity({onlySelf: true, emitEvent: true}); + } + } + + private fetchKeys(searchText?: string): Observable> { + if (this.keySearchText !== searchText || this.latestKeySearchTextResult === null) { + this.keySearchText = searchText; + const dataKeyFilter = this.createDataKeyFilter(this.keySearchText); + return this.getKeys().pipe( + map(name => name.filter(dataKeyFilter)), + tap(res => this.latestKeySearchTextResult = res) + ); + } + return of(this.latestKeySearchTextResult); + } + + private getKeys(): Observable> { + if (this.keyFetchObservable$ === null) { + let fetchObservable: Observable>; + if (this.datasourceType === DatasourceType.function) { + const targetKeysList = this.widgetType === widgetType.alarm ? this.alarmKeys : this.functionTypeKeys; + fetchObservable = of(targetKeysList); + } else if (this.datasourceType === DatasourceType.entity && (this.entityAliasId || this.entityAlias) || + this.datasourceType === DatasourceType.device && this.deviceId) { + if (this.datasourceType === DatasourceType.device) { + fetchObservable = this.callbacks.fetchEntityKeysForDevice(this.deviceId, this.allowedDataKeyTypes); + } else { + let entityAliasId = this.entityAliasId; + if (!entityAliasId && this.entityAlias && this.aliasController) { + entityAliasId = this.aliasController.getEntityAliasId(this.entityAlias); + } + fetchObservable = entityAliasId ? this.callbacks.fetchEntityKeys(entityAliasId, this.allowedDataKeyTypes) : of([]); + } + } else { + fetchObservable = of([]); + } + this.keyFetchObservable$ = fetchObservable.pipe( + publishReplay(1), + refCount() + ); + } + return this.keyFetchObservable$; + } + + private createDataKeyFilter(query: string): (key: DataKey) => boolean { + const lowercaseQuery = query.toLowerCase(); + return key => key.name.toLowerCase().startsWith(lowercaseQuery); + } + + private addKeyFromChipValue(chip: DataKey) { + this.modelValue = this.generateKey(chip); + this.updateModel(); + this.clearKeyChip('', false); + } + + private clearKeySearchCache() { + this.keySearchText = ''; + this.keyFetchObservable$ = null; + this.latestKeySearchTextResult = null; + } + + private updateModel() { + this.keysFormControl.patchValue(this.modelValue ? [this.modelValue] : [], {emitEvent: false}); + this.propagateChange(this.modelValue); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.html new file mode 100644 index 0000000000..78d0533865 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.html @@ -0,0 +1,49 @@ + + + + + warning + + + + + + + + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.scss new file mode 100644 index 0000000000..baccbf2ab7 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.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. + */ +.tb-entity-alias-input { + .mat-mdc-form-field.tb-inline-field { + width: 100%; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts new file mode 100644 index 0000000000..dd6d19f14e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/entity-alias-input.component.ts @@ -0,0 +1,156 @@ +/// +/// 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 { + ChangeDetectorRef, + Component, + ElementRef, + forwardRef, + HostBinding, + Input, + OnInit, + ViewChild, + ViewEncapsulation +} from '@angular/core'; +import { + ControlValueAccessor, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormControl, + Validators +} from '@angular/forms'; +import { coerceBoolean } from '@shared/decorators/coercion'; +import { IAliasController } from '@core/api/widget-api.models'; +import { map, mergeMap } from 'rxjs/operators'; +import { Observable, of } from 'rxjs'; +import { TimeSeriesChartThresholdType } from '@home/components/widget/lib/chart/time-series-chart.models'; + +@Component({ + selector: 'tb-entity-alias-input', + templateUrl: './entity-alias-input.component.html', + styleUrls: ['./entity-alias-input.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => EntityAliasInputComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None +}) +export class EntityAliasInputComponent implements ControlValueAccessor, OnInit { + + @HostBinding('class') + hostClass = 'tb-entity-alias-input'; + + @ViewChild('entityAliasInput') entityAliasInput: ElementRef; + + @Input() + disabled: boolean; + + @Input() + @coerceBoolean() + required = false; + + @Input() + aliasController: IAliasController; + + entityAliasFormControl: UntypedFormControl; + + filteredEntityAliases: Observable>; + aliasSearchText = ''; + + private entityAliasList: Array = []; + private entityAliasDirty = false; + + private propagateChange = (_val: any) => {}; + + constructor(private fb: UntypedFormBuilder, + private cd: ChangeDetectorRef) { + } + + ngOnInit() { + this.entityAliasFormControl = this.fb.control(null, this.required ? [Validators.required] : []); + this.entityAliasFormControl.valueChanges.subscribe( + () => this.updateModel() + ); + + this.filteredEntityAliases = this.entityAliasFormControl.valueChanges + .pipe( + map(value => value ? value : ''), + mergeMap(name => this.fetchEntityAliases(name) ) + ); + + if (this.aliasController) { + const entityAliases = this.aliasController.getEntityAliases(); + for (const aliasId of Object.keys(entityAliases)) { + this.entityAliasList.push(entityAliases[aliasId].alias); + } + } + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.entityAliasFormControl.disable({emitEvent: false}); + } else { + this.entityAliasFormControl.enable({emitEvent: false}); + } + } + + writeValue(value: string): void { + this.entityAliasFormControl.patchValue(value, {emitEvent: false}); + this.entityAliasDirty = true; + } + + onEntityAliasFocus() { + if (this.entityAliasDirty) { + this.entityAliasFormControl.updateValueAndValidity({onlySelf: true}); + this.entityAliasDirty = false; + } + } + + clearEntityAlias() { + this.entityAliasFormControl.patchValue(null, {emitEvent: true}); + setTimeout(() => { + this.entityAliasInput.nativeElement.blur(); + this.entityAliasInput.nativeElement.focus(); + }, 0); + } + + private fetchEntityAliases(searchText?: string): Observable> { + this.aliasSearchText = searchText; + let result = this.entityAliasList; + if (searchText && searchText.length) { + result = this.entityAliasList.filter((entityAlias) => entityAlias.toLowerCase().includes(searchText.toLowerCase())); + } + return of(result); + } + + private updateModel() { + const value = this.entityAliasFormControl.value; + this.propagateChange(value); + } + + protected readonly TimeSeriesChartThresholdType = TimeSeriesChartThresholdType; +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts index a7922dfdc4..e741314315 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts @@ -95,6 +95,17 @@ import { import { TimeSeriesChartAxisSettingsComponent } from '@home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component'; +import { + TimeSeriesChartThresholdsPanelComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component'; +import { + TimeSeriesChartThresholdRowComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component'; +import { DataKeyInputComponent } from '@home/components/widget/lib/settings/common/data-key-input.component'; +import { EntityAliasInputComponent } from '@home/components/widget/lib/settings/common/entity-alias-input.component'; +import { + TimeSeriesChartThresholdSettingsPanelComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component'; @NgModule({ declarations: [ @@ -131,7 +142,12 @@ import { WidgetButtonAppearanceComponent, WidgetButtonCustomStyleComponent, WidgetButtonCustomStylePanelComponent, - TimeSeriesChartAxisSettingsComponent + TimeSeriesChartAxisSettingsComponent, + TimeSeriesChartThresholdsPanelComponent, + TimeSeriesChartThresholdRowComponent, + TimeSeriesChartThresholdSettingsPanelComponent, + DataKeyInputComponent, + EntityAliasInputComponent ], imports: [ CommonModule, @@ -172,7 +188,12 @@ import { WidgetButtonAppearanceComponent, WidgetButtonCustomStyleComponent, WidgetButtonCustomStylePanelComponent, - TimeSeriesChartAxisSettingsComponent + TimeSeriesChartAxisSettingsComponent, + TimeSeriesChartThresholdsPanelComponent, + TimeSeriesChartThresholdRowComponent, + TimeSeriesChartThresholdSettingsPanelComponent, + DataKeyInputComponent, + EntityAliasInputComponent ], providers: [ ColorSettingsComponentService, 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 4a05e1c3c1..29fbafe83c 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6615,6 +6615,37 @@ "shape-pin": "Pin", "shape-arrow": "Arrow", "shape-none": "None", + "threshold": { + "thresholds": "Thresholds", + "source": "Source", + "key-value": "Key / Value", + "no-thresholds": "No thresholds configured", + "add-threshold": "Add threshold", + "type-constant": "Constant", + "type-latest-key": "Key", + "type-entity": "Entity", + "threshold-settings": "Threshold settings", + "remove-threshold": "Remove threshold", + "threshold-value-required": "Threshold value is required.", + "line-appearance": "Line appearance", + "line-color": "Line color", + "start-symbol": "Start symbol", + "end-symbol": "End symbol", + "symbol-size": "size", + "label": "Label", + "label-position-start": "Start", + "label-position-middle": "Middle", + "label-position-end": "End", + "label-position-inside-start": "Inside start", + "label-position-inside-start-top": "Inside start top", + "label-position-inside-start-bottom": "Inside start bottom", + "label-position-inside-middle": "Inside middle", + "label-position-inside-middle-top": "Inside middle top", + "label-position-inside-middle-bottom": "Inside middle bottom", + "label-position-inside-end": "Inside end", + "label-position-inside-end-top": "Inside end top", + "label-position-inside-end-bottom": "Inside end bottom" + }, "axis": { "axes": "Axes", "x-axis": "X axis", From ff18b8712a357f9af1545532a237e8ed00e9d6fe Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 6 Mar 2024 14:03:05 +0200 Subject: [PATCH 305/397] Fix null values in Firebase message data --- .../DefaultNotificationCenter.java | 12 ++++- .../MobileAppNotificationChannel.java | 5 +- .../AbstractNotificationApiTest.java | 13 +++-- .../notification/NotificationApiTest.java | 54 +++++++++++++++++++ .../notification/NotificationRuleApiTest.java | 4 +- .../NotificationRequestStats.java | 10 ++++ 6 files changed, 89 insertions(+), 9 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java index 5a9e3fc3e1..25a344b775 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/DefaultNotificationCenter.java @@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thingsboard.rule.engine.api.NotificationCenter; +import org.thingsboard.server.cache.limits.RateLimitService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.EntityId; @@ -62,7 +63,6 @@ import org.thingsboard.server.dao.notification.NotificationService; import org.thingsboard.server.dao.notification.NotificationSettingsService; import org.thingsboard.server.dao.notification.NotificationTargetService; import org.thingsboard.server.dao.notification.NotificationTemplateService; -import org.thingsboard.server.cache.limits.RateLimitService; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.TopicService; @@ -204,6 +204,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple private void processNotificationRequestAsync(NotificationProcessingContext ctx, List targets, FutureCallback callback) { notificationExecutor.submit(() -> { + long startTs = System.currentTimeMillis(); NotificationRequestId requestId = ctx.getRequest().getId(); for (NotificationTarget target : targets) { try { @@ -219,9 +220,16 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple return; } } - log.debug("[{}] Notification request processing is finished", requestId); NotificationRequestStats stats = ctx.getStats(); + long time = System.currentTimeMillis() - startTs; + int sent = stats.getTotalSent().get(); + int errors = stats.getTotalErrors().get(); + if (errors > 0) { + log.info("[{}][{}] Notification request processing finished in {} ms (sent: {}, errors: {})", ctx.getTenantId(), requestId, time, sent, errors); + } else { + log.info("[{}][{}] Notification request processing finished in {} ms (sent: {})", ctx.getTenantId(), requestId, time, sent); + } updateRequestStats(ctx, requestId, stats); if (callback != null) { callback.onSuccess(stats); diff --git a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java index dc7f3f9d99..646556372a 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/channels/MobileAppNotificationChannel.java @@ -15,6 +15,8 @@ */ package org.thingsboard.server.service.notification.channels; +import com.fasterxml.jackson.databind.JsonNode; +import com.google.common.base.Strings; import com.google.firebase.messaging.FirebaseMessagingException; import com.google.firebase.messaging.MessagingErrorCode; import lombok.RequiredArgsConstructor; @@ -82,7 +84,7 @@ public class MobileAppNotificationChannel implements NotificationChannel getNotificationData(MobileAppDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) { Map data = Optional.ofNullable(processedTemplate.getAdditionalConfig()) - .map(JacksonUtil::toFlatMap).orElseGet(HashMap::new); + .filter(JsonNode::isObject).map(JacksonUtil::toFlatMap).orElseGet(HashMap::new); NotificationInfo info = ctx.getRequest().getInfo(); if (info == null) { return data; @@ -107,6 +109,7 @@ public class MobileAppNotificationChannel implements NotificationChannel Strings.nullToEmpty(value)); return data; } diff --git a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java index f54b5d9b7b..b945c162df 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/AbstractNotificationApiTest.java @@ -60,6 +60,7 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.controller.AbstractControllerTest; import org.thingsboard.server.dao.DaoUtil; +import org.thingsboard.server.dao.notification.DefaultNotifications; import org.thingsboard.server.dao.notification.NotificationRequestService; import org.thingsboard.server.dao.notification.NotificationRuleService; import org.thingsboard.server.dao.notification.NotificationSettingsService; @@ -99,6 +100,8 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest protected NotificationSettingsService notificationSettingsService; @Autowired protected SqlPartitioningRepository partitioningRepository; + @Autowired + protected DefaultNotifications defaultNotifications; public static final String DEFAULT_NOTIFICATION_SUBJECT = "Just a test"; public static final NotificationType DEFAULT_NOTIFICATION_TYPE = NotificationType.GENERAL; @@ -249,10 +252,14 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest } protected NotificationRule createNotificationRule(NotificationRuleTriggerConfig triggerConfig, String subject, String text, NotificationTargetId... targets) { - NotificationTemplate template = createNotificationTemplate(NotificationType.valueOf(triggerConfig.getTriggerType().toString()), subject, text, NotificationDeliveryMethod.WEB); + return createNotificationRule(triggerConfig, subject, text, List.of(targets), NotificationDeliveryMethod.WEB); + } + + protected NotificationRule createNotificationRule(NotificationRuleTriggerConfig triggerConfig, String subject, String text, List targets, NotificationDeliveryMethod... deliveryMethods) { + NotificationTemplate template = createNotificationTemplate(NotificationType.valueOf(triggerConfig.getTriggerType().toString()), subject, text, deliveryMethods); NotificationRule rule = new NotificationRule(); - rule.setName(triggerConfig.getTriggerType() + " " + Arrays.toString(targets)); + rule.setName(triggerConfig.getTriggerType() + " " + targets); rule.setEnabled(true); rule.setTemplateId(template.getId()); rule.setTriggerType(triggerConfig.getTriggerType()); @@ -260,7 +267,7 @@ public abstract class AbstractNotificationApiTest extends AbstractControllerTest DefaultNotificationRuleRecipientsConfig recipientsConfig = new DefaultNotificationRuleRecipientsConfig(); recipientsConfig.setTriggerType(triggerConfig.getTriggerType()); - recipientsConfig.setTargets(DaoUtil.toUUIDs(List.of(targets))); + recipientsConfig.setTargets(DaoUtil.toUUIDs(targets)); rule.setRecipientsConfig(recipientsConfig); return saveNotificationRule(rule); diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java index 2d93573a25..d3b79029ba 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationApiTest.java @@ -30,8 +30,12 @@ import org.springframework.web.client.RestTemplate; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.NotificationCenter; import org.thingsboard.rule.engine.api.notification.FirebaseService; +import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.alarm.Alarm; +import org.thingsboard.server.common.data.alarm.AlarmComment; +import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.NotificationRequestId; @@ -49,6 +53,7 @@ import org.thingsboard.server.common.data.notification.NotificationRequestStats; import org.thingsboard.server.common.data.notification.NotificationRequestStatus; import org.thingsboard.server.common.data.notification.NotificationType; import org.thingsboard.server.common.data.notification.info.EntityActionNotificationInfo; +import org.thingsboard.server.common.data.notification.rule.trigger.config.AlarmCommentNotificationRuleTriggerConfig; import org.thingsboard.server.common.data.notification.settings.MobileAppNotificationDeliveryMethodConfig; import org.thingsboard.server.common.data.notification.settings.NotificationSettings; import org.thingsboard.server.common.data.notification.settings.SlackNotificationDeliveryMethodConfig; @@ -771,6 +776,55 @@ public class NotificationApiTest extends AbstractNotificationApiTest { verifyNoMoreInteractions(firebaseService); } + @Test + public void testMobileAppNotifications_ruleBased() throws Exception { + loginSysAdmin(); + MobileAppNotificationDeliveryMethodConfig config = new MobileAppNotificationDeliveryMethodConfig(); + config.setFirebaseServiceAccountCredentials("testCredentials"); + saveNotificationSettings(config); + + loginTenantAdmin(); + mobileToken = "tenantFcmToken"; + doPost("/api/user/mobile/session", new MobileSessionInfo()).andExpect(status().isOk()); + + createNotificationRule(AlarmCommentNotificationRuleTriggerConfig.builder().onlyUserComments(true).build(), + DefaultNotifications.alarmComment.getSubject(), DefaultNotifications.alarmComment.getText(), + List.of(createNotificationTarget(tenantAdminUserId).getId()), NotificationDeliveryMethod.MOBILE_APP); + + Device device = createDevice("test", "test"); + UUID alarmDashboardId = UUID.randomUUID(); + Alarm alarm = Alarm.builder() + .type("test") + .tenantId(tenantId) + .originator(device.getId()) + .severity(AlarmSeverity.MAJOR) + .details(JacksonUtil.newObjectNode() + .put("dashboardId", alarmDashboardId.toString())) + .build(); + alarm = doPost("/api/alarm", alarm, Alarm.class); + + AlarmComment comment = new AlarmComment(); + comment.setComment(JacksonUtil.newObjectNode() + .put("text", "text")); + doPost("/api/alarm/" + alarm.getId() + "/comment", comment, AlarmComment.class); + + ArgumentCaptor> msgCaptor = ArgumentCaptor.forClass(Map.class); + await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { + verify(firebaseService).sendMessage(eq(tenantId), eq("testCredentials"), + eq("tenantFcmToken"), eq("Comment on 'test' alarm"), + eq(TENANT_ADMIN_EMAIL + " added comment: text"), + msgCaptor.capture()); + }); + Map firebaseMessageData = msgCaptor.getValue(); + assertThat(firebaseMessageData.keySet()).doesNotContainNull().doesNotContain(""); + assertThat(firebaseMessageData.values()).doesNotContainNull(); + assertThat(firebaseMessageData.get("info.userEmail")).isEqualTo(TENANT_ADMIN_EMAIL); + assertThat(firebaseMessageData.get("info.alarmType")).isEqualTo("test"); + assertThat(firebaseMessageData.get("onClick.enabled")).isEqualTo("true"); + assertThat(firebaseMessageData.get("onClick.linkType")).isEqualTo("DASHBOARD"); + assertThat(firebaseMessageData.get("onClick.dashboardId")).isEqualTo(alarmDashboardId.toString()); + } + @Test public void testMobileSettings_tenantLevel() throws Exception { MobileAppNotificationDeliveryMethodConfig config = new MobileAppNotificationDeliveryMethodConfig(); diff --git a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java index 1e95f9add3..9cf73894c2 100644 --- a/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java +++ b/application/src/test/java/org/thingsboard/server/service/notification/NotificationRuleApiTest.java @@ -26,6 +26,7 @@ import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.data.util.Pair; import org.springframework.test.context.TestPropertySource; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.cache.limits.RateLimitService; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; @@ -93,7 +94,6 @@ import org.thingsboard.server.dao.notification.DefaultNotifications; import org.thingsboard.server.dao.notification.NotificationRequestService; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.service.DaoSqlTest; -import org.thingsboard.server.cache.limits.RateLimitService; import org.thingsboard.server.queue.notification.DefaultNotificationDeduplicationService; import org.thingsboard.server.service.notification.rule.cache.DefaultNotificationRulesCache; import org.thingsboard.server.service.state.DeviceStateService; @@ -140,8 +140,6 @@ public class NotificationRuleApiTest extends AbstractNotificationApiTest { @Autowired private NotificationRuleProcessor notificationRuleProcessor; @Autowired - private DefaultNotifications defaultNotifications; - @Autowired private DefaultNotificationRulesCache notificationRulesCache; @Autowired private DeviceStateService deviceStateService; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStats.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStats.java index f7cdbda6fc..2bd9c526fd 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStats.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationRequestStats.java @@ -31,14 +31,20 @@ import java.util.concurrent.atomic.AtomicInteger; public class NotificationRequestStats { private final Map sent; + @JsonIgnore + private final AtomicInteger totalSent; private final Map> errors; + @JsonIgnore + private final AtomicInteger totalErrors; private String error; @JsonIgnore private final Map> processedRecipients; public NotificationRequestStats() { this.sent = new ConcurrentHashMap<>(); + this.totalSent = new AtomicInteger(); this.errors = new ConcurrentHashMap<>(); + this.totalErrors = new AtomicInteger(); this.processedRecipients = new ConcurrentHashMap<>(); } @@ -47,13 +53,16 @@ public class NotificationRequestStats { @JsonProperty("errors") Map> errors, @JsonProperty("error") String error) { this.sent = sent; + this.totalSent = null; this.errors = errors; + this.totalErrors = null; this.error = error; this.processedRecipients = Collections.emptyMap(); } public void reportSent(NotificationDeliveryMethod deliveryMethod, NotificationRecipient recipient) { sent.computeIfAbsent(deliveryMethod, k -> new AtomicInteger()).incrementAndGet(); + totalSent.incrementAndGet(); } public void reportError(NotificationDeliveryMethod deliveryMethod, Throwable error, NotificationRecipient recipient) { @@ -65,6 +74,7 @@ public class NotificationRequestStats { errorMessage = error.getClass().getSimpleName(); } errors.computeIfAbsent(deliveryMethod, k -> new ConcurrentHashMap<>()).put(recipient.getTitle(), errorMessage); + totalErrors.incrementAndGet(); } public void reportProcessed(NotificationDeliveryMethod deliveryMethod, Object recipientId) { From 270a023c5ecfb8722e64a9adb39533478a8ce91e Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Wed, 6 Mar 2024 13:56:57 +0100 Subject: [PATCH 306/397] fixed deserialization lwm2m client --- .../server/store/util/LwM2MClientSerDes.java | 2 +- .../lwm2m/server/client/LwM2mClientTest.java | 0 .../store/util/LwM2MClientSerDesTest.java | 151 ++++++++++++++++++ .../store/util/LwM2MClientSerDesTest.java | 101 ------------ .../transport/lwm2m/src/test/resources/15.xml | 26 +++ .../transport/lwm2m/src/test/resources/17.xml | 26 +++ 6 files changed, 204 insertions(+), 102 deletions(-) rename common/transport/lwm2m/src/test/{ => java}/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientTest.java (100%) create mode 100644 common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java delete mode 100644 common/transport/lwm2m/src/test/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java create mode 100644 common/transport/lwm2m/src/test/resources/15.xml create mode 100644 common/transport/lwm2m/src/test/resources/17.xml diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDes.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDes.java index 88663bae71..51fcfef97f 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDes.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDes.java @@ -146,7 +146,7 @@ public class LwM2MClientSerDes { if (multiInstances) { Map instances = new HashMap<>(); o.get("instances").asObject().forEach(entry -> { - instances.put(Integer.valueOf(entry.getName()), parseValue(type, entry.getValue())); + instances.put(Integer.valueOf(entry.getName()), parseValue(type, entry.getValue().asObject().get("value"))); }); return LwM2mMultipleResource.newResource(id, instances, type); } else { diff --git a/common/transport/lwm2m/src/test/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientTest.java similarity index 100% rename from common/transport/lwm2m/src/test/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientTest.java rename to common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientTest.java diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java new file mode 100644 index 0000000000..8cdd7b5147 --- /dev/null +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java @@ -0,0 +1,151 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.server.store.util; + +import org.eclipse.leshan.core.link.Link; +import org.eclipse.leshan.core.node.LwM2mMultipleResource; +import org.eclipse.leshan.core.node.LwM2mResource; +import org.eclipse.leshan.core.node.LwM2mSingleResource; +import org.eclipse.leshan.core.request.Identity; +import org.eclipse.leshan.core.request.WriteRequest; +import org.eclipse.leshan.server.registration.Registration; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.thingsboard.server.common.data.TbResource; +import org.thingsboard.server.common.data.device.data.PowerMode; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.transport.TransportResourceCache; +import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; +import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; +import org.thingsboard.server.gen.transport.TransportProtos; +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContext; +import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportServerHelper; +import org.thingsboard.server.transport.lwm2m.server.LwM2mVersionedModelProvider; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientState; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; +import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; +import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; + +import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class LwM2MClientSerDesTest { + + @Test + public void serializeDeserialize() throws Exception { + LwM2mClient client = new LwM2mClient("nodeId", "testEndpoint"); + + TransportDeviceInfo tdi = new TransportDeviceInfo(); + tdi.setPowerMode(PowerMode.PSM); + tdi.setPsmActivityTimer(10000L); + tdi.setPagingTransmissionWindow(2000L); + tdi.setEdrxCycle(3000L); + tdi.setTenantId(TenantId.fromUUID(UUID.randomUUID())); + tdi.setCustomerId(new CustomerId(UUID.randomUUID())); + tdi.setDeviceId(new DeviceId(UUID.randomUUID())); + tdi.setDeviceProfileId(new DeviceProfileId(UUID.randomUUID())); + tdi.setDeviceName("testDevice"); + tdi.setDeviceType("testType"); + ValidateDeviceCredentialsResponse credentialsResponse = ValidateDeviceCredentialsResponse.builder() + .deviceInfo(tdi) + .build(); + + client.init(credentialsResponse, UUID.randomUUID()); + + Registration registration = + new Registration.Builder("test", "testEndpoint", Identity + .unsecure(new InetSocketAddress(1000))) + .supportedContentFormats() + .supportedObjects(Map.of(15, "1.0", 17, "1.0")) + .objectLinks(new Link[]{new Link("/")}) + .build(); + + client.setRegistration(registration); + client.setState(LwM2MClientState.REGISTERED); + client.getSharedAttributes().put("key1", TransportProtos.TsKvProto.newBuilder().setTs(0).setKv(TransportProtos.KeyValueProto.newBuilder().setStringV("test").build()).build()); + client.getSharedAttributes().put("key2", TransportProtos.TsKvProto.newBuilder().setTs(1).setKv(TransportProtos.KeyValueProto.newBuilder().setDoubleV(1.02).build()).build()); + + TransportResourceCache resourceCache = mock(TransportResourceCache.class); + LwM2mTransportContext context = mock(LwM2mTransportContext.class); + LwM2mClientContext clientContext = mock(LwM2mClientContext.class); + + var provider = new LwM2mVersionedModelProvider(clientContext, new LwM2mTransportServerHelper(context), context); + + TbResource resource15 = new TbResource(); + resource15.setData(Files.readAllBytes(Path.of(this.getClass().getClassLoader().getResource("15.xml").toURI()))); + TbResource resource17 = new TbResource(); + resource17.setData(Files.readAllBytes(Path.of(this.getClass().getClassLoader().getResource("17.xml").toURI()))); + + when(resourceCache.get(any(), any(), eq("15_1.0"))).thenReturn(Optional.of(resource15)); + when(resourceCache.get(any(), any(), eq("17_1.0"))).thenReturn(Optional.of(resource17)); + when(context.getTransportResourceCache()).thenReturn(resourceCache); + when(clientContext.getClientByEndpoint(any())).thenReturn(client); + + LwM2mResource singleResource = LwM2mSingleResource.newStringResource(15, "testValue"); + LwM2mResource multipleResource = LwM2mMultipleResource.newStringResource(17, Map.of(0, "testValue", 1, "testValue")); + client.saveResourceValue("/15_1.0/0/0", singleResource, provider, WriteRequest.Mode.UPDATE); + client.saveResourceValue("/17_1.0/0/0", multipleResource, provider, WriteRequest.Mode.UPDATE); + + byte[] bytes = LwM2MClientSerDes.serialize(client); + Assert.assertNotNull(bytes); + + LwM2mClient desClient = LwM2MClientSerDes.deserialize(bytes); + + assertEquals(client.getNodeId(), desClient.getNodeId()); + assertEquals(client.getEndpoint(), desClient.getEndpoint()); + assertEquals(client.getSharedAttributes(), desClient.getSharedAttributes()); + assertEquals(client.getKeyTsLatestMap(), desClient.getKeyTsLatestMap()); + assertEquals(client.getTenantId(), desClient.getTenantId()); + assertEquals(client.getProfileId(), desClient.getProfileId()); + assertEquals(client.getDeviceId(), desClient.getDeviceId()); + assertEquals(client.getState(), desClient.getState()); + assertEquals(client.getSession(), desClient.getSession()); + assertEquals(client.getPowerMode(), desClient.getPowerMode()); + assertEquals(client.getPsmActivityTimer(), desClient.getPsmActivityTimer()); + assertEquals(client.getPagingTransmissionWindow(), desClient.getPagingTransmissionWindow()); + assertEquals(client.getEdrxCycle(), desClient.getEdrxCycle()); + assertEquals(client.getRegistration(), desClient.getRegistration()); + assertEquals(client.isAsleep(), desClient.isAsleep()); + assertEquals(client.getLastUplinkTime(), desClient.getLastUplinkTime()); + assertEquals(client.getSleepTask(), desClient.getSleepTask()); + assertEquals(client.getClientSupportContentFormats(), desClient.getClientSupportContentFormats()); + assertEquals(client.getDefaultContentFormat(), desClient.getDefaultContentFormat()); + assertEquals(client.getRetryAttempts().get(), desClient.getRetryAttempts().get()); + assertEquals(client.getLastSentRpcId(), desClient.getLastSentRpcId()); + + Map expectedResources = client.getResources(); + Map actualResources = desClient.getResources(); + assertNotNull(actualResources); + assertEquals(expectedResources.size(), actualResources.size()); + expectedResources.forEach((key, value) -> assertEquals(value.toString(), actualResources.get(key).toString())); + } + +} \ No newline at end of file diff --git a/common/transport/lwm2m/src/test/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java b/common/transport/lwm2m/src/test/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java deleted file mode 100644 index 79e1f99c67..0000000000 --- a/common/transport/lwm2m/src/test/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright © 2016-2023 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.transport.lwm2m.server.store.util; - -import org.eclipse.leshan.core.link.Link; -import org.eclipse.leshan.core.request.Identity; -import org.eclipse.leshan.server.registration.Registration; -import org.junit.Assert; -import org.junit.Test; -import org.thingsboard.server.common.data.device.data.PowerMode; -import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.DeviceId; -import org.thingsboard.server.common.data.id.DeviceProfileId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; -import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; -import org.thingsboard.server.gen.transport.TransportProtos; -import org.thingsboard.server.transport.lwm2m.server.client.LwM2MClientState; -import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; - -import java.net.InetSocketAddress; -import java.util.UUID; - -public class LwM2MClientSerDesTest { - - @Test - public void serializeDeserialize() { - LwM2mClient client = new LwM2mClient("nodeId", "testEndpoint"); - - TransportDeviceInfo tdi = new TransportDeviceInfo(); - tdi.setPowerMode(PowerMode.PSM); - tdi.setPsmActivityTimer(10000L); - tdi.setPagingTransmissionWindow(2000L); - tdi.setEdrxCycle(3000L); - tdi.setTenantId(TenantId.fromUUID(UUID.randomUUID())); - tdi.setCustomerId(new CustomerId(UUID.randomUUID())); - tdi.setDeviceId(new DeviceId(UUID.randomUUID())); - tdi.setDeviceProfileId(new DeviceProfileId(UUID.randomUUID())); - tdi.setDeviceName("testDevice"); - tdi.setDeviceType("testType"); - ValidateDeviceCredentialsResponse credentialsResponse = ValidateDeviceCredentialsResponse.builder() - .deviceInfo(tdi) - .build(); - - client.init(credentialsResponse, UUID.randomUUID()); - - Registration registration = - new Registration.Builder("test", "testEndpoint", Identity - .unsecure(new InetSocketAddress(1000))) - .supportedContentFormats() - .objectLinks(new Link[]{new Link("/")}) - .build(); - - client.setRegistration(registration); - client.setState(LwM2MClientState.REGISTERED); - - client.getSharedAttributes().put("key1", TransportProtos.TsKvProto.newBuilder().setTs(0).setKv(TransportProtos.KeyValueProto.newBuilder().setStringV("test").build()).build()); - client.getSharedAttributes().put("key2", TransportProtos.TsKvProto.newBuilder().setTs(1).setKv(TransportProtos.KeyValueProto.newBuilder().setDoubleV(1.02).build()).build()); - - byte[] bytes = LwM2MClientSerDes.serialize(client); - Assert.assertNotNull(bytes); - - LwM2mClient desClient = LwM2MClientSerDes.deserialize(bytes); - - Assert.assertEquals(client.getNodeId(), desClient.getNodeId()); - Assert.assertEquals(client.getEndpoint(), desClient.getEndpoint()); - Assert.assertEquals(client.getResources(), desClient.getResources()); - Assert.assertEquals(client.getSharedAttributes(), desClient.getSharedAttributes()); - Assert.assertEquals(client.getKeyTsLatestMap(), desClient.getKeyTsLatestMap()); - Assert.assertEquals(client.getTenantId(), desClient.getTenantId()); - Assert.assertEquals(client.getProfileId(), desClient.getProfileId()); - Assert.assertEquals(client.getDeviceId(), desClient.getDeviceId()); - Assert.assertEquals(client.getState(), desClient.getState()); - Assert.assertEquals(client.getSession(), desClient.getSession()); - Assert.assertEquals(client.getPowerMode(), desClient.getPowerMode()); - Assert.assertEquals(client.getPsmActivityTimer(), desClient.getPsmActivityTimer()); - Assert.assertEquals(client.getPagingTransmissionWindow(), desClient.getPagingTransmissionWindow()); - Assert.assertEquals(client.getEdrxCycle(), desClient.getEdrxCycle()); - Assert.assertEquals(client.getRegistration(), desClient.getRegistration()); - Assert.assertEquals(client.isAsleep(), desClient.isAsleep()); - Assert.assertEquals(client.getLastUplinkTime(), desClient.getLastUplinkTime()); - Assert.assertEquals(client.getSleepTask(), desClient.getSleepTask()); - Assert.assertEquals(client.getClientSupportContentFormats(), desClient.getClientSupportContentFormats()); - Assert.assertEquals(client.getDefaultContentFormat(), desClient.getDefaultContentFormat()); - Assert.assertEquals(client.getRetryAttempts().get(), desClient.getRetryAttempts().get()); - Assert.assertEquals(client.getLastSentRpcId(), desClient.getLastSentRpcId()); - } -} \ No newline at end of file diff --git a/common/transport/lwm2m/src/test/resources/15.xml b/common/transport/lwm2m/src/test/resources/15.xml new file mode 100644 index 0000000000..11c018b3ac --- /dev/null +++ b/common/transport/lwm2m/src/test/resources/15.xml @@ -0,0 +1,26 @@ + + + + Test 15 + + 15 + urn:oma:lwm2m:oma:15:1.0 + 1.0 + 1.0 + Multiple + Optional + + + Test + R + Single + Mandatory + String + + + + + + + + diff --git a/common/transport/lwm2m/src/test/resources/17.xml b/common/transport/lwm2m/src/test/resources/17.xml new file mode 100644 index 0000000000..8417c66fb4 --- /dev/null +++ b/common/transport/lwm2m/src/test/resources/17.xml @@ -0,0 +1,26 @@ + + + + Test 17 + + 17 + urn:oma:lwm2m:oma:17:1.0 + 1.0 + 1.0 + Multiple + Mandatory + + + Test + R + Multiple + Optional + String + + + + + + + + From 686e41bd393c221534bf2f969e541dcc13746554 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 6 Mar 2024 17:04:25 +0200 Subject: [PATCH 307/397] moved path not found error handing from ThingsboardErrorController to ThingsboardErrorResponseHandler --- .../ThingsboardErrorController.java | 56 ------------------- .../ThingsboardErrorResponseHandler.java | 33 ++++++++++- 2 files changed, 32 insertions(+), 57 deletions(-) delete mode 100644 application/src/main/java/org/thingsboard/server/controller/ThingsboardErrorController.java diff --git a/application/src/main/java/org/thingsboard/server/controller/ThingsboardErrorController.java b/application/src/main/java/org/thingsboard/server/controller/ThingsboardErrorController.java deleted file mode 100644 index b70edcba45..0000000000 --- a/application/src/main/java/org/thingsboard/server/controller/ThingsboardErrorController.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright © 2016-2024 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.controller; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.web.servlet.error.ErrorController; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.RequestMapping; -import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; -import org.thingsboard.server.exception.ThingsboardErrorResponse; - -import javax.servlet.RequestDispatcher; -import javax.servlet.http.HttpServletRequest; - -@Slf4j -@ControllerAdvice -public class ThingsboardErrorController implements ErrorController { - - public static final String PATH_NOT_FOUND_ERROR_DESCRIPTION = "Path is not found."; - public static final String GENERAL_ERROR_DESCRIPTION = "Something went wrong! Our Engineers are on it"; - - @RequestMapping("/error") - public ResponseEntity handleError(HttpServletRequest request) { - Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); - - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON); - - if (status != null) { - int statusCode = Integer.parseInt(status.toString()); - - if(statusCode == HttpStatus.NOT_FOUND.value()) { - return new ResponseEntity<>(ThingsboardErrorResponse.of(PATH_NOT_FOUND_ERROR_DESCRIPTION, ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND), httpHeaders, HttpStatus.NOT_FOUND); - } - } - return new ResponseEntity<>(ThingsboardErrorResponse.of(GENERAL_ERROR_DESCRIPTION, ThingsboardErrorCode.GENERAL, HttpStatus.INTERNAL_SERVER_ERROR), httpHeaders, HttpStatus.INTERNAL_SERVER_ERROR); - } - -} diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java index b2509187d5..ec149fede8 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -16,6 +16,7 @@ package org.thingsboard.server.exception; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -28,7 +29,9 @@ import org.springframework.security.authentication.LockedException; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.context.request.WebRequest; @@ -43,6 +46,7 @@ import org.thingsboard.server.service.security.exception.JwtExpiredTokenExceptio import org.thingsboard.server.service.security.exception.UserPasswordExpiredException; import org.thingsboard.server.service.security.exception.UserPasswordNotValidException; +import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -50,9 +54,15 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; +import static javax.servlet.RequestDispatcher.ERROR_EXCEPTION; + @Slf4j +@Controller @RestControllerAdvice -public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHandler implements AccessDeniedHandler { +public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHandler implements AccessDeniedHandler, ErrorController { + + public static final String PATH_NOT_FOUND_ERROR_DESCRIPTION = "Path is not found."; + public static final String GENERAL_ERROR_DESCRIPTION = "Something went wrong!"; private static final Map statusToErrorCodeMap = new HashMap<>(); static { @@ -90,6 +100,27 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand return errorCodeToStatusMap.getOrDefault(errorCode, HttpStatus.INTERNAL_SERVER_ERROR); } + @RequestMapping("/error") + public ResponseEntity handleError(HttpServletRequest request) { + Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); + + if (status != null) { + int statusCode = Integer.parseInt(status.toString()); + if(statusCode == HttpStatus.NOT_FOUND.value()) { + return new ResponseEntity<>(ThingsboardErrorResponse.of(PATH_NOT_FOUND_ERROR_DESCRIPTION, ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND), HttpStatus.NOT_FOUND); + } + } + String errorMessage; + Throwable throwable = (Throwable) + request.getAttribute(ERROR_EXCEPTION); + if (throwable != null) { + errorMessage = throwable.getMessage(); + } else { + errorMessage = GENERAL_ERROR_DESCRIPTION; + } + return new ResponseEntity<>(ThingsboardErrorResponse.of(errorMessage, ThingsboardErrorCode.GENERAL, HttpStatus.INTERNAL_SERVER_ERROR), HttpStatus.INTERNAL_SERVER_ERROR); + } + @Override @ExceptionHandler(AccessDeniedException.class) public void handle(HttpServletRequest request, HttpServletResponse response, From 0177b5fdc7f7127db8cc398973f5239920a1b7eb Mon Sep 17 00:00:00 2001 From: IrynaMatveieva Date: Wed, 6 Mar 2024 17:56:51 +0200 Subject: [PATCH 308/397] added a method for getting a password with a null checking --- .../src/main/java/org/thingsboard/common/util/SslUtil.java | 6 +++++- .../rule/engine/credentials/CertPemCredentials.java | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/common/util/src/main/java/org/thingsboard/common/util/SslUtil.java b/common/util/src/main/java/org/thingsboard/common/util/SslUtil.java index d58f203956..4ef6fae706 100644 --- a/common/util/src/main/java/org/thingsboard/common/util/SslUtil.java +++ b/common/util/src/main/java/org/thingsboard/common/util/SslUtil.java @@ -73,7 +73,7 @@ public class SslUtil { @SneakyThrows public static PrivateKey readPrivateKey(String fileContent, String passStr) { - char[] password = StringUtils.isEmpty(passStr) ? EMPTY_PASS : passStr.toCharArray(); + char[] password = getPassword(passStr); PrivateKey privateKey = null; JcaPEMKeyConverter keyConverter = new JcaPEMKeyConverter(); @@ -102,4 +102,8 @@ public class SslUtil { return privateKey; } + public static char[] getPassword(String passStr) { + return StringUtils.isEmpty(passStr) ? EMPTY_PASS : passStr.toCharArray(); + } + } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java index 958957a3e2..40d899412d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/credentials/CertPemCredentials.java @@ -87,7 +87,7 @@ public class CertPemCredentials implements ClientCredentials { private KeyManagerFactory createAndInitKeyManagerFactory() throws Exception { KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(loadKeyStore(), password.toCharArray()); + kmf.init(loadKeyStore(), SslUtil.getPassword(password)); return kmf; } @@ -107,7 +107,7 @@ public class CertPemCredentials implements ClientCredentials { CertPath certPath = factory.generateCertPath(certificates); List path = certPath.getCertificates(); Certificate[] x509Certificates = path.toArray(new Certificate[0]); - keyStore.setKeyEntry(PRIVATE_KEY_ALIAS, privateKey, password.toCharArray(), x509Certificates); + keyStore.setKeyEntry(PRIVATE_KEY_ALIAS, privateKey, SslUtil.getPassword(password), x509Certificates); } return keyStore; } From b67189429dbf45defc2b6929b4c9152550f7ee57 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 6 Mar 2024 18:32:43 +0200 Subject: [PATCH 309/397] code formatting --- .../server/exception/ThingsboardErrorResponseHandler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java index ec149fede8..f843a8ec6f 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -111,8 +111,7 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand } } String errorMessage; - Throwable throwable = (Throwable) - request.getAttribute(ERROR_EXCEPTION); + Throwable throwable = (Throwable) request.getAttribute(ERROR_EXCEPTION); if (throwable != null) { errorMessage = throwable.getMessage(); } else { From cd206c0f8095a7122b13c2723ca2c9a0865fa1eb Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 6 Mar 2024 19:50:56 +0200 Subject: [PATCH 310/397] UI: Implement line / bar / point charts. --- .../json/system/widget_bundles/charts.json | 5 +- .../json/system/widget_types/bar_chart.json | 32 ++++ .../json/system/widget_types/line_chart.json | 32 ++++ .../json/system/widget_types/point_chart.json | 32 ++++ .../widget_types/time_series_chart.json | 8 +- .../widget_types/timeseries_bar_chart.json | 5 +- .../widget_types/timeseries_line_chart.json | 5 +- ui-ngx/src/app/core/api/data-aggregator.ts | 17 +- ...rt-with-labels-basic-config.component.html | 7 + ...hart-with-labels-basic-config.component.ts | 6 + .../range-chart-basic-config.component.html | 7 + .../range-chart-basic-config.component.ts | 6 + ...e-series-chart-basic-config.component.html | 2 +- ...ime-series-chart-basic-config.component.ts | 18 +- .../basic/common/data-key-row.component.scss | 8 +- .../basic/common/data-key-row.component.ts | 1 + .../common/data-keys-panel.component.html | 2 +- .../common/data-keys-panel.component.scss | 107 ++++++----- .../config/data-key-config.component.html | 1 + .../config/widget-settings.component.ts | 12 +- .../lib/chart/time-series-chart-bar.models.ts | 9 +- .../lib/chart/time-series-chart.models.ts | 15 ++ .../widget/lib/chart/time-series-chart.ts | 21 ++- ...with-labels-widget-settings.component.html | 7 + ...t-with-labels-widget-settings.component.ts | 7 +- ...range-chart-widget-settings.component.html | 7 + .../range-chart-widget-settings.component.ts | 5 + ...e-series-chart-key-settings.component.html | 6 +- ...ime-series-chart-key-settings.component.ts | 14 +- ...-series-chart-line-settings.component.html | 89 ++++----- ...me-series-chart-line-settings.component.ts | 7 +- ...eries-chart-widget-settings.component.html | 159 ++++++++++++++++ ...-series-chart-widget-settings.component.ts | 174 ++++++++++++++++++ ...-series-chart-threshold-row.component.html | 3 + ...-series-chart-threshold-row.component.scss | 41 ++++- ...me-series-chart-threshold-row.component.ts | 6 +- ...rt-threshold-settings-panel.component.html | 68 ++++--- ...rt-threshold-settings-panel.component.scss | 2 + ...hart-threshold-settings-panel.component.ts | 9 +- ...ries-chart-thresholds-panel.component.html | 3 +- ...ries-chart-thresholds-panel.component.scss | 31 +++- .../common/data-key-input.component.html | 12 +- .../common/data-key-input.component.ts | 3 + .../lib/settings/widget-settings.module.ts | 12 +- .../widget/widget-config.component.html | 1 + .../src/app/shared/models/time/time.models.ts | 9 +- ui-ngx/src/app/shared/models/widget.models.ts | 9 +- .../assets/locale/locale.constant-en_US.json | 6 + 48 files changed, 870 insertions(+), 178 deletions(-) create mode 100644 application/src/main/data/json/system/widget_types/bar_chart.json create mode 100644 application/src/main/data/json/system/widget_types/line_chart.json create mode 100644 application/src/main/data/json/system/widget_types/point_chart.json create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts diff --git a/application/src/main/data/json/system/widget_bundles/charts.json b/application/src/main/data/json/system/widget_bundles/charts.json index 5421cfb607..979b241e67 100644 --- a/application/src/main/data/json/system/widget_bundles/charts.json +++ b/application/src/main/data/json/system/widget_bundles/charts.json @@ -2,13 +2,16 @@ "widgetsBundle": { "alias": "charts", "title": "Charts", - "image": "tb-image:Y2hhcnRzX3N5c3RlbV9idW5kbGVfaW1hZ2UucG5n:IkNoYXJ0cyIgc3lzdGVtIGJ1bmRsZSBpbWFnZQ==;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAMAAAB+IdObAAAC91BMVEX////K5vz/wQchlvP0QzZgfYtMr1C20ujl5eUAAADi4uL/ySX9/v7/9+Dg4OA8o/TK2eT+6Ob1Wk7q9f7x8fHw8PHy8/L5+vn09PTT2t/p6ekznvRfs/b+wxHLy8v8/Pz/6KL///3+8/JRsVX6+/vq9uqTw+rn5+diuWVNq/bk5OTY2NjNzc2+vr6lzqfqop3u1Yr/wgzD4/w2oPSs2Pv4+Pnj4+S83/v8xBj/wgr0+v5itfdGqPX/1lv29vZUrvXHx8fH5fx2vvgunPTO5OvQ4+Oryd35xSG23fuRy/qAw/n39/jt7e3U4NK3t7eqqqprufdasfY/pPXL5PHu7u7r6+vf3t3/8srW3sjCwsK6urqxsbGw2vum1fuGxvn//fj/+urtzVf3/P/i8v6g0vvL5vqa0PqMyfns7Ozm5ubl1IL/333p0nLtz1/zyj/7/f/S6v17wfjM5fR4uevS0tJtiJX/3HLq0Wrxy0b1yTj/zDD/xhn9/v/u9/7/+PgpmvT//PPS4dj8w77/663c2qnm03yXzvpwu/dmt/fv7+/m6+2uz+ra4eX93tzV1dX/7LOurq6tra3g15j/4of/2WfvzFH1V0v/0kj0STz3yDH5xyjZ7f2gyerR4t7/9tzb3Nv/9dT61tPY3b/Z3Lrb27KMoavf2J92j5v/5JPrz2P2ZFn/xx++4fvr7/Dg6Ou+ztD8zcquvcT/8MKarbakpKSCmqT5n5iTz5Zmgo/5kIn3cWfpx0z1T0P/zz7U6/3P4+bO3ObO19vF0tq80dm6x82jtLz/7rni1YyJy4zc7/3O6Pz+7uz94d/Y7tm437qx3LPIz7P6sauo1ar/5pv6opuRkZHi1o97xH7aynr4gHdpvGzhymZbtl7zxC36wRC30ui30uTM1Njz69TM6M3F5cbC5MPDz7/p3bt/q52huI64wIf4gXjfzG67umTVvUDk8+Tm5N3a185yss2TwMjCz8T7ta/7s610qaWOr5PSy5H4hn33fnX3eG83NCs7AAAOvklEQVR42tzaSYyLYRzH8Z9SaV6P19a+7+u1VKmUWhJLK7baDpY2StKZCSNmwsFMHJDgYM84WGIZIUgkloMQYt8FsUessUWIiy0ODk4ccDDzvG2fvn3eeVvK+758LxKHJ/30eZ63/+kM/p+ICGVhHA5r9Gj0m7wQv1LlHiRrt8BZSae7kiSS+IWk55WhLXAWRIY4uW/fLaiHTFBsZdO9k5OOgRApJAiCCqm+78LTNZVQwoIQTcgoIlJfL/abPBpEEPYIf6kwiioeEqMpGbToQpLqGknjasWoj6D4BNhYUBVDMpqK+MSw8i9A4kLB1+kvExPE4ZBYOORHEUmiShwMkbmXZ0ZZ51QIUcUg8lPWb4hh2TAYlBDjjoTEREnvOnrs1JlFbre7Izo0b96p95qJQ5ZDlz+sOhCSEAhYwWunGgw0Ckk3YmazZfrzJTsM4hdSYB29pSkYhDVo0q5csCg5CiKLEWTbsN/NYhDW8LvIRjwJB0EiYpDtRobBQ1hTryCbqv5VyKpufKthnCISpIvfYgADCGssu/gpz9+EtHbxtYJhceboeMBtDmF1moBMXo8jIHLWQU5wCAbhGzsruyeqAyDBcj+0lP1uMwhf79lIV1ZjO4RkPwmOHHCbQ/gGZe+8R7Ib4lGgtX6RuxCEb9yY7PsRtBfiVZmjMIRvZbPsTbMVIovcuTKF8I2bz94SGyGZAxE84y4Owjcoc+PDEfsgUhm0TrmLhfD1ngWaX7QNQjKfIDfdxUP4xkKrxmcXJKSkL/r5kiDNh0BLJPZAiJj+94y7NEin5eyk2gFRFdCOuUuA0BY0uSVXO/ONLR1iuCGxRSVA0s0HzZuA1rTInul0+bbN+dr8YUiZBNoJd+mQztASQSt/LiWRtAoighZfVAIkW7Pc0xqsnC7Vo94iSCTENqR0yPDM9yp0Qyqfd7VuR2plNEYWlQJhzdZd900Nd6QcRBBuGM0Cwq/00QAyXhDC+SfrmvvPQOaAts4HliU7Ele5b35KgXSeARqJWg1RY0hHNtw6UBJk5fDBy9lGWw0RQVtVrQ0pJ8zHeFPFMO7qWQkRQOvmWtKNs/CQQgqWlLASwh6+I+n/P9UsR26e+QXIuClMwSJRayFeH2itXFqHD7bmLGaQTmOHzAMtRKBLtBaiRrQr4mIt3do6oFn2F4CMGNxhHpt0FOgSfhsS6G5QIYhA0FiFi8Ysu6lFub7/fFOQUUP0ByqmQleU/C6kXQu+9gUg7K7n12XuXmqJpS16yKgJwwpcCqgxOyBbXQYNWKxZ4m9Onc+FrB04CwD87849MPnZKSXZAVnsMm7otopA+hdX5zXIlGZUEXx37nXLlg9NID6vHZBtrqbbVlGlWdZj2Hx6ueX3dxoUDZ0zgUgpOyAjXaaNPFmFTPKHOz2oogBEqXEgpKEdt1c1Kh6+oIp0d0wgcdWZEJerNQDygikK7UjCaXck3UGgbgXkHrmQJ2Z3ZJ0dkLmFj1YAG3deAB7kQj6YQNZJdkAOFnJ0WYUVh1q0qAP650B6mkASiqUQEbTNhSAVwIWG9S61A3mVdbxCTsFa6ArJlkI8fjS2t4BjLlBHF7wYgJSFPOI/N1gCLIXUKNrA2cXUsSSAdpe0FZ8B79OOHhJy8sjQJVoJYQ/Jy6aQavgvZpY8DtwxeGZBhK0Qf5gbtvg2A2ezS27vDj8dUHrptkD2QJccshLC3rjbZgMKsK8F6yXwufFgPTCZ2oGEZDEkrN32qqYvyeEqdG+fu+hX4BGdfM1OlkCA2OnToX7TR1sD8fkKDSm7ge+6RXduBHnxiPstJA+TUn02JZG0AsIuyWaT0eRxC32HVsAPfSIB+K/GlUqyBfVWQNhLqFpqMprkL3sBeUkq9IUiAOTTHimpbgHxeq8bQbzGbTSAbPe+NYJ4vRIypbzcuMWNJlx10EXKidHDN9a3r6D0jYP4fIYQn3H7jCA+Q4jP50UmIoBW3cVkNNGljSq5qRL0KWVgWXS0EPU3Pcov1kYTvosBsGJh5BUO2gBRVG5LuNGE7xn/9wasoAAbIBBJU7ekGoH0aMK3jzkiyKs2bgOEfQasasWPJs+MDJlRRSss8X88DDsgbEtOmowmfC9B8/iQXyhmE0QJQWsxP5qY9AUAiXqRnyzAJgiiMmhVl/WjySdjARtVEFXAJcjFQnr24HtVCiQoQmv3UpPRhMVGFQIuSUXRkJZ8vUqBoMwHrYrMM/hyAPe50cR0VGEPYxshEGVorR6qfRNfDdz7VMCxvQ58Qgx2QvwiyUgGuBraisaOHzJhXDq7AnypGtgKgVKLrITOvLRA3cWmduPsPRgUEWAzBGoC6SoOL61Gto1n2/PPq5d1VTAqWE5sh6B2HdK1Pgld9x9/O7QzuxU/zh5fAeP85TLsh/xk545xGgaCAIr+Eo1GUzn2apsVkoUlF0Bjl1wASsgZnKOk4AZIKDfIPaDiBtyEDhdZkLPVRPKrd4uv3WKqYaz52/XH6+F4PHzmG+apy0OIWqDMfN9FCNpXlEv2gJMQ6CZKNdbgJ4S4U4rU1uIphGANBWKv+Aoh2abgW1XgLQSmMx9FozR4DKEdO2WxYDX4DIFgUcnJn/QbArXFtHTBgOsQCCKV8o+hs0nBfQjos437RI6GznYDcBEhQNr01k+hZaaP+87sZWAxFfm+OfUm77envmR7lyHb+wyRnuVSeLoy+TXGamC1Wq1WPxoFtAfR4rpyDpE6ugxDHZSIy4EBw1AHfaAYcQDHCCemLMcQEULij3pkUAiNeoR8odq04eERE2ljz2HgkZOBNrHmxkY09wgHBtCmppBZsXMxOzu7mvMBqhuvTc8Y6Q4K9GAEgULNfOI15u8zKU6vISpGtHUdSmhfIQq3G6cxQkGgF1Eaa43S2m3qg6yLNWWsiPGIhLa2ro4OjT1iIh3QzQgDRkEmBDQKm3ta8ztrdnilGDEysjsG2CQT4REdHm1dGsfIbHtNE0Z2RjgwkZ6NW2NyoWY9v0xhmwdUMUijl/Ep4jM7J608YhUnHQd2DwKkB1nh0lhg7BRrhFAJ1dgmHTPgxe8afhlzqHsQIMAaV5Eg3YasDq7RxDhuYD0i3M6fBncPAjhqtmHVaOIci6QKWaO5ZkDSAHkE0N7ZhTQVhnF879NFRcSCPoiOZxREMLKLbdHO2sbcV/uAlXOQm87VdHMwp+kMt5lR4lZCYmBJaFqhIklR0K2UQZDUVRBEEH1c9UVFX1DdtffMebZ5ds5ZlJT0v5j4+Pzf9/zeZ+/zvuzCdZ3f2SY1GuSIBQRZCT2LMVQ1goqAIHmZ7ujig6zx+nTpzkl3HVYQ1KhYW2g8dFKqZLIWGg1V59lnrP8jIA3WkNOoKLMHrrI9D6M23aF8426nU464QJCNkOPELfm9xKsm+n4XyO61Da16pbfuREhNEM62xuILy0iv8+WN1aA5qUeI21inCIhEq2+SQ9ozPZe24FpYK41Om5ynIq1r+UBslU6pRmxcdowQa3ROdaUh2/4FgKCr4hERo1sKuwCjtcrecwQyknX63377HMKF5wZpIKR93CCNGltj3U7rKZQrbhB3YpxZX+M9UVZywiZoBVzvAbSrXz3sOGeZwxnyh5Mf8RA1+z0Vkh0Lb7994vYy3S6ui+cpYs9yLPzKiDP0lQKYvp4NtYv75oYaMW7jMDJ6+RSefb+9YvvzdkLcvuPHu+kMzqfMN0tI0lpQkXqdAek1Po6KXHs9rUpMCFhFJmS2QIIEMuyaC/VWzr1FxV5OY1YDJAw5fAq7QmO3ZkvknkxN0Q8lkeCKFIJ09arRjOtUVV0RkAM92meA1TImHMQ0BC1RczOAJZkJyTUB3HYNGiUSAGLyA8SiCDW25Z02XHvk4N237+MWUD198noNC8iWGx1HMMMj84Al/eOBQJBoCwyZ8D5pSZscdMhKINFutU6OBIC4h4FKMiFukOPVPU3aThnQolT4dfjs5ku5IFuqO64AwIc3ZrqyYQpg0CEEJDgIFtqDgpMUqGImnBVQtEp79UzWneRUbDzKMlYwrIKWUSQIpOPcKsjI8uHdwNgMcj0Ix+k30BHt5eoDdNKlCM7pPLNHKs8WPEUCNHfzg8SAmgc2RWRADbzAx/UyO8rKMRun144cHDAXjGWOA6SCSBiICvdmbdPmahexc94Q/PJGe4Ue/VzT3TOdALCqqVrkFStzVjFCgmpqlAfkMZBuxMgRB3g6hpA+gGhFxyPDuJvGH4UTkFYi5Q4yY01QYBlHSCDIw9OZfxpzngjkGtSVXRc2n8UIuDbNN9I5rTQpM6w5JgNZZIYLZABUE/mRiWEAfwbfPOknAYCaSt7J/bU5acpsrgjA4AwSDJK9eYtteQa9LkQ3gNNNN7WnD6ygM04ULn93MwCZMhUFSapgsjAWfUy3YjdTAmzMK5AqPutY3p0A2SxCpYLsltoLDMrcJpz21Et9LMM6/ABU2MU+0xgJj1m2DW7FMmZTFBi7Z+P4jxYKht2oZJBDZZULDF5CngPS1dvLPiyNkjKxzOSgIMbeWN0JGI4lXcUe0TURswD4Tah0EINTv9AQUNxjQHxSfbFhx1pwVUyFM41awB9kB0HBbp52F3wwgVDpICGNnM0QqjqaBdkpVnIMOzYIQEbMuSF8oMejLI8oOCQMpEJS0T//cVCdWMluMOjqMyDPCS/3sG6M8sTMBFz0gf7nQTb09+8ol2AQfJ8dKXbx1JWtwLpNbOO96r6cBpA9yd5xX0yD5TpL1u8MbccgtfvnP6BrJeqKksulNtzSNO1ClszhV4Fs7rSfAqr7ty4//x5pUDRyGJRir6hLfVLgTI7mOZQIUG60yCAaH6fBS9y36/SCZ8IoqqkUyMbRYoPYeAwBY9XVUmYajeHzbBItOgivwWYtcabRCPkI/YUgvxAyoSUCgv6D/AdZEiB79y4REI9niYAsmYrQWvkPS5SvlSJW/SNZS1F4q/CrZoeApNr15fv5szySDQKmlJSXe0oD8QjKr60VkLR9fW0Nf9bGw+US/qxNnq2SP1KRGgFJF9d5BKTt6z+8jz+rQlJzmCflJ6e3vqMkTdRjAAAAAElFTkSuQmCC", + "image": "tb-image:Y2hhcnRzLnN2Zw==:IkNoYXJ0cyIgc3lzdGVtIGJ1bmRsZSBpbWFnZQ==;data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE2MCIgdmlld0JveD0iMCAwIDIwMCAxNjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF80MTk4XzExMDQ5MykiPgo8cGF0aCBkPSJNMTkuMjQ2MSAyMC45OTY5TDQuOTU0NDggNTQuMzI1NEwwIDYzLjVWNzZIOTZWNjAuOTU2MVY0NS4zMzMzTDg4Ljg5ODcgNjkuMDQ2MUw4NC45NDA3IDU0LjIxNTNMODMuMjIzMyA1OC41NzczTDc1Ljg4MjQgNzQuOTM3NkM3MC45ODg5IDU3LjE0MzMgNjYuOTExMSA1MC41MDM2IDYxLjU4NTEgMzMuMDIwOUw1Ni4wODk3IDU5LjEzMDlINDkuMDIyMUw0Ny42NTcgMTYuNzAyTDQ0LjkwNzYgMEwzMS44MjUgNDEuNjcwOEwyOC43MTQxIDQwLjM2MjdMMTkuMjQ2MSAyMC45OTY5WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzQxOThfMTEwNDkzKSIvPgo8cGF0aCBkPSJNMCA2My42NDg3TDUuMDAxMDkgNTMuNDg4TDE5LjQyNzEgMjAuMzk4OEwyOC45ODQyIDQwLjYyNTVMMzIuMTI0NCA0MS45MjQzTDQ0Ljg2OTYgMUw0Ny43MzkxIDE2LjE3MDNDNDguMjc3MiAzMi42MjA5IDQ4LjQxODQgNDIuNTQ5NCA0OC45NTY1IDU5SDU2TDYxLjU2NTIgMzIuMTIzM0w3NS45MTMgNzRMODUuMDE4NSA1My40NDEzTDg4Ljk1NjUgNjguMDE3Nkw5NiA0NC43MTk0IiBzdHJva2U9InVybCgjcGFpbnQxX2xpbmVhcl80MTk4XzExMDQ5MykiIHN0cm9rZS13aWR0aD0iMC43NzY1ODIiLz4KPC9nPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDFfNDE5OF8xMTA0OTMpIj4KPHBhdGggZD0iTTAgMEw5NiAxLjYwODcyZS0wNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiIHN0cm9rZS13aWR0aD0iMC4yNTQxNyIvPgo8cGF0aCBkPSJNMCAxOUw5NiAxOSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiIHN0cm9rZS13aWR0aD0iMC4yNTQxNyIvPgo8cGF0aCBkPSJNMCAzOEw5NiAzOCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiIHN0cm9rZS13aWR0aD0iMC4yNTQxNyIvPgo8cGF0aCBkPSJNMCA1N0w5NiA1NyIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiIHN0cm9rZS13aWR0aD0iMC4yNTQxNyIvPgo8cGF0aCBkPSJNMCA3Nkw5NiA3NiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiIHN0cm9rZS13aWR0aD0iMC4yNTQxNyIvPgo8L2c+CjxyZWN0IHg9IjEwNCIgd2lkdGg9Ijk2IiBoZWlnaHQ9Ijc2IiByeD0iMS4xMzQzMyIgZmlsbD0id2hpdGUiLz4KPG1hc2sgaWQ9InBhdGgtOS1vdXRzaWRlLTFfNDE5OF8xMTA0OTMiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjE1Mi4wMTgiIHk9IjMuMjUiIHdpZHRoPSIzNSIgaGVpZ2h0PSI1MSIgZmlsbD0iYmxhY2siPgo8cmVjdCBmaWxsPSJ3aGl0ZSIgeD0iMTUyLjAxOCIgeT0iMy4yNSIgd2lkdGg9IjM1IiBoZWlnaHQ9IjUxIi8+CjxwYXRoIGQ9Ik0xNTMuMzQxIDcuMjYyNDlDMTUzLjM5IDUuODg2MDYgMTU0LjU0NiA0Ljc5OTU1IDE1NS45MTUgNC45NTA2MUMxNjAuNjM1IDUuNDcxNDMgMTY1LjE5OCA2Ljk5ODQgMTY5LjI5MyA5LjQzOTU4QzE3NC4xMDQgMTIuMzA3MyAxNzguMTEzIDE2LjM0MzggMTgwLjk0NyAyMS4xNzQ0QzE4My43ODEgMjYuMDA1IDE4NS4zNDkgMzEuNDczMiAxODUuNTA1IDM3LjA3MTZDMTg1LjYzOCA0MS44MzczIDE4NC43NDUgNDYuNTY1OSAxODIuODk3IDUwLjkzOThDMTgyLjM2MSA1Mi4yMDg1IDE4MC44NDggNTIuNjg4MiAxNzkuNjIzIDUyLjA1ODZDMTc4LjM5OCA1MS40MjkxIDE3Ny45MjcgNDkuOTI5IDE3OC40NDYgNDguNjUzM0MxNzkuOTE5IDQ1LjAzMjUgMTgwLjYyOSA0MS4xMzY1IDE4MC41MiAzNy4yMTA5QzE4MC4zODcgMzIuNDUyMiAxNzkuMDU0IDI3LjgwNDIgMTc2LjY0NSAyMy42OTgyQzE3NC4yMzYgMTkuNTkyMiAxNzAuODI5IDE2LjE2MTIgMTY2Ljc0IDEzLjcyMzZDMTYzLjM2NiAxMS43MTI4IDE1OS42MTkgMTAuNDMxNyAxNTUuNzQgOS45NTE1MkMxNTQuMzczIDkuNzgyMzQgMTUzLjI5MyA4LjYzODkxIDE1My4zNDEgNy4yNjI0OVoiLz4KPC9tYXNrPgo8cGF0aCBkPSJNMTUzLjM0MSA3LjI2MjQ5QzE1My4zOSA1Ljg4NjA2IDE1NC41NDYgNC43OTk1NSAxNTUuOTE1IDQuOTUwNjFDMTYwLjYzNSA1LjQ3MTQzIDE2NS4xOTggNi45OTg0IDE2OS4yOTMgOS40Mzk1OEMxNzQuMTA0IDEyLjMwNzMgMTc4LjExMyAxNi4zNDM4IDE4MC45NDcgMjEuMTc0NEMxODMuNzgxIDI2LjAwNSAxODUuMzQ5IDMxLjQ3MzIgMTg1LjUwNSAzNy4wNzE2QzE4NS42MzggNDEuODM3MyAxODQuNzQ1IDQ2LjU2NTkgMTgyLjg5NyA1MC45Mzk4QzE4Mi4zNjEgNTIuMjA4NSAxODAuODQ4IDUyLjY4ODIgMTc5LjYyMyA1Mi4wNTg2QzE3OC4zOTggNTEuNDI5MSAxNzcuOTI3IDQ5LjkyOSAxNzguNDQ2IDQ4LjY1MzNDMTc5LjkxOSA0NS4wMzI1IDE4MC42MjkgNDEuMTM2NSAxODAuNTIgMzcuMjEwOUMxODAuMzg3IDMyLjQ1MjIgMTc5LjA1NCAyNy44MDQyIDE3Ni42NDUgMjMuNjk4MkMxNzQuMjM2IDE5LjU5MjIgMTcwLjgyOSAxNi4xNjEyIDE2Ni43NCAxMy43MjM2QzE2My4zNjYgMTEuNzEyOCAxNTkuNjE5IDEwLjQzMTcgMTU1Ljc0IDkuOTUxNTJDMTU0LjM3MyA5Ljc4MjM0IDE1My4yOTMgOC42Mzg5MSAxNTMuMzQxIDcuMjYyNDlaIiBmaWxsPSIjRkY0RDVBIi8+CjxwYXRoIGQ9Ik0xNTMuMzQxIDcuMjYyNDlDMTUzLjM5IDUuODg2MDYgMTU0LjU0NiA0Ljc5OTU1IDE1NS45MTUgNC45NTA2MUMxNjAuNjM1IDUuNDcxNDMgMTY1LjE5OCA2Ljk5ODQgMTY5LjI5MyA5LjQzOTU4QzE3NC4xMDQgMTIuMzA3MyAxNzguMTEzIDE2LjM0MzggMTgwLjk0NyAyMS4xNzQ0QzE4My43ODEgMjYuMDA1IDE4NS4zNDkgMzEuNDczMiAxODUuNTA1IDM3LjA3MTZDMTg1LjYzOCA0MS44MzczIDE4NC43NDUgNDYuNTY1OSAxODIuODk3IDUwLjkzOThDMTgyLjM2MSA1Mi4yMDg1IDE4MC44NDggNTIuNjg4MiAxNzkuNjIzIDUyLjA1ODZDMTc4LjM5OCA1MS40MjkxIDE3Ny45MjcgNDkuOTI5IDE3OC40NDYgNDguNjUzM0MxNzkuOTE5IDQ1LjAzMjUgMTgwLjYyOSA0MS4xMzY1IDE4MC41MiAzNy4yMTA5QzE4MC4zODcgMzIuNDUyMiAxNzkuMDU0IDI3LjgwNDIgMTc2LjY0NSAyMy42OTgyQzE3NC4yMzYgMTkuNTkyMiAxNzAuODI5IDE2LjE2MTIgMTY2Ljc0IDEzLjcyMzZDMTYzLjM2NiAxMS43MTI4IDE1OS42MTkgMTAuNDMxNyAxNTUuNzQgOS45NTE1MkMxNTQuMzczIDkuNzgyMzQgMTUzLjI5MyA4LjYzODkxIDE1My4zNDEgNy4yNjI0OVoiIGZpbGw9IndoaXRlIiBmaWxsLW9wYWNpdHk9IjAuMSIvPgo8cGF0aCBkPSJNMTUzLjM0MSA3LjI2MjQ5QzE1My4zOSA1Ljg4NjA2IDE1NC41NDYgNC43OTk1NSAxNTUuOTE1IDQuOTUwNjFDMTYwLjYzNSA1LjQ3MTQzIDE2NS4xOTggNi45OTg0IDE2OS4yOTMgOS40Mzk1OEMxNzQuMTA0IDEyLjMwNzMgMTc4LjExMyAxNi4zNDM4IDE4MC45NDcgMjEuMTc0NEMxODMuNzgxIDI2LjAwNSAxODUuMzQ5IDMxLjQ3MzIgMTg1LjUwNSAzNy4wNzE2QzE4NS42MzggNDEuODM3MyAxODQuNzQ1IDQ2LjU2NTkgMTgyLjg5NyA1MC45Mzk4QzE4Mi4zNjEgNTIuMjA4NSAxODAuODQ4IDUyLjY4ODIgMTc5LjYyMyA1Mi4wNTg2QzE3OC4zOTggNTEuNDI5MSAxNzcuOTI3IDQ5LjkyOSAxNzguNDQ2IDQ4LjY1MzNDMTc5LjkxOSA0NS4wMzI1IDE4MC42MjkgNDEuMTM2NSAxODAuNTIgMzcuMjEwOUMxODAuMzg3IDMyLjQ1MjIgMTc5LjA1NCAyNy44MDQyIDE3Ni42NDUgMjMuNjk4MkMxNzQuMjM2IDE5LjU5MjIgMTcwLjgyOSAxNi4xNjEyIDE2Ni43NCAxMy43MjM2QzE2My4zNjYgMTEuNzEyOCAxNTkuNjE5IDEwLjQzMTcgMTU1Ljc0IDkuOTUxNTJDMTU0LjM3MyA5Ljc4MjM0IDE1My4yOTMgOC42Mzg5MSAxNTMuMzQxIDcuMjYyNDlaIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjEuOTMzNzEiIG1hc2s9InVybCgjcGF0aC05LW91dHNpZGUtMV80MTk4XzExMDQ5MykiLz4KPHBhdGggZD0iTTE1MS4xOTUgNy4yNjI0OUMxNTEuMTQ3IDUuODg2MDYgMTQ5Ljk5IDQuNzk5NTUgMTQ4LjYyMSA0Ljk1MDYyQzE0My43MjcgNS40OTA2NyAxMzkuMDAzIDcuMTEyMzcgMTM0Ljc5NiA5LjcxMDUzQzEyOS44ODEgMTIuNzQ2NSAxMjUuODQxIDE3LjAxMDkgMTIzLjA3NSAyMi4wODM1QzEyMC4zMDkgMjcuMTU2MSAxMTguOTEzIDMyLjg2MTggMTE5LjAyNCAzOC42MzgzQzExOS4xMzUgNDQuNDE0OCAxMjAuNzQ5IDUwLjA2MjcgMTIzLjcwOCA1NS4wMjU0QzEyNi42NjYgNTkuOTg4MSAxMzAuODY2IDY0LjA5NDMgMTM1Ljg5NSA2Ni45MzkzQzE0MC45MjQgNjkuNzg0MyAxNDYuNjA3IDcxLjI3IDE1Mi4zODQgNzEuMjQ5OEMxNTguMTYyIDcxLjIyOTYgMTYzLjgzNCA2OS43MDQ0IDE2OC44NDMgNjYuODI0M0MxNzMuMTI5IDY0LjM1OTYgMTc2LjgwMiA2MC45NzU0IDE3OS42MDUgNTYuOTI3M0MxODAuMzg5IDU1Ljc5NDkgMTc5Ljk4NCA1NC4yNjA3IDE3OC43OTYgNTMuNTYzN0MxNzcuNjA4IDUyLjg2NjggMTc2LjA4OSA1My4yNzI0IDE3NS4yOSA1NC4zOTQzQzE3Mi45MzYgNTcuNjk5OSAxNjkuODkxIDYwLjQ2ODEgMTY2LjM1NyA2Mi41MDA3QzE2Mi4wOTkgNjQuOTQ4NyAxNTcuMjc4IDY2LjI0NTIgMTUyLjM2NyA2Ni4yNjIzQzE0Ny40NTYgNjYuMjc5NSAxNDIuNjI1IDY1LjAxNjcgMTM4LjM1MSA2Mi41OTg0QzEzNC4wNzcgNjAuMTgwMiAxMzAuNTA2IDU2LjY4OTkgMTI3Ljk5MiA1Mi40NzE2QzEyNS40NzcgNDguMjUzMyAxMjQuMTA1IDQzLjQ1MjYgMTI0LjAxMSAzOC41NDI2QzEyMy45MTYgMzMuNjMyNSAxMjUuMTAzIDI4Ljc4MjcgMTI3LjQ1NCAyNC40NzFDMTI5LjgwNSAyMC4xNTkzIDEzMy4yMzkgMTYuNTM0NSAxMzcuNDE3IDEzLjk1MzlDMTQwLjg4NiAxMS44MTEzIDE0NC43NjkgMTAuNDUgMTQ4Ljc5NiA5Ljk1MTUxQzE1MC4xNjMgOS43ODIzNCAxNTEuMjQzIDguNjM4OTEgMTUxLjE5NSA3LjI2MjQ5WiIgZmlsbD0iIzRDQUY1MCIvPgo8cGF0aCBkPSJNMTQ3LjEwNiAyOS4yMzQ0VjMzLjVIMTQ2LjU0OVYyOS4yMzQ0SDE0Ny4xMDZaTTE0OC40NzcgMjkuMjM0NFYyOS42OTczSDE0NS4xODFWMjkuMjM0NEgxNDguNDc3Wk0xNDguNTkxIDMxLjk1MDJWMzEuODgyOEMxNDguNTkxIDMxLjY1NDMgMTQ4LjYyNSAzMS40NDI0IDE0OC42OTEgMzEuMjQ3MUMxNDguNzU3IDMxLjA0OTggMTQ4Ljg1MyAzMC44Nzg5IDE0OC45NzggMzAuNzM0NEMxNDkuMTAzIDMwLjU4NzkgMTQ5LjI1NCAzMC40NzQ2IDE0OS40MzIgMzAuMzk0NUMxNDkuNjEgMzAuMzEyNSAxNDkuODA5IDMwLjI3MTUgMTUwLjAzIDMwLjI3MTVDMTUwLjI1MiAzMC4yNzE1IDE1MC40NTMgMzAuMzEyNSAxNTAuNjMgMzAuMzk0NUMxNTAuODEgMzAuNDc0NiAxNTAuOTYyIDMwLjU4NzkgMTUxLjA4NyAzMC43MzQ0QzE1MS4yMTQgMzAuODc4OSAxNTEuMzExIDMxLjA0OTggMTUxLjM3NyAzMS4yNDcxQzE1MS40NDQgMzEuNDQyNCAxNTEuNDc3IDMxLjY1NDMgMTUxLjQ3NyAzMS44ODI4VjMxLjk1MDJDMTUxLjQ3NyAzMi4xNzg3IDE1MS40NDQgMzIuMzkwNiAxNTEuMzc3IDMyLjU4NTlDMTUxLjMxMSAzMi43ODEyIDE1MS4yMTQgMzIuOTUyMSAxNTEuMDg3IDMzLjA5ODZDMTUwLjk2MiAzMy4yNDMyIDE1MC44MTEgMzMuMzU2NCAxNTAuNjMzIDMzLjQzODVDMTUwLjQ1OCAzMy41MTg2IDE1MC4yNTggMzMuNTU4NiAxNTAuMDM2IDMzLjU1ODZDMTQ5LjgxMyAzMy41NTg2IDE0OS42MTMgMzMuNTE4NiAxNDkuNDM1IDMzLjQzODVDMTQ5LjI1NyAzMy4zNTY0IDE0OS4xMDUgMzMuMjQzMiAxNDguOTc4IDMzLjA5ODZDMTQ4Ljg1MyAzMi45NTIxIDE0OC43NTcgMzIuNzgxMiAxNDguNjkxIDMyLjU4NTlDMTQ4LjYyNSAzMi4zOTA2IDE0OC41OTEgMzIuMTc4NyAxNDguNTkxIDMxLjk1MDJaTTE0OS4xMzMgMzEuODgyOFYzMS45NTAyQzE0OS4xMzMgMzIuMTA4NCAxNDkuMTUyIDMyLjI1NzggMTQ5LjE4OSAzMi4zOTg0QzE0OS4yMjYgMzIuNTM3MSAxNDkuMjgyIDMyLjY2MDIgMTQ5LjM1NiAzMi43Njc2QzE0OS40MzIgMzIuODc1IDE0OS41MjcgMzIuOTYgMTQ5LjY0IDMzLjAyMjVDMTQ5Ljc1MyAzMy4wODMgMTQ5Ljg4NSAzMy4xMTMzIDE1MC4wMzYgMzMuMTEzM0MxNTAuMTg0IDMzLjExMzMgMTUwLjMxNCAzMy4wODMgMTUwLjQyNSAzMy4wMjI1QzE1MC41MzkgMzIuOTYgMTUwLjYzMiAzMi44NzUgMTUwLjcwNyAzMi43Njc2QzE1MC43ODEgMzIuNjYwMiAxNTAuODM2IDMyLjUzNzEgMTUwLjg3NCAzMi4zOTg0QzE1MC45MTMgMzIuMjU3OCAxNTAuOTMyIDMyLjEwODQgMTUwLjkzMiAzMS45NTAyVjMxLjg4MjhDMTUwLjkzMiAzMS43MjY2IDE1MC45MTMgMzEuNTc5MSAxNTAuODc0IDMxLjQ0MDRDMTUwLjgzNiAzMS4yOTk4IDE1MC43OCAzMS4xNzU4IDE1MC43MDQgMzEuMDY4NEMxNTAuNjI5IDMwLjk1OSAxNTAuNTM2IDMwLjg3MyAxNTAuNDIyIDMwLjgxMDVDMTUwLjMxMSAzMC43NDggMTUwLjE4IDMwLjcxNjggMTUwLjAzIDMwLjcxNjhDMTQ5Ljg4MSAzMC43MTY4IDE0OS43NSAzMC43NDggMTQ5LjYzNyAzMC44MTA1QzE0OS41MjYgMzAuODczIDE0OS40MzIgMzAuOTU5IDE0OS4zNTYgMzEuMDY4NEMxNDkuMjgyIDMxLjE3NTggMTQ5LjIyNiAzMS4yOTk4IDE0OS4xODkgMzEuNDQwNEMxNDkuMTUyIDMxLjU3OTEgMTQ5LjEzMyAzMS43MjY2IDE0OS4xMzMgMzEuODgyOFpNMTUzLjQ4NCAzMC4zMzAxVjMwLjc0NjFIMTUxLjc3VjMwLjMzMDFIMTUzLjQ4NFpNMTUyLjM1IDI5LjU1OTZIMTUyLjg5MlYzMi43MTQ4QzE1Mi44OTIgMzIuODIyMyAxNTIuOTA5IDMyLjkwMzMgMTUyLjk0MiAzMi45NThDMTUyLjk3NSAzMy4wMTI3IDE1My4wMTggMzMuMDQ4OCAxNTMuMDcxIDMzLjA2NjRDMTUzLjEyNCAzMy4wODQgMTUzLjE4IDMzLjA5MjggMTUzLjI0MSAzMy4wOTI4QzE1My4yODYgMzMuMDkyOCAxNTMuMzMzIDMzLjA4ODkgMTUzLjM4MSAzMy4wODExQzE1My40MzIgMzMuMDcxMyAxNTMuNDcgMzMuMDYzNSAxNTMuNDk2IDMzLjA1NzZMMTUzLjQ5OSAzMy41QzE1My40NTYgMzMuNTEzNyAxNTMuMzk5IDMzLjUyNjQgMTUzLjMyOSAzMy41MzgxQzE1My4yNiAzMy41NTE4IDE1My4xNzcgMzMuNTU4NiAxNTMuMDggMzMuNTU4NkMxNTIuOTQ3IDMzLjU1ODYgMTUyLjgyNSAzMy41MzIyIDE1Mi43MTMgMzMuNDc5NUMxNTIuNjAyIDMzLjQyNjggMTUyLjUxMyAzMy4zMzg5IDE1Mi40NDcgMzMuMjE1OEMxNTIuMzgyIDMzLjA5MDggMTUyLjM1IDMyLjkyMjkgMTUyLjM1IDMyLjcxMTlWMjkuNTU5NlpNMTU1Ljk4OSAzMi45NThWMzEuMzI2MkMxNTUuOTg5IDMxLjIwMTIgMTU1Ljk2MyAzMS4wOTI4IDE1NS45MTMgMzEuMDAxQzE1NS44NjQgMzAuOTA3MiAxNTUuNzkgMzAuODM1IDE1NS42OSAzMC43ODQyQzE1NS41OSAzMC43MzM0IDE1NS40NjcgMzAuNzA4IDE1NS4zMjEgMzAuNzA4QzE1NS4xODQgMzAuNzA4IDE1NS4wNjQgMzAuNzMxNCAxNTQuOTYgMzAuNzc4M0MxNTQuODU5IDMwLjgyNTIgMTU0Ljc3OSAzMC44ODY3IDE1NC43MiAzMC45NjI5QzE1NC42NjQgMzEuMDM5MSAxNTQuNjM1IDMxLjEyMTEgMTU0LjYzNSAzMS4yMDlIMTU0LjA5M0MxNTQuMDkzIDMxLjA5NTcgMTU0LjEyMyAzMC45ODM0IDE1NC4xODEgMzAuODcyMUMxNTQuMjQgMzAuNzYwNyAxNTQuMzI0IDMwLjY2MDIgMTU0LjQzMyAzMC41NzAzQzE1NC41NDQgMzAuNDc4NSAxNTQuNjc3IDMwLjQwNjIgMTU0LjgzMiAzMC4zNTM1QzE1NC45ODggMzAuMjk4OCAxNTUuMTYyIDMwLjI3MTUgMTU1LjM1MyAzMC4yNzE1QzE1NS41ODMgMzAuMjcxNSAxNTUuNzg3IDMwLjMxMDUgMTU1Ljk2MiAzMC4zODg3QzE1Ni4xNCAzMC40NjY4IDE1Ni4yNzkgMzAuNTg1IDE1Ni4zNzggMzAuNzQzMkMxNTYuNDggMzAuODk5NCAxNTYuNTMxIDMxLjA5NTcgMTU2LjUzMSAzMS4zMzJWMzIuODA4NkMxNTYuNTMxIDMyLjkxNDEgMTU2LjU0IDMzLjAyNjQgMTU2LjU1NyAzMy4xNDU1QzE1Ni41NzcgMzMuMjY0NiAxNTYuNjA1IDMzLjM2NzIgMTU2LjY0MiAzMy40NTMxVjMzLjVIMTU2LjA3N0MxNTYuMDQ5IDMzLjQzNzUgMTU2LjAyOCAzMy4zNTQ1IDE1Ni4wMTIgMzMuMjUxQzE1NS45OTcgMzMuMTQ1NSAxNTUuOTg5IDMzLjA0NzkgMTU1Ljk4OSAzMi45NThaTTE1Ni4wODMgMzEuNTc4MUwxNTYuMDg4IDMxLjk1OUgxNTUuNTQxQzE1NS4zODYgMzEuOTU5IDE1NS4yNDkgMzEuOTcxNyAxNTUuMTI3IDMxLjk5NzFDMTU1LjAwNiAzMi4wMjA1IDE1NC45MDUgMzIuMDU2NiAxNTQuODIzIDMyLjEwNTVDMTU0Ljc0MSAzMi4xNTQzIDE1NC42NzggMzIuMjE1OCAxNTQuNjM1IDMyLjI5QzE1NC41OTIgMzIuMzYyMyAxNTQuNTcxIDMyLjQ0NzMgMTU0LjU3MSAzMi41NDQ5QzE1NC41NzEgMzIuNjQ0NSAxNTQuNTkzIDMyLjczNTQgMTU0LjYzOCAzMi44MTc0QzE1NC42ODMgMzIuODk5NCAxNTQuNzUgMzIuOTY0OCAxNTQuODQgMzMuMDEzN0MxNTQuOTMyIDMzLjA2MDUgMTU1LjA0NCAzMy4wODQgMTU1LjE3NyAzMy4wODRDMTU1LjM0MyAzMy4wODQgMTU1LjQ5IDMzLjA0ODggMTU1LjYxNyAzMi45Nzg1QzE1NS43NDQgMzIuOTA4MiAxNTUuODQ0IDMyLjgyMjMgMTU1LjkxOCAzMi43MjA3QzE1NS45OTUgMzIuNjE5MSAxNTYuMDM2IDMyLjUyMDUgMTU2LjA0MiAzMi40MjQ4TDE1Ni4yNzMgMzIuNjg1NUMxNTYuMjU5IDMyLjc2NzYgMTU2LjIyMiAzMi44NTg0IDE1Ni4xNjIgMzIuOTU4QzE1Ni4xMDEgMzMuMDU3NiAxNTYuMDIgMzMuMTUzMyAxNTUuOTE4IDMzLjI0NTFDMTU1LjgxOSAzMy4zMzUgMTU1LjcgMzMuNDEwMiAxNTUuNTYxIDMzLjQ3MDdDMTU1LjQyNCAzMy41MjkzIDE1NS4yNyAzMy41NTg2IDE1NS4wOTggMzMuNTU4NkMxNTQuODgzIDMzLjU1ODYgMTU0LjY5NSAzMy41MTY2IDE1NC41MzMgMzMuNDMyNkMxNTQuMzczIDMzLjM0ODYgMTU0LjI0OCAzMy4yMzYzIDE1NC4xNTggMzMuMDk1N0MxNTQuMDcgMzIuOTUzMSAxNTQuMDI2IDMyLjc5MzkgMTU0LjAyNiAzMi42MTgyQzE1NC4wMjYgMzIuNDQ4MiAxNTQuMDU5IDMyLjI5ODggMTU0LjEyNSAzMi4xNjk5QzE1NC4xOTIgMzIuMDM5MSAxNTQuMjg4IDMxLjkzMDcgMTU0LjQxMyAzMS44NDQ3QzE1NC41MzggMzEuNzU2OCAxNTQuNjg4IDMxLjY5MDQgMTU0Ljg2NCAzMS42NDU1QzE1NS4wNCAzMS42MDA2IDE1NS4yMzYgMzEuNTc4MSAxNTUuNDUzIDMxLjU3ODFIMTU2LjA4M1pNMTU3Ljk3MiAyOVYzMy41SDE1Ny40MjdWMjlIMTU3Ljk3MloiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuMzgiLz4KPHBhdGggZD0iTTE0NS43MzIgMzYuOTM5NVY0NS41SDE0NC4zMlYzOC42MTUyTDE0Mi4yMjggMzkuMzI0MlYzOC4xNTgyTDE0NS41NjIgMzYuOTM5NUgxNDUuNzMyWk0xNTQuMjc1IDQzLjE3MzhDMTU0LjI3NSA0My43MDUxIDE1NC4xNTIgNDQuMTUyMyAxNTMuOTA2IDQ0LjUxNTZDMTUzLjY2IDQ0Ljg3ODkgMTUzLjMyNCA0NS4xNTQzIDE1Mi44OTggNDUuMzQxOEMxNTIuNDc2IDQ1LjUyNTQgMTUyIDQ1LjYxNzIgMTUxLjQ2OCA0NS42MTcyQzE1MC45MzcgNDUuNjE3MiAxNTAuNDU4IDQ1LjUyNTQgMTUwLjAzMyA0NS4zNDE4QzE0OS42MDcgNDUuMTU0MyAxNDkuMjcxIDQ0Ljg3ODkgMTQ5LjAyNSA0NC41MTU2QzE0OC43NzkgNDQuMTUyMyAxNDguNjU2IDQzLjcwNTEgMTQ4LjY1NiA0My4xNzM4QzE0OC42NTYgNDIuODIyMyAxNDguNzI0IDQyLjUwMzkgMTQ4Ljg2MSA0Mi4yMTg4QzE0OC45OTggNDEuOTI5NyAxNDkuMTkxIDQxLjY4MTYgMTQ5LjQ0MSA0MS40NzQ2QzE0OS42OTUgNDEuMjYzNyAxNDkuOTkyIDQxLjEwMTYgMTUwLjMzMiA0MC45ODgzQzE1MC42NzUgNDAuODc1IDE1MS4wNSA0MC44MTg0IDE1MS40NTcgNDAuODE4NEMxNTEuOTk2IDQwLjgxODQgMTUyLjQ3OCA0MC45MTggMTUyLjkwNCA0MS4xMTcyQzE1My4zMyA0MS4zMTY0IDE1My42NjQgNDEuNTkxOCAxNTMuOTA2IDQxLjk0MzRDMTU0LjE1MiA0Mi4yOTQ5IDE1NC4yNzUgNDIuNzA1MSAxNTQuMjc1IDQzLjE3MzhaTTE1Mi44NTcgNDMuMTAzNUMxNTIuODU3IDQyLjgxODQgMTUyLjc5OCA0Mi41Njg0IDE1Mi42ODEgNDIuMzUzNUMxNTIuNTY0IDQyLjEzODcgMTUyLjQgNDEuOTcyNyAxNTIuMTg5IDQxLjg1NTVDMTUxLjk3OCA0MS43MzgzIDE1MS43MzQgNDEuNjc5NyAxNTEuNDU3IDQxLjY3OTdDMTUxLjE3NSA0MS42Nzk3IDE1MC45MzEgNDEuNzM4MyAxNTAuNzI0IDQxLjg1NTVDMTUwLjUxNyA0MS45NzI3IDE1MC4zNTUgNDIuMTM4NyAxNTAuMjM4IDQyLjM1MzVDMTUwLjEyNSA0Mi41Njg0IDE1MC4wNjggNDIuODE4NCAxNTAuMDY4IDQzLjEwMzVDMTUwLjA2OCA0My4zOTI2IDE1MC4xMjUgNDMuNjQyNiAxNTAuMjM4IDQzLjg1MzVDMTUwLjM1MSA0NC4wNjA1IDE1MC41MTMgNDQuMjE4OCAxNTAuNzI0IDQ0LjMyODFDMTUwLjkzNSA0NC40Mzc1IDE1MS4xODMgNDQuNDkyMiAxNTEuNDY4IDQ0LjQ5MjJDMTUxLjc1MyA0NC40OTIyIDE1MiA0NC40Mzc1IDE1Mi4yMDcgNDQuMzI4MUMxNTIuNDE0IDQ0LjIxODggMTUyLjU3NCA0NC4wNjA1IDE1Mi42ODcgNDMuODUzNUMxNTIuOCA0My42NDI2IDE1Mi44NTcgNDMuMzkyNiAxNTIuODU3IDQzLjEwMzVaTTE1NC4wODIgMzkuMjEyOUMxNTQuMDgyIDM5LjYzODcgMTUzLjk2OCA0MC4wMTc2IDE1My43NDIgNDAuMzQ5NkMxNTMuNTE5IDQwLjY4MTYgMTUzLjIxIDQwLjk0MzQgMTUyLjgxNiA0MS4xMzQ4QzE1Mi40MjEgNDEuMzIyMyAxNTEuOTcyIDQxLjQxNiAxNTEuNDY4IDQxLjQxNkMxNTAuOTYgNDEuNDE2IDE1MC41MDcgNDEuMzIyMyAxNTAuMTA5IDQxLjEzNDhDMTQ5LjcxNCA0MC45NDM0IDE0OS40MDQgNDAuNjgxNiAxNDkuMTc3IDQwLjM0OTZDMTQ4Ljk1NSA0MC4wMTc2IDE0OC44NDMgMzkuNjM4NyAxNDguODQzIDM5LjIxMjlDMTQ4Ljg0MyAzOC43MDUxIDE0OC45NTUgMzguMjc3MyAxNDkuMTc3IDM3LjkyOTdDMTQ5LjQwNCAzNy41NzgxIDE0OS43MTQgMzcuMzEwNSAxNTAuMTA5IDM3LjEyN0MxNTAuNTAzIDM2Ljk0MzQgMTUwLjk1NSAzNi44NTE2IDE1MS40NjIgMzYuODUxNkMxNTEuOTcgMzYuODUxNiAxNTIuNDIxIDM2Ljk0MzQgMTUyLjgxNiAzNy4xMjdDMTUzLjIxIDM3LjMxMDUgMTUzLjUxOSAzNy41NzgxIDE1My43NDIgMzcuOTI5N0MxNTMuOTY4IDM4LjI3NzMgMTU0LjA4MiAzOC43MDUxIDE1NC4wODIgMzkuMjEyOVpNMTUyLjY2OSAzOS4yNTk4QzE1Mi42NjkgMzkuMDA1OSAxNTIuNjE5IDM4Ljc4MzIgMTUyLjUxNyAzOC41OTE4QzE1Mi40MTkgMzguMzk2NSAxNTIuMjgxIDM4LjI0NDEgMTUyLjEwMSAzOC4xMzQ4QzE1MS45MjEgMzguMDI1NCAxNTEuNzA4IDM3Ljk3MDcgMTUxLjQ2MiAzNy45NzA3QzE1MS4yMTYgMzcuOTcwNyAxNTEuMDAzIDM4LjAyMzQgMTUwLjgyNCAzOC4xMjg5QzE1MC42NDQgMzguMjM0NCAxNTAuNTA1IDM4LjM4MjggMTUwLjQwOCAzOC41NzQyQzE1MC4zMSAzOC43NjU2IDE1MC4yNjEgMzguOTk0MSAxNTAuMjYxIDM5LjI1OThDMTUwLjI2MSAzOS41MjE1IDE1MC4zMSAzOS43NSAxNTAuNDA4IDM5Ljk0NTNDMTUwLjUwNSA0MC4xMzY3IDE1MC42NDQgNDAuMjg3MSAxNTAuODI0IDQwLjM5NjVDMTUxLjAwNyA0MC41MDU5IDE1MS4yMjIgNDAuNTYwNSAxNTEuNDY4IDQwLjU2MDVDMTUxLjcxNCA0MC41NjA1IDE1MS45MjcgNDAuNTA1OSAxNTIuMTA3IDQwLjM5NjVDMTUyLjI4NyA0MC4yODcxIDE1Mi40MjUgNDAuMTM2NyAxNTIuNTIzIDM5Ljk0NTNDMTUyLjYyMSAzOS43NSAxNTIuNjY5IDM5LjUyMTUgMTUyLjY2OSAzOS4yNTk4Wk0xNTcuMTc1IDQwLjU5NTdIMTU4LjAxOUMxNTguMzQ3IDQwLjU5NTcgMTU4LjYxOSA0MC41MzkxIDE1OC44MzMgNDAuNDI1OEMxNTkuMDUyIDQwLjMxMjUgMTU5LjIxNCA0MC4xNTYyIDE1OS4zMiAzOS45NTdDMTU5LjQyNSAzOS43NTc4IDE1OS40NzggMzkuNTI5MyAxNTkuNDc4IDM5LjI3MTVDMTU5LjQ3OCAzOS4wMDIgMTU5LjQyOSAzOC43NzE1IDE1OS4zMzIgMzguNTgwMUMxNTkuMjM4IDM4LjM4NDggMTU5LjA5MyAzOC4yMzQ0IDE1OC44OTggMzguMTI4OUMxNTguNzA3IDM4LjAyMzQgMTU4LjQ2MiAzNy45NzA3IDE1OC4xNjYgMzcuOTcwN0MxNTcuOTE2IDM3Ljk3MDcgMTU3LjY4OSAzOC4wMjE1IDE1Ny40ODYgMzguMTIzQzE1Ny4yODcgMzguMjIwNyAxNTcuMTI4IDM4LjM2MTMgMTU3LjAxMSAzOC41NDQ5QzE1Ni44OTQgMzguNzI0NiAxNTYuODM1IDM4LjkzOTUgMTU2LjgzNSAzOS4xODk1SDE1NS40MTdDMTU1LjQxNyAzOC43MzYzIDE1NS41MzcgMzguMzM0IDE1NS43NzUgMzcuOTgyNEMxNTYuMDEzIDM3LjYzMDkgMTU2LjMzNyAzNy4zNTU1IDE1Ni43NDggMzcuMTU2MkMxNTcuMTYyIDM2Ljk1MzEgMTU3LjYyNiAzNi44NTE2IDE1OC4xNDIgMzYuODUxNkMxNTguNjkzIDM2Ljg1MTYgMTU5LjE3MyAzNi45NDM0IDE1OS41ODMgMzcuMTI3QzE1OS45OTggMzcuMzA2NiAxNjAuMzIgMzcuNTc2MiAxNjAuNTUgMzcuOTM1NUMxNjAuNzgxIDM4LjI5NDkgMTYwLjg5NiAzOC43NDAyIDE2MC44OTYgMzkuMjcxNUMxNjAuODk2IDM5LjUxMzcgMTYwLjgzOSAzOS43NTk4IDE2MC43MjYgNDAuMDA5OEMxNjAuNjEzIDQwLjI1OTggMTYwLjQ0NSA0MC40ODgzIDE2MC4yMjIgNDAuNjk1M0MxNjAgNDAuODk4NCAxNTkuNzIyIDQxLjA2NDUgMTU5LjM5IDQxLjE5MzRDMTU5LjA1OCA0MS4zMTg0IDE1OC42NzMgNDEuMzgwOSAxNTguMjM2IDQxLjM4MDlIMTU3LjE3NVY0MC41OTU3Wk0xNTcuMTc1IDQxLjY5NzNWNDAuOTIzOEgxNTguMjM2QzE1OC43MzYgNDAuOTIzOCAxNTkuMTYyIDQwLjk4MjQgMTU5LjUxMyA0MS4wOTk2QzE1OS44NjkgNDEuMjE2OCAxNjAuMTU4IDQxLjM3ODkgMTYwLjM4IDQxLjU4NTlDMTYwLjYwMyA0MS43ODkxIDE2MC43NjUgNDIuMDIxNSAxNjAuODY3IDQyLjI4MzJDMTYwLjk3MiA0Mi41NDQ5IDE2MS4wMjUgNDIuODIyMyAxNjEuMDI1IDQzLjExNTJDMTYxLjAyNSA0My41MTM3IDE2MC45NTMgNDMuODY5MSAxNjAuODA4IDQ0LjE4MTZDMTYwLjY2NyA0NC40OTAyIDE2MC40NjYgNDQuNzUyIDE2MC4yMDUgNDQuOTY2OEMxNTkuOTQzIDQ1LjE4MTYgMTU5LjYzNiA0NS4zNDM4IDE1OS4yODUgNDUuNDUzMUMxNTguOTM3IDQ1LjU2MjUgMTU4LjU1OCA0NS42MTcyIDE1OC4xNDggNDUuNjE3MkMxNTcuNzgxIDQ1LjYxNzIgMTU3LjQyOSA0NS41NjY0IDE1Ny4wOTMgNDUuNDY0OEMxNTYuNzU3IDQ1LjM2MzMgMTU2LjQ1NyA0NS4yMTI5IDE1Ni4xOTEgNDUuMDEzN0MxNTUuOTI1IDQ0LjgxMDUgMTU1LjcxNCA0NC41NTg2IDE1NS41NTggNDQuMjU3OEMxNTUuNDA2IDQzLjk1MzEgMTU1LjMzIDQzLjYwMTYgMTU1LjMzIDQzLjIwMzFIMTU2Ljc0MkMxNTYuNzQyIDQzLjQ1NyAxNTYuOCA0My42ODE2IDE1Ni45MTcgNDMuODc3QzE1Ny4wMzkgNDQuMDY4NCAxNTcuMjA3IDQ0LjIxODggMTU3LjQyMSA0NC4zMjgxQzE1Ny42NCA0NC40Mzc1IDE1Ny44OSA0NC40OTIyIDE1OC4xNzEgNDQuNDkyMkMxNTguNDY4IDQ0LjQ5MjIgMTU4LjcyNCA0NC40Mzk1IDE1OC45MzkgNDQuMzM0QzE1OS4xNTQgNDQuMjI4NSAxNTkuMzE4IDQ0LjA3MjMgMTU5LjQzMSA0My44NjUyQzE1OS41NDggNDMuNjU4MiAxNTkuNjA3IDQzLjQwODIgMTU5LjYwNyA0My4xMTUyQzE1OS42MDcgNDIuNzgzMiAxNTkuNTQyIDQyLjUxMzcgMTU5LjQxNCA0Mi4zMDY2QzE1OS4yODUgNDIuMDk5NiAxNTkuMTAxIDQxLjk0NzMgMTU4Ljg2MyA0MS44NDk2QzE1OC42MjUgNDEuNzQ4IDE1OC4zNDMgNDEuNjk3MyAxNTguMDE5IDQxLjY5NzNIMTU3LjE3NVoiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuODciLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAyXzQxOThfMTEwNDkzKSI+CjxwYXRoIGQ9Ik0yIDg4TDE5NyA4OCIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxwYXRoIGQ9Ik0yIDEwNkwxOTcgMTA2IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC4xMiIgc3Ryb2tlLXdpZHRoPSIwLjUiLz4KPHBhdGggZD0iTTIgMTI0TDE5NyAxMjQiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1vcGFjaXR5PSIwLjEyIiBzdHJva2Utd2lkdGg9IjAuNSIvPgo8cGF0aCBkPSJNMiAxNDJMMTk3IDE0MiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiIHN0cm9rZS13aWR0aD0iMC41Ii8+CjxwYXRoIGQ9Ik0yIDE2MEwxOTcgMTYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC4xMiIvPgo8cGF0aCBkPSJNMTAzLjY5NSA5MUMxMDMuNjk1IDg5Ljg5NTQgMTA0LjU5IDg5IDEwNS42OTUgODlIMTE3LjY5NUMxMTguNzk5IDg5IDExOS42OTUgODkuODk1NCAxMTkuNjk1IDkxVjE2MEgxMDMuNjk1VjkxWiIgZmlsbD0iIzQxOTZGNiIvPgo8cGF0aCBkPSJNMTM2IDEyNEMxMzYgMTIyLjg5NSAxMzYuODk1IDEyMiAxMzggMTIySDE1MEMxNTEuMTA1IDEyMiAxNTIgMTIyLjg5NSAxNTIgMTI0VjE2MEgxMzZWMTI0WiIgZmlsbD0iIzQxOTZGNiIvPgo8cGF0aCBkPSJNNy42OTQ4MiAxNDNDNy42OTQ4MiAxNDEuODk1IDguNTkwMjUgMTQxIDkuNjk0ODIgMTQxSDIxLjY5NDhDMjIuNzk5NCAxNDEgMjMuNjk0OCAxNDEuODk1IDIzLjY5NDggMTQzVjE2MEg3LjY5NDgyVjE0M1oiIGZpbGw9IiM0MTk2RjYiLz4KPHBhdGggZD0iTTM5LjY5NDggMTA3QzM5LjY5NDggMTA1Ljg5NSA0MC41OTAzIDEwNSA0MS42OTQ4IDEwNUg1My42OTQ4QzU0Ljc5OTQgMTA1IDU1LjY5NDggMTA1Ljg5NSA1NS42OTQ4IDEwN1YxNjBIMzkuNjk0OFYxMDdaIiBmaWxsPSIjNDE5NkY2Ii8+CjxwYXRoIGQ9Ik03MiAxMzJDNzIgMTMwLjg5NSA3Mi44OTU0IDEzMCA3NCAxMzBIODZDODcuMTA0NiAxMzAgODggMTMwLjg5NSA4OCAxMzJWMTYwSDcyVjEzMloiIGZpbGw9IiM0MTk2RjYiLz4KPHBhdGggZD0iTTE2Ny42OTUgMTUwQzE2Ny42OTUgMTQ4Ljg5NSAxNjguNTkgMTQ4IDE2OS42OTUgMTQ4SDE4MS42OTVDMTgyLjc5OSAxNDggMTgzLjY5NSAxNDguODk1IDE4My42OTUgMTUwVjE2MEgxNjcuNjk1VjE1MFoiIGZpbGw9IiM0MTk2RjYiLz4KPHBhdGggZD0iTTQgMTA5TDE4LjUyMTEgMTAzLjAzMUMxOC41OTMzIDEwMy4wMDEgMTguNjY4NyAxMDIuOTggMTguNzQ1NyAxMDIuOTY4TDU5LjU3NDcgOTYuNTM2NUM1OS42NjE1IDk2LjUyMjggNTkuNzQ5OCA5Ni41MjA3IDU5LjgzNzMgOTYuNTMwMUw5OS4wOTMzIDEwMC43NTVMMTM5LjA0NCA5OS43MTMxTDE4MS4xNDIgOTUuODQwMkMxODEuMjEgOTUuODMzOSAxODEuMjc4IDk1LjgyMDYgMTgxLjM0NCA5NS44MDA1TDE5NyA5MSIgc3Ryb2tlPSIjRkZDMTA3IiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8Y2lyY2xlIGN4PSI1OSIgY3k9Ijk3IiByPSIxLjUiIGZpbGw9IndoaXRlIiBzdHJva2U9IiNGRkMxMDciLz4KPGNpcmNsZSBjeD0iMTguNjk0OCIgY3k9IjEwMy4xNjEiIHI9IjEuNSIgZmlsbD0id2hpdGUiIHN0cm9rZT0iI0ZGQzEwNyIvPgo8Y2lyY2xlIGN4PSIzLjY5NDgyIiBjeT0iMTA5LjE2MSIgcj0iMS41IiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSIjRkZDMTA3Ii8+CjxjaXJjbGUgY3g9IjEwMCIgY3k9IjEwMSIgcj0iMS41IiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSIjRkZDMTA3Ii8+CjxjaXJjbGUgY3g9IjE0MyIgY3k9Ijk5IiByPSIxLjUiIGZpbGw9IndoaXRlIiBzdHJva2U9IiNGRkMxMDciLz4KPGNpcmNsZSBjeD0iMTgwLjY5NSIgY3k9Ijk2LjE2MTEiIHI9IjEuNSIgZmlsbD0id2hpdGUiIHN0cm9rZT0iI0ZGQzEwNyIvPgo8Y2lyY2xlIGN4PSIxOTYiIGN5PSI5MSIgcj0iMS41IiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSIjRkZDMTA3Ii8+CjxwYXRoIGQ9Ik00IDEzMkwxOC42MzkzIDExOS44MTRMNjAuMzA1IDEyNy42TDEwMC4yODIgMTE2TDE0MC4yNTggMTE2TDE3Ny45ODIgMTIyLjE4NEwxOTYgMTI3LjYiIHN0cm9rZT0iIzRDQUY1MCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPGNpcmNsZSBjeD0iNTkiIGN5PSIxMjgiIHI9IjEuNSIgZmlsbD0id2hpdGUiIHN0cm9rZT0iIzRDQUY1MCIvPgo8Y2lyY2xlIGN4PSIxOSIgY3k9IjEyMCIgcj0iMS41IiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSIjNENBRjUwIi8+CjxjaXJjbGUgY3g9IjEwMCIgY3k9IjExNiIgcj0iMS41IiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSIjNENBRjUwIi8+CjxjaXJjbGUgY3g9IjE3OC42OTUiIGN5PSIxMjIiIHI9IjEuNSIgZmlsbD0id2hpdGUiIHN0cm9rZT0iIzRDQUY1MCIvPgo8Y2lyY2xlIGN4PSIxOTYiIGN5PSIxMjgiIHI9IjEuNSIgZmlsbD0id2hpdGUiIHN0cm9rZT0iIzRDQUY1MCIvPgo8Y2lyY2xlIGN4PSIzLjY5NDgyIiBjeT0iMTMxLjE2MSIgcj0iMS41IiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSIjNENBRjUwIi8+CjxjaXJjbGUgY3g9IjE0MyIgY3k9IjExNiIgcj0iMS41IiBmaWxsPSJ3aGl0ZSIgc3Ryb2tlPSIjNENBRjUwIi8+CjwvZz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl80MTk4XzExMDQ5MyIgeDE9IjQ1LjY5ODYiIHkxPSI4NC43NDkzIiB4Mj0iNDUuNjk4NiIgeTI9Ii0xOS45Mzg4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIG9mZnNldD0iMC4xNzMzODkiIHN0b3AtY29sb3I9IiM2REM3NzAiLz4KPHN0b3Agb2Zmc2V0PSIwLjI2Mjk3OSIgc3RvcC1jb2xvcj0iIzZEQzc3MCIvPgo8c3RvcCBvZmZzZXQ9IjAuMjY3OTY5IiBzdG9wLWNvbG9yPSIjRkZDMTA3Ii8+CjxzdG9wIG9mZnNldD0iMC40NDYxNzgiIHN0b3AtY29sb3I9IiNGRkMxMDciLz4KPHN0b3Agb2Zmc2V0PSIwLjQ0ODMxNiIgc3RvcC1jb2xvcj0iI0ZEOEYzQyIvPgo8c3RvcCBvZmZzZXQ9IjAuNjI0Mzg3IiBzdG9wLWNvbG9yPSIjRkQ4RjNDIi8+CjxzdG9wIG9mZnNldD0iMC42MzA4MDMiIHN0b3AtY29sb3I9IiNGMjczN0MiLz4KPC9saW5lYXJHcmFkaWVudD4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDFfbGluZWFyXzQxOThfMTEwNDkzIiB4MT0iNDUuMjc5NyIgeTE9Ijc0LjY2MzUiIHgyPSI0NS4yMjYxIiB5Mj0iLTIwLjI0MzEiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agb2Zmc2V0PSIwLjE4MjI1NCIgc3RvcC1jb2xvcj0iIzNGQTcxQSIvPgo8c3RvcCBvZmZzZXQ9IjAuMTkwMTE4IiBzdG9wLWNvbG9yPSIjRkZBNjAwIi8+CjxzdG9wIG9mZnNldD0iMC4zODI3NjEiIHN0b3AtY29sb3I9IiNGRkE2MDAiLz4KPHN0b3Agb2Zmc2V0PSIwLjM4ODI2OCIgc3RvcC1jb2xvcj0iI0Y1NkUwOCIvPgo8c3RvcCBvZmZzZXQ9IjAuNTgxNjk1IiBzdG9wLWNvbG9yPSIjRjU2RTA4Ii8+CjxzdG9wIG9mZnNldD0iMC41ODc5ODUiIHN0b3AtY29sb3I9IiNGRjRENUEiLz4KPC9saW5lYXJHcmFkaWVudD4KPGNsaXBQYXRoIGlkPSJjbGlwMF80MTk4XzExMDQ5MyI+CjxyZWN0IHdpZHRoPSI5NiIgaGVpZ2h0PSI3NiIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwMV80MTk4XzExMDQ5MyI+CjxyZWN0IHdpZHRoPSI5NiIgaGVpZ2h0PSI3NiIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwMl80MTk4XzExMDQ5MyI+CjxyZWN0IHdpZHRoPSIyMDAiIGhlaWdodD0iNzYiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDg0KSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=", "description": "Display time series data using customizable line and bar charts. Use various pie charts to display the latest values.", "order": 1000, "name": "Charts" }, "widgetTypeFqns": [ "time_series_chart", + "line_chart", + "bar_chart", + "point_chart", "charts.basic_timeseries", "charts.state_chart", "range_chart", diff --git a/application/src/main/data/json/system/widget_types/bar_chart.json b/application/src/main/data/json/system/widget_types/bar_chart.json new file mode 100644 index 0000000000..c857922eea --- /dev/null +++ b/application/src/main/data/json/system/widget_types/bar_chart.json @@ -0,0 +1,32 @@ +{ + "fqn": "bar_chart", + "name": "Bar chart", + "deprecated": false, + "image": "tb-image:Y2hhcnRfKDIpLnN2Zw==:IkJhciBjaGFydCIgc3lzdGVtIHdpZGdldCBpbWFnZQ==;data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE2MCIgdmlld0JveD0iMCAwIDIwMCAxNjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF80MTgzXzkwODc3KSI+CjxwYXRoIGQ9Ik0yLjg0NzY2IDEuMjgxMjVWN0gyLjEyNVYyLjE4MzU5TDAuNjY3OTY5IDIuNzE0ODRWMi4wNjI1TDIuNzM0MzggMS4yODEyNUgyLjg0NzY2Wk04LjY3NTE3IDMuNzAzMTJWNC41NzAzMUM4LjY3NTE3IDUuMDM2NDYgOC42MzM1MSA1LjQyOTY5IDguNTUwMTcgNS43NUM4LjQ2Njg0IDYuMDcwMzEgOC4zNDcwNSA2LjMyODEyIDguMTkwOCA2LjUyMzQ0QzguMDM0NTUgNi43MTg3NSA3Ljg0NTc1IDYuODYwNjggNy42MjQzOSA2Ljk0OTIyQzcuNDA1NjQgNy4wMzUxNiA3LjE1ODI1IDcuMDc4MTIgNi44ODIyIDcuMDc4MTJDNi42NjM0NSA3LjA3ODEyIDYuNDYxNjMgNy4wNTA3OCA2LjI3NjczIDYuOTk2MDlDNi4wOTE4NCA2Ljk0MTQxIDUuOTI1MTcgNi44NTQxNyA1Ljc3NjczIDYuNzM0MzhDNS42MzA5IDYuNjExOTggNS41MDU5IDYuNDUzMTIgNS40MDE3MyA2LjI1NzgxQzUuMjk3NTcgNi4wNjI1IDUuMjE4MTQgNS44MjU1MiA1LjE2MzQ1IDUuNTQ2ODhDNS4xMDg3NyA1LjI2ODIzIDUuMDgxNDIgNC45NDI3MSA1LjA4MTQyIDQuNTcwMzFWMy43MDMxMkM1LjA4MTQyIDMuMjM2OTggNS4xMjMwOSAyLjg0NjM1IDUuMjA2NDIgMi41MzEyNUM1LjI5MjM2IDIuMjE2MTUgNS40MTM0NSAxLjk2MzU0IDUuNTY5NyAxLjc3MzQ0QzUuNzI1OTUgMS41ODA3MyA1LjkxMzQ1IDEuNDQyNzEgNi4xMzIyIDEuMzU5MzhDNi4zNTM1NiAxLjI3NjA0IDYuNjAwOTUgMS4yMzQzOCA2Ljg3NDM5IDEuMjM0MzhDNy4wOTU3NSAxLjIzNDM4IDcuMjk4ODcgMS4yNjE3MiA3LjQ4Mzc3IDEuMzE2NDFDNy42NzEyNyAxLjM2ODQ5IDcuODM3OTMgMS40NTMxMiA3Ljk4Mzc3IDEuNTcwMzFDOC4xMjk2IDEuNjg0OSA4LjI1MzMgMS44Mzg1NCA4LjM1NDg2IDIuMDMxMjVDOC40NTkwMyAyLjIyMTM1IDguNTM4NDUgMi40NTQ0MyA4LjU5MzE0IDIuNzMwNDdDOC42NDc4MyAzLjAwNjUxIDguNjc1MTcgMy4zMzA3MyA4LjY3NTE3IDMuNzAzMTJaTTcuOTQ4NjEgNC42ODc1VjMuNTgyMDNDNy45NDg2MSAzLjMyNjgyIDcuOTMyOTggMy4xMDI4NiA3LjkwMTczIDIuOTEwMTZDNy44NzMwOSAyLjcxNDg0IDcuODMwMTIgMi41NDgxOCA3Ljc3MjgzIDIuNDEwMTZDNy43MTU1NCAyLjI3MjE0IDcuNjQyNjIgMi4xNjAxNiA3LjU1NDA4IDIuMDc0MjJDNy40NjgxNCAxLjk4ODI4IDcuMzY3ODggMS45MjU3OCA3LjI1MzMgMS44ODY3MkM3LjE0MTMyIDEuODQ1MDUgNy4wMTUwMiAxLjgyNDIyIDYuODc0MzkgMS44MjQyMkM2LjcwMjUyIDEuODI0MjIgNi41NTAxNyAxLjg1Njc3IDYuNDE3MzYgMS45MjE4OEM2LjI4NDU1IDEuOTg0MzggNi4xNzI1NyAyLjA4NDY0IDYuMDgxNDIgMi4yMjI2NkM1Ljk5Mjg4IDIuMzYwNjggNS45MjUxNyAyLjU0MTY3IDUuODc4MyAyLjc2NTYyQzUuODMxNDIgMi45ODk1OCA1LjgwNzk4IDMuMjYxNzIgNS44MDc5OCAzLjU4MjAzVjQuNjg3NUM1LjgwNzk4IDQuOTQyNzEgNS44MjIzMSA1LjE2Nzk3IDUuODUwOTUgNS4zNjMyOEM1Ljg4MjIgNS41NTg1OSA1LjkyNzc4IDUuNzI3ODYgNS45ODc2NyA1Ljg3MTA5QzYuMDQ3NTcgNi4wMTE3MiA2LjEyMDQ4IDYuMTI3NiA2LjIwNjQyIDYuMjE4NzVDNi4yOTIzNiA2LjMwOTkgNi4zOTEzMiA2LjM3NzYgNi41MDMzIDYuNDIxODhDNi42MTc4OCA2LjQ2MzU0IDYuNzQ0MTggNi40ODQzOCA2Ljg4MjIgNi40ODQzOEM3LjA1OTI5IDYuNDg0MzggNy4yMTQyMyA2LjQ1MDUyIDcuMzQ3MDUgNi4zODI4MUM3LjQ3OTg2IDYuMzE1MSA3LjU5MDU0IDYuMjA5NjQgNy42NzkwOCA2LjA2NjQxQzcuNzcwMjIgNS45MjA1NyA3LjgzNzkzIDUuNzM0MzggNy44ODIyIDUuNTA3ODFDNy45MjY0NyA1LjI3ODY1IDcuOTQ4NjEgNS4wMDUyMSA3Ljk0ODYxIDQuNjg3NVpNMTMuMzA3NCAzLjcwMzEyVjQuNTcwMzFDMTMuMzA3NCA1LjAzNjQ2IDEzLjI2NTcgNS40Mjk2OSAxMy4xODI0IDUuNzVDMTMuMDk5IDYuMDcwMzEgMTIuOTc5MyA2LjMyODEyIDEyLjgyMyA2LjUyMzQ0QzEyLjY2NjggNi43MTg3NSAxMi40Nzc5IDYuODYwNjggMTIuMjU2NiA2Ljk0OTIyQzEyLjAzNzggNy4wMzUxNiAxMS43OTA0IDcuMDc4MTIgMTEuNTE0NCA3LjA3ODEyQzExLjI5NTcgNy4wNzgxMiAxMS4wOTM4IDcuMDUwNzggMTAuOTA4OSA2Ljk5NjA5QzEwLjcyNCA2Ljk0MTQxIDEwLjU1NzQgNi44NTQxNyAxMC40MDg5IDYuNzM0MzhDMTAuMjYzMSA2LjYxMTk4IDEwLjEzODEgNi40NTMxMiAxMC4wMzM5IDYuMjU3ODFDOS45Mjk3NyA2LjA2MjUgOS44NTAzNCA1LjgyNTUyIDkuNzk1NjYgNS41NDY4OEM5Ljc0MDk3IDUuMjY4MjMgOS43MTM2MyA0Ljk0MjcxIDkuNzEzNjMgNC41NzAzMVYzLjcwMzEyQzkuNzEzNjMgMy4yMzY5OCA5Ljc1NTI5IDIuODQ2MzUgOS44Mzg2MyAyLjUzMTI1QzkuOTI0NTYgMi4yMTYxNSAxMC4wNDU3IDEuOTYzNTQgMTAuMjAxOSAxLjc3MzQ0QzEwLjM1ODIgMS41ODA3MyAxMC41NDU3IDEuNDQyNzEgMTAuNzY0NCAxLjM1OTM4QzEwLjk4NTggMS4yNzYwNCAxMS4yMzMyIDEuMjM0MzggMTEuNTA2NiAxLjIzNDM4QzExLjcyNzkgMS4yMzQzOCAxMS45MzExIDEuMjYxNzIgMTIuMTE2IDEuMzE2NDFDMTIuMzAzNSAxLjM2ODQ5IDEyLjQ3MDEgMS40NTMxMiAxMi42MTYgMS41NzAzMUMxMi43NjE4IDEuNjg0OSAxMi44ODU1IDEuODM4NTQgMTIuOTg3MSAyLjAzMTI1QzEzLjA5MTIgMi4yMjEzNSAxMy4xNzA3IDIuNDU0NDMgMTMuMjI1MyAyLjczMDQ3QzEzLjI4IDMuMDA2NTEgMTMuMzA3NCAzLjMzMDczIDEzLjMwNzQgMy43MDMxMlpNMTIuNTgwOCA0LjY4NzVWMy41ODIwM0MxMi41ODA4IDMuMzI2ODIgMTIuNTY1MiAzLjEwMjg2IDEyLjUzMzkgMi45MTAxNkMxMi41MDUzIDIuNzE0ODQgMTIuNDYyMyAyLjU0ODE4IDEyLjQwNSAyLjQxMDE2QzEyLjM0NzcgMi4yNzIxNCAxMi4yNzQ4IDIuMTYwMTYgMTIuMTg2MyAyLjA3NDIyQzEyLjEwMDMgMS45ODgyOCAxMi4wMDAxIDEuOTI1NzggMTEuODg1NSAxLjg4NjcyQzExLjc3MzUgMS44NDUwNSAxMS42NDcyIDEuODI0MjIgMTEuNTA2NiAxLjgyNDIyQzExLjMzNDcgMS44MjQyMiAxMS4xODI0IDEuODU2NzcgMTEuMDQ5NiAxLjkyMTg4QzEwLjkxNjggMS45ODQzOCAxMC44MDQ4IDIuMDg0NjQgMTAuNzEzNiAyLjIyMjY2QzEwLjYyNTEgMi4zNjA2OCAxMC41NTc0IDIuNTQxNjcgMTAuNTEwNSAyLjc2NTYyQzEwLjQ2MzYgMi45ODk1OCAxMC40NDAyIDMuMjYxNzIgMTAuNDQwMiAzLjU4MjAzVjQuNjg3NUMxMC40NDAyIDQuOTQyNzEgMTAuNDU0NSA1LjE2Nzk3IDEwLjQ4MzIgNS4zNjMyOEMxMC41MTQ0IDUuNTU4NTkgMTAuNTYgNS43Mjc4NiAxMC42MTk5IDUuODcxMDlDMTAuNjc5OCA2LjAxMTcyIDEwLjc1MjcgNi4xMjc2IDEwLjgzODYgNi4yMTg3NUMxMC45MjQ2IDYuMzA5OSAxMS4wMjM1IDYuMzc3NiAxMS4xMzU1IDYuNDIxODhDMTEuMjUwMSA2LjQ2MzU0IDExLjM3NjQgNi40ODQzOCAxMS41MTQ0IDYuNDg0MzhDMTEuNjkxNSA2LjQ4NDM4IDExLjg0NjQgNi40NTA1MiAxMS45NzkzIDYuMzgyODFDMTIuMTEyMSA2LjMxNTEgMTIuMjIyNyA2LjIwOTY0IDEyLjMxMTMgNi4wNjY0MUMxMi40MDI0IDUuOTIwNTcgMTIuNDcwMSA1LjczNDM4IDEyLjUxNDQgNS41MDc4MUMxMi41NTg3IDUuMjc4NjUgMTIuNTgwOCA1LjAwNTIxIDEyLjU4MDggNC42ODc1Wk0xNC4zMDY4IDIuNzA3MDNWMi40MDYyNUMxNC4zMDY4IDIuMTkwMSAxNC4zNTM2IDEuOTkzNDkgMTQuNDQ3NCAxLjgxNjQxQzE0LjU0MTEgMS42MzkzMiAxNC42NzUzIDEuNDk3NCAxNC44NDk3IDEuMzkwNjJDMTUuMDI0MiAxLjI4Mzg1IDE1LjIzMTIgMS4yMzA0NyAxNS40NzA4IDEuMjMwNDdDMTUuNzE1NiAxLjIzMDQ3IDE1LjkyNCAxLjI4Mzg1IDE2LjA5NTggMS4zOTA2MkMxNi4yNzAzIDEuNDk3NCAxNi40MDQ0IDEuNjM5MzIgMTYuNDk4MiAxLjgxNjQxQzE2LjU5MTkgMS45OTM0OSAxNi42Mzg4IDIuMTkwMSAxNi42Mzg4IDIuNDA2MjVWMi43MDcwM0MxNi42Mzg4IDIuOTE3OTcgMTYuNTkxOSAzLjExMTk4IDE2LjQ5ODIgMy4yODkwNkMxNi40MDcgMy40NjYxNSAxNi4yNzQyIDMuNjA4MDcgMTYuMDk5NyAzLjcxNDg0QzE1LjkyNzkgMy44MjE2MSAxNS43MjA4IDMuODc1IDE1LjQ3ODYgMy44NzVDMTUuMjM2NSAzLjg3NSAxNS4wMjY4IDMuODIxNjEgMTQuODQ5NyAzLjcxNDg0QzE0LjY3NTMgMy42MDgwNyAxNC41NDExIDMuNDY2MTUgMTQuNDQ3NCAzLjI4OTA2QzE0LjM1MzYgMy4xMTE5OCAxNC4zMDY4IDIuOTE3OTcgMTQuMzA2OCAyLjcwNzAzWk0xNC44NDk3IDIuNDA2MjVWMi43MDcwM0MxNC44NDk3IDIuODI2ODIgMTQuODcxOSAyLjk0MDEgMTQuOTE2MSAzLjA0Njg4QzE0Ljk2MyAzLjE1MzY1IDE1LjAzMzMgMy4yNDA4OSAxNS4xMjcxIDMuMzA4NTlDMTUuMjIwOCAzLjM3MzcgMTUuMzM4IDMuNDA2MjUgMTUuNDc4NiAzLjQwNjI1QzE1LjYxOTMgMy40MDYyNSAxNS43MzUyIDMuMzczNyAxNS44MjYzIDMuMzA4NTlDMTUuOTE3NCAzLjI0MDg5IDE1Ljk4NTIgMy4xNTM2NSAxNi4wMjk0IDMuMDQ2ODhDMTYuMDczNyAyLjk0MDEgMTYuMDk1OCAyLjgyNjgyIDE2LjA5NTggMi43MDcwM1YyLjQwNjI1QzE2LjA5NTggMi4yODM4NSAxNi4wNzI0IDIuMTY5MjcgMTYuMDI1NSAyLjA2MjVDMTUuOTgxMiAxLjk1MzEyIDE1LjkxMjIgMS44NjU4OSAxNS44MTg1IDEuODAwNzhDMTUuNzI3MyAxLjczMzA3IDE1LjYxMTUgMS42OTkyMiAxNS40NzA4IDEuNjk5MjJDMTUuMzMyOCAxLjY5OTIyIDE1LjIxNjkgMS43MzMwNyAxNS4xMjMyIDEuODAwNzhDMTUuMDMyIDEuODY1ODkgMTQuOTYzIDEuOTUzMTIgMTQuOTE2MSAyLjA2MjVDMTQuODcxOSAyLjE2OTI3IDE0Ljg0OTcgMi4yODM4NSAxNC44NDk3IDIuNDA2MjVaTTE3LjA3NjMgNS45MTAxNlY1LjYwNTQ3QzE3LjA3NjMgNS4zOTE5MyAxNy4xMjMyIDUuMTk2NjEgMTcuMjE2OSA1LjAxOTUzQzE3LjMxMDcgNC44NDI0NSAxNy40NDQ4IDQuNzAwNTIgMTcuNjE5MyA0LjU5Mzc1QzE3Ljc5MzcgNC40ODY5OCAxOC4wMDA4IDQuNDMzNTkgMTguMjQwNCA0LjQzMzU5QzE4LjQ4NTIgNC40MzM1OSAxOC42OTM1IDQuNDg2OTggMTguODY1NCA0LjU5Mzc1QzE5LjAzOTggNC43MDA1MiAxOS4xNzQgNC44NDI0NSAxOS4yNjc3IDUuMDE5NTNDMTkuMzYxNSA1LjE5NjYxIDE5LjQwODMgNS4zOTE5MyAxOS40MDgzIDUuNjA1NDdWNS45MTAxNkMxOS40MDgzIDYuMTIzNyAxOS4zNjE1IDYuMzE5MDEgMTkuMjY3NyA2LjQ5NjA5QzE5LjE3NjYgNi42NzMxOCAxOS4wNDM3IDYuODE1MSAxOC44NjkzIDYuOTIxODhDMTguNjk3NCA3LjAyODY1IDE4LjQ5MDQgNy4wODIwMyAxOC4yNDgyIDcuMDgyMDNDMTguMDA2IDcuMDgyMDMgMTcuNzk3NyA3LjAyODY1IDE3LjYyMzIgNi45MjE4OEMxNy40NDg3IDYuODE1MSAxNy4zMTMzIDYuNjczMTggMTcuMjE2OSA2LjQ5NjA5QzE3LjEyMzIgNi4zMTkwMSAxNy4wNzYzIDYuMTIzNyAxNy4wNzYzIDUuOTEwMTZaTTE3LjYxOTMgNS42MDU0N1Y1LjkxMDE2QzE3LjYxOTMgNi4wMjk5NSAxNy42NDE0IDYuMTQ0NTMgMTcuNjg1NyA2LjI1MzkxQzE3LjczMjUgNi4zNjA2OCAxNy44MDI5IDYuNDQ3OTIgMTcuODk2NiA2LjUxNTYyQzE3Ljk5MDQgNi41ODA3MyAxOC4xMDc1IDYuNjEzMjggMTguMjQ4MiA2LjYxMzI4QzE4LjM4ODggNi42MTMyOCAxOC41MDQ3IDYuNTgwNzMgMTguNTk1OCA2LjUxNTYyQzE4LjY4OTYgNi40NDc5MiAxOC43NTg2IDYuMzYwNjggMTguODAyOSA2LjI1MzkxQzE4Ljg0NzEgNi4xNDcxNCAxOC44NjkzIDYuMDMyNTUgMTguODY5MyA1LjkxMDE2VjUuNjA1NDdDMTguODY5MyA1LjQ4MzA3IDE4Ljg0NTggNS4zNjg0OSAxOC43OTkgNS4yNjE3MkMxOC43NTQ3IDUuMTU0OTUgMTguNjg1NyA1LjA2OTAxIDE4LjU5MTkgNS4wMDM5MUMxOC41MDA4IDQuOTM2MiAxOC4zODM2IDQuOTAyMzQgMTguMjQwNCA0LjkwMjM0QzE4LjEwMjMgNC45MDIzNCAxNy45ODY1IDQuOTM2MiAxNy44OTI3IDUuMDAzOTFDMTcuODAxNiA1LjA2OTAxIDE3LjczMjUgNS4xNTQ5NSAxNy42ODU3IDUuMjYxNzJDMTcuNjQxNCA1LjM2ODQ5IDE3LjYxOTMgNS40ODMwNyAxNy42MTkzIDUuNjA1NDdaTTE4LjQyIDIuMTIxMDlMMTUuNjQyNyA2LjU2NjQxTDE1LjIzNjUgNi4zMDg1OUwxOC4wMTM4IDEuODYzMjhMMTguNDIgMi4xMjEwOVoiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuNTQiLz4KPHBhdGggZD0iTTguMDU4NTkgMzMuNjY3N0M4LjA1ODU5IDM0LjAxNDEgNy45Nzc4NiAzNC4zMDgzIDcuODE2NDEgMzQuNTUwNUM3LjY1NzU1IDM0Ljc5MDEgNy40NDE0MSAzNC45NzI0IDcuMTY3OTcgMzUuMDk3NEM2Ljg5NzE0IDM1LjIyMjQgNi41OTExNSAzNS4yODQ5IDYuMjUgMzUuMjg0OUM1LjkwODg1IDM1LjI4NDkgNS42MDE1NiAzNS4yMjI0IDUuMzI4MTIgMzUuMDk3NEM1LjA1NDY5IDM0Ljk3MjQgNC44Mzg1NCAzNC43OTAxIDQuNjc5NjkgMzQuNTUwNUM0LjUyMDgzIDM0LjMwODMgNC40NDE0MSAzNC4wMTQxIDQuNDQxNDEgMzMuNjY3N0M0LjQ0MTQxIDMzLjQ0MTIgNC40ODQzOCAzMy4yMzQxIDQuNTcwMzEgMzMuMDQ2NkM0LjY1ODg1IDMyLjg1NjUgNC43ODI1NSAzMi42OTEyIDQuOTQxNDEgMzIuNTUwNUM1LjEwMjg2IDMyLjQwOTkgNS4yOTI5NyAzMi4zMDE4IDUuNTExNzIgMzIuMjI2M0M1LjczMzA3IDMyLjE0ODIgNS45NzY1NiAzMi4xMDkxIDYuMjQyMTkgMzIuMTA5MUM2LjU5MTE1IDMyLjEwOTEgNi45MDIzNCAzMi4xNzY4IDcuMTc1NzggMzIuMzEyM0M3LjQ0OTIyIDMyLjQ0NTEgNy42NjQwNiAzMi42Mjg3IDcuODIwMzEgMzIuODYzQzcuOTc5MTcgMzMuMDk3NCA4LjA1ODU5IDMzLjM2NTYgOC4wNTg1OSAzMy42Njc3Wk03LjMzMjAzIDMzLjY1MjFDNy4zMzIwMyAzMy40NDEyIDcuMjg2NDYgMzMuMjU1IDcuMTk1MzEgMzMuMDkzNUM3LjEwNDE3IDMyLjkyOTQgNi45NzY1NiAzMi44MDE4IDYuODEyNSAzMi43MTA3QzYuNjQ4NDQgMzIuNjE5NSA2LjQ1ODMzIDMyLjU3NCA2LjI0MjE5IDMyLjU3NEM2LjAyMDgzIDMyLjU3NCA1LjgyOTQzIDMyLjYxOTUgNS42Njc5NyAzMi43MTA3QzUuNTA5MTEgMzIuODAxOCA1LjM4NTQyIDMyLjkyOTQgNS4yOTY4OCAzMy4wOTM1QzUuMjA4MzMgMzMuMjU1IDUuMTY0MDYgMzMuNDQxMiA1LjE2NDA2IDMzLjY1MjFDNS4xNjQwNiAzMy44NzA4IDUuMjA3MDMgMzQuMDU4MyA1LjI5Mjk3IDM0LjIxNDZDNS4zODE1MSAzNC4zNjgyIDUuNTA2NTEgMzQuNDg2NyA1LjY2Nzk3IDM0LjU3MDFDNS44MzIwMyAzNC42NTA4IDYuMDI2MDQgMzQuNjkxMiA2LjI1IDM0LjY5MTJDNi40NzM5NiAzNC42OTEyIDYuNjY2NjcgMzQuNjUwOCA2LjgyODEyIDM0LjU3MDFDNi45ODk1OCAzNC40ODY3IDcuMTEzMjggMzQuMzY4MiA3LjE5OTIyIDM0LjIxNDZDNy4yODc3NiAzNC4wNTgzIDcuMzMyMDMgMzMuODcwOCA3LjMzMjAzIDMzLjY1MjFaTTcuOTI1NzggMzAuOTk5OEM3LjkyNTc4IDMxLjI3NTggNy44NTI4NiAzMS41MjQ1IDcuNzA3MDMgMzEuNzQ1OEM3LjU2MTIgMzEuOTY3MiA3LjM2MTk4IDMyLjE0MTcgNy4xMDkzOCAzMi4yNjkzQzYuODU2NzcgMzIuMzk2OSA2LjU3MDMxIDMyLjQ2MDcgNi4yNSAzMi40NjA3QzUuOTI0NDggMzIuNDYwNyA1LjYzNDExIDMyLjM5NjkgNS4zNzg5MSAzMi4yNjkzQzUuMTI2MyAzMi4xNDE3IDQuOTI4MzkgMzEuOTY3MiA0Ljc4NTE2IDMxLjc0NThDNC42NDE5MyAzMS41MjQ1IDQuNTcwMzEgMzEuMjc1OCA0LjU3MDMxIDMwLjk5OThDNC41NzAzMSAzMC42NjkgNC42NDE5MyAzMC4zODc4IDQuNzg1MTYgMzAuMTU2QzQuOTMwOTkgMjkuOTI0MiA1LjEzMDIxIDI5Ljc0NzIgNS4zODI4MSAyOS42MjQ4QzUuNjM1NDIgMjkuNTAyNCA1LjkyMzE4IDI5LjQ0MTIgNi4yNDYwOSAyOS40NDEyQzYuNTcxNjEgMjkuNDQxMiA2Ljg2MDY4IDI5LjUwMjQgNy4xMTMyOCAyOS42MjQ4QzcuMzY1ODkgMjkuNzQ3MiA3LjU2MzggMjkuOTI0MiA3LjcwNzAzIDMwLjE1NkM3Ljg1Mjg2IDMwLjM4NzggNy45MjU3OCAzMC42NjkgNy45MjU3OCAzMC45OTk4Wk03LjIwMzEyIDMxLjAxMTVDNy4yMDMxMiAzMC44MjE0IDcuMTYyNzYgMzAuNjUzNCA3LjA4MjAzIDMwLjUwNzZDNy4wMDEzIDMwLjM2MTcgNi44ODkzMiAzMC4yNDcyIDYuNzQ2MDkgMzAuMTYzOEM2LjYwMjg2IDMwLjA3NzkgNi40MzYyIDMwLjAzNDkgNi4yNDYwOSAzMC4wMzQ5QzYuMDU1OTkgMzAuMDM0OSA1Ljg4OTMyIDMwLjA3NTMgNS43NDYwOSAzMC4xNTZDNS42MDU0NyAzMC4yMzQxIDUuNDk0NzkgMzAuMzQ2MSA1LjQxNDA2IDMwLjQ5MTlDNS4zMzU5NCAzMC42Mzc4IDUuMjk2ODggMzAuODExIDUuMjk2ODggMzEuMDExNUM1LjI5Njg4IDMxLjIwNjggNS4zMzU5NCAzMS4zNzc0IDUuNDE0MDYgMzEuNTIzMkM1LjQ5NDc5IDMxLjY2OSA1LjYwNjc3IDMxLjc4MjMgNS43NSAzMS44NjNDNS44OTMyMyAzMS45NDM4IDYuMDU5OSAzMS45ODQxIDYuMjUgMzEuOTg0MUM2LjQ0MDEgMzEuOTg0MSA2LjYwNTQ3IDMxLjk0MzggNi43NDYwOSAzMS44NjNDNi44ODkzMiAzMS43ODIzIDcuMDAxMyAzMS42NjkgNy4wODIwMyAzMS41MjMyQzcuMTYyNzYgMzEuMzc3NCA3LjIwMzEyIDMxLjIwNjggNy4yMDMxMiAzMS4wMTE1Wk0xMi42NzUyIDMxLjkwOTlWMzIuNzc3MUMxMi42NzUyIDMzLjI0MzIgMTIuNjMzNSAzMy42MzY1IDEyLjU1MDIgMzMuOTU2OEMxMi40NjY4IDM0LjI3NzEgMTIuMzQ3IDM0LjUzNDkgMTIuMTkwOCAzNC43MzAyQzEyLjAzNDUgMzQuOTI1NSAxMS44NDU3IDM1LjA2NzUgMTEuNjI0NCAzNS4xNTZDMTEuNDA1NiAzNS4yNDE5IDExLjE1ODIgMzUuMjg0OSAxMC44ODIyIDM1LjI4NDlDMTAuNjYzNSAzNS4yODQ5IDEwLjQ2MTYgMzUuMjU3NiAxMC4yNzY3IDM1LjIwMjlDMTAuMDkxOCAzNS4xNDgyIDkuOTI1MTcgMzUuMDYxIDkuNzc2NzMgMzQuOTQxMkM5LjYzMDkgMzQuODE4OCA5LjUwNTkgMzQuNjU5OSA5LjQwMTczIDM0LjQ2NDZDOS4yOTc1NyAzNC4yNjkzIDkuMjE4MTQgMzQuMDMyMyA5LjE2MzQ1IDMzLjc1MzdDOS4xMDg3NyAzMy40NzUgOS4wODE0MiAzMy4xNDk1IDkuMDgxNDIgMzIuNzc3MVYzMS45MDk5QzkuMDgxNDIgMzEuNDQzOCA5LjEyMzA5IDMxLjA1MzEgOS4yMDY0MiAzMC43MzhDOS4yOTIzNiAzMC40MjI5IDkuNDEzNDUgMzAuMTcwMyA5LjU2OTcgMjkuOTgwMkM5LjcyNTk1IDI5Ljc4NzUgOS45MTM0NSAyOS42NDk1IDEwLjEzMjIgMjkuNTY2MkMxMC4zNTM2IDI5LjQ4MjggMTAuNjAxIDI5LjQ0MTIgMTAuODc0NCAyOS40NDEyQzExLjA5NTcgMjkuNDQxMiAxMS4yOTg5IDI5LjQ2ODUgMTEuNDgzOCAyOS41MjMyQzExLjY3MTMgMjkuNTc1MyAxMS44Mzc5IDI5LjY1OTkgMTEuOTgzOCAyOS43NzcxQzEyLjEyOTYgMjkuODkxNyAxMi4yNTMzIDMwLjA0NTMgMTIuMzU0OSAzMC4yMzhDMTIuNDU5IDMwLjQyODEgMTIuNTM4NSAzMC42NjEyIDEyLjU5MzEgMzAuOTM3M0MxMi42NDc4IDMxLjIxMzMgMTIuNjc1MiAzMS41Mzc1IDEyLjY3NTIgMzEuOTA5OVpNMTEuOTQ4NiAzMi44OTQzVjMxLjc4ODhDMTEuOTQ4NiAzMS41MzM2IDExLjkzMyAzMS4zMDk3IDExLjkwMTcgMzEuMTE2OUMxMS44NzMxIDMwLjkyMTYgMTEuODMwMSAzMC43NTUgMTEuNzcyOCAzMC42MTY5QzExLjcxNTUgMzAuNDc4OSAxMS42NDI2IDMwLjM2NjkgMTEuNTU0MSAzMC4yODFDMTEuNDY4MSAzMC4xOTUxIDExLjM2NzkgMzAuMTMyNiAxMS4yNTMzIDMwLjA5MzVDMTEuMTQxMyAzMC4wNTE4IDExLjAxNSAzMC4wMzEgMTAuODc0NCAzMC4wMzFDMTAuNzAyNSAzMC4wMzEgMTAuNTUwMiAzMC4wNjM2IDEwLjQxNzQgMzAuMTI4N0MxMC4yODQ1IDMwLjE5MTIgMTAuMTcyNiAzMC4yOTE0IDEwLjA4MTQgMzAuNDI5NEM5Ljk5Mjg4IDMwLjU2NzUgOS45MjUxNyAzMC43NDg1IDkuODc4MyAzMC45NzI0QzkuODMxNDIgMzEuMTk2NCA5LjgwNzk4IDMxLjQ2ODUgOS44MDc5OCAzMS43ODg4VjMyLjg5NDNDOS44MDc5OCAzMy4xNDk1IDkuODIyMzEgMzMuMzc0OCA5Ljg1MDk1IDMzLjU3MDFDOS44ODIyIDMzLjc2NTQgOS45Mjc3OCAzMy45MzQ3IDkuOTg3NjcgMzQuMDc3OUMxMC4wNDc2IDM0LjIxODUgMTAuMTIwNSAzNC4zMzQ0IDEwLjIwNjQgMzQuNDI1NUMxMC4yOTI0IDM0LjUxNjcgMTAuMzkxMyAzNC41ODQ0IDEwLjUwMzMgMzQuNjI4N0MxMC42MTc5IDM0LjY3MDMgMTAuNzQ0MiAzNC42OTEyIDEwLjg4MjIgMzQuNjkxMkMxMS4wNTkzIDM0LjY5MTIgMTEuMjE0MiAzNC42NTczIDExLjM0NyAzNC41ODk2QzExLjQ3OTkgMzQuNTIxOSAxMS41OTA1IDM0LjQxNjQgMTEuNjc5MSAzNC4yNzMyQzExLjc3MDIgMzQuMTI3NCAxMS44Mzc5IDMzLjk0MTIgMTEuODgyMiAzMy43MTQ2QzExLjkyNjUgMzMuNDg1NCAxMS45NDg2IDMzLjIxMiAxMS45NDg2IDMyLjg5NDNaTTEzLjY3NDYgMzAuOTEzOFYzMC42MTNDMTMuNjc0NiAzMC4zOTY5IDEzLjcyMTQgMzAuMjAwMyAxMy44MTUyIDMwLjAyMzJDMTMuOTA4OSAyOS44NDYxIDE0LjA0MzEgMjkuNzA0MiAxNC4yMTc1IDI5LjU5NzRDMTQuMzkyIDI5LjQ5MDYgMTQuNTk5IDI5LjQzNzMgMTQuODM4NiAyOS40MzczQzE1LjA4MzQgMjkuNDM3MyAxNS4yOTE4IDI5LjQ5MDYgMTUuNDYzNiAyOS41OTc0QzE1LjYzODEgMjkuNzA0MiAxNS43NzIyIDI5Ljg0NjEgMTUuODY2IDMwLjAyMzJDMTUuOTU5NyAzMC4yMDAzIDE2LjAwNjYgMzAuMzk2OSAxNi4wMDY2IDMwLjYxM1YzMC45MTM4QzE2LjAwNjYgMzEuMTI0OCAxNS45NTk3IDMxLjMxODggMTUuODY2IDMxLjQ5NThDMTUuNzc0OCAzMS42NzI5IDE1LjY0MiAzMS44MTQ5IDE1LjQ2NzUgMzEuOTIxNkMxNS4yOTU3IDMyLjAyODQgMTUuMDg4NiAzMi4wODE4IDE0Ljg0NjQgMzIuMDgxOEMxNC42MDQzIDMyLjA4MTggMTQuMzk0NiAzMi4wMjg0IDE0LjIxNzUgMzEuOTIxNkMxNC4wNDMxIDMxLjgxNDkgMTMuOTA4OSAzMS42NzI5IDEzLjgxNTIgMzEuNDk1OEMxMy43MjE0IDMxLjMxODggMTMuNjc0NiAzMS4xMjQ4IDEzLjY3NDYgMzAuOTEzOFpNMTQuMjE3NSAzMC42MTNWMzAuOTEzOEMxNC4yMTc1IDMxLjAzMzYgMTQuMjM5NyAzMS4xNDY5IDE0LjI4MzkgMzEuMjUzN0MxNC4zMzA4IDMxLjM2MDQgMTQuNDAxMSAzMS40NDc3IDE0LjQ5NDkgMzEuNTE1NEMxNC41ODg2IDMxLjU4MDUgMTQuNzA1OCAzMS42MTMgMTQuODQ2NCAzMS42MTNDMTQuOTg3MSAzMS42MTMgMTUuMTAyOSAzMS41ODA1IDE1LjE5NDEgMzEuNTE1NEMxNS4yODUyIDMxLjQ0NzcgMTUuMzUyOSAzMS4zNjA0IDE1LjM5NzIgMzEuMjUzN0MxNS40NDE1IDMxLjE0NjkgMTUuNDYzNiAzMS4wMzM2IDE1LjQ2MzYgMzAuOTEzOFYzMC42MTNDMTUuNDYzNiAzMC40OTA2IDE1LjQ0MDIgMzAuMzc2MSAxNS4zOTMzIDMwLjI2OTNDMTUuMzQ5IDMwLjE1OTkgMTUuMjggMzAuMDcyNyAxNS4xODYzIDMwLjAwNzZDMTUuMDk1MSAyOS45Mzk5IDE0Ljk3OTMgMjkuOTA2IDE0LjgzODYgMjkuOTA2QzE0LjcwMDYgMjkuOTA2IDE0LjU4NDcgMjkuOTM5OSAxNC40OTEgMzAuMDA3NkMxNC4zOTk4IDMwLjA3MjcgMTQuMzMwOCAzMC4xNTk5IDE0LjI4MzkgMzAuMjY5M0MxNC4yMzk3IDMwLjM3NjEgMTQuMjE3NSAzMC40OTA2IDE0LjIxNzUgMzAuNjEzWk0xNi40NDQxIDM0LjExNjlWMzMuODEyM0MxNi40NDQxIDMzLjU5ODcgMTYuNDkxIDMzLjQwMzQgMTYuNTg0NyAzMy4yMjYzQzE2LjY3ODUgMzMuMDQ5MiAxNi44MTI2IDMyLjkwNzMgMTYuOTg3MSAzMi44MDA1QzE3LjE2MTUgMzIuNjkzOCAxNy4zNjg2IDMyLjY0MDQgMTcuNjA4MiAzMi42NDA0QzE3Ljg1MjkgMzIuNjQwNCAxOC4wNjEzIDMyLjY5MzggMTguMjMzMiAzMi44MDA1QzE4LjQwNzYgMzIuOTA3MyAxOC41NDE4IDMzLjA0OTIgMTguNjM1NSAzMy4yMjYzQzE4LjcyOTMgMzMuNDAzNCAxOC43NzYxIDMzLjU5ODcgMTguNzc2MSAzMy44MTIzVjM0LjExNjlDMTguNzc2MSAzNC4zMzA1IDE4LjcyOTMgMzQuNTI1OCAxOC42MzU1IDM0LjcwMjlDMTguNTQ0NCAzNC44OCAxOC40MTE1IDM1LjAyMTkgMTguMjM3MSAzNS4xMjg3QzE4LjA2NTIgMzUuMjM1NCAxNy44NTgyIDM1LjI4ODggMTcuNjE2IDM1LjI4ODhDMTcuMzczOCAzNS4yODg4IDE3LjE2NTQgMzUuMjM1NCAxNi45OTEgMzUuMTI4N0MxNi44MTY1IDM1LjAyMTkgMTYuNjgxMSAzNC44OCAxNi41ODQ3IDM0LjcwMjlDMTYuNDkxIDM0LjUyNTggMTYuNDQ0MSAzNC4zMzA1IDE2LjQ0NDEgMzQuMTE2OVpNMTYuOTg3MSAzMy44MTIzVjM0LjExNjlDMTYuOTg3MSAzNC4yMzY3IDE3LjAwOTIgMzQuMzUxMyAxNy4wNTM1IDM0LjQ2MDdDMTcuMTAwMyAzNC41Njc1IDE3LjE3MDcgMzQuNjU0NyAxNy4yNjQ0IDM0LjcyMjRDMTcuMzU4MiAzNC43ODc1IDE3LjQ3NTMgMzQuODIwMSAxNy42MTYgMzQuODIwMUMxNy43NTY2IDM0LjgyMDEgMTcuODcyNSAzNC43ODc1IDE3Ljk2MzYgMzQuNzIyNEMxOC4wNTc0IDM0LjY1NDcgMTguMTI2NCAzNC41Njc1IDE4LjE3MDcgMzQuNDYwN0MxOC4yMTQ5IDM0LjM1MzkgMTguMjM3MSAzNC4yMzkzIDE4LjIzNzEgMzQuMTE2OVYzMy44MTIzQzE4LjIzNzEgMzMuNjg5OSAxOC4yMTM2IDMzLjU3NTMgMTguMTY2OCAzMy40Njg1QzE4LjEyMjUgMzMuMzYxNyAxOC4wNTM1IDMzLjI3NTggMTcuOTU5NyAzMy4yMTA3QzE3Ljg2ODYgMzMuMTQzIDE3Ljc1MTQgMzMuMTA5MSAxNy42MDgyIDMzLjEwOTFDMTcuNDcwMSAzMy4xMDkxIDE3LjM1NDMgMzMuMTQzIDE3LjI2MDUgMzMuMjEwN0MxNy4xNjk0IDMzLjI3NTggMTcuMTAwMyAzMy4zNjE3IDE3LjA1MzUgMzMuNDY4NUMxNy4wMDkyIDMzLjU3NTMgMTYuOTg3MSAzMy42ODk5IDE2Ljk4NzEgMzMuODEyM1pNMTcuNzg3OCAzMC4zMjc5TDE1LjAxMDUgMzQuNzczMkwxNC42MDQzIDM0LjUxNTRMMTcuMzgxNiAzMC4wNzAxTDE3Ljc4NzggMzAuMzI3OVoiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuNTQiLz4KPHBhdGggZD0iTTcuMjQ2MDkgNTcuNzE4M0g3LjMwODU5VjU4LjMzMTVINy4yNDYwOUM2Ljg2MzI4IDU4LjMzMTUgNi41NDI5NyA1OC4zOTQgNi4yODUxNiA1OC41MTlDNi4wMjczNCA1OC42NDE0IDUuODIyOTIgNTguODA2OCA1LjY3MTg4IDU5LjAxNTFDNS41MjA4MyA1OS4yMjA5IDUuNDExNDYgNTkuNDUyNiA1LjM0Mzc1IDU5LjcxMDRDNS4yNzg2NSA1OS45NjgzIDUuMjQ2MDkgNjAuMjMgNS4yNDYwOSA2MC40OTU2VjYxLjMzMTVDNS4yNDYwOSA2MS41ODQxIDUuMjc2MDQgNjEuODA4MSA1LjMzNTk0IDYyLjAwMzRDNS4zOTU4MyA2Mi4xOTYxIDUuNDc3ODYgNjIuMzU4OSA1LjU4MjAzIDYyLjQ5MTdDNS42ODYyIDYyLjYyNDUgNS44MDMzOSA2Mi43MjQ4IDUuOTMzNTkgNjIuNzkyNUM2LjA2NjQxIDYyLjg2MDIgNi4yMDQ0MyA2Mi44OTQgNi4zNDc2NiA2Mi44OTRDNi41MTQzMiA2Mi44OTQgNi42NjI3NiA2Mi44NjI4IDYuNzkyOTcgNjIuODAwM0M2LjkyMzE4IDYyLjczNTIgNy4wMzI1NSA2Mi42NDUzIDcuMTIxMDkgNjIuNTMwOEM3LjIxMjI0IDYyLjQxMzYgNy4yODEyNSA2Mi4yNzU2IDcuMzI4MTIgNjIuMTE2N0M3LjM3NSA2MS45NTc4IDcuMzk4NDQgNjEuNzgzNCA3LjM5ODQ0IDYxLjU5MzNDNy4zOTg0NCA2MS40MjQgNy4zNzc2IDYxLjI2MTIgNy4zMzU5NCA2MS4xMDVDNy4yOTQyNyA2MC45NDYxIDcuMjMwNDcgNjAuODA1NSA3LjE0NDUzIDYwLjY4MzFDNy4wNTg1OSA2MC41NTgxIDYuOTUwNTIgNjAuNDYwNCA2LjgyMDMxIDYwLjM5MDFDNi42OTI3MSA2MC4zMTcyIDYuNTQwMzYgNjAuMjgwOCA2LjM2MzI4IDYwLjI4MDhDNi4xNjI3NiA2MC4yODA4IDUuOTc1MjYgNjAuMzMwMiA1LjgwMDc4IDYwLjQyOTJDNS42Mjg5MSA2MC41MjU2IDUuNDg2OTggNjAuNjUzMiA1LjM3NSA2MC44MTJDNS4yNjU2MiA2MC45NjgzIDUuMjAzMTIgNjEuMTM4OCA1LjE4NzUgNjEuMzIzN0w0LjgwNDY5IDYxLjMxOThDNC44NDExNSA2MS4wMjgyIDQuOTA4ODUgNjAuNzc5NSA1LjAwNzgxIDYwLjU3MzdDNS4xMDkzOCA2MC4zNjU0IDUuMjM0MzggNjAuMTk2MSA1LjM4MjgxIDYwLjA2NTlDNS41MzM4NSA1OS45MzMxIDUuNzAxODIgNTkuODM2OCA1Ljg4NjcyIDU5Ljc3NjlDNi4wNzQyMiA1OS43MTQ0IDYuMjcyMTQgNTkuNjgzMSA2LjQ4MDQ3IDU5LjY4MzFDNi43NjQzMiA1OS42ODMxIDcuMDA5MTEgNTkuNzM2NSA3LjIxNDg0IDU5Ljg0MzNDNy40MjA1NyA1OS45NSA3LjU4OTg0IDYwLjA5MzMgNy43MjI2NiA2MC4yNzI5QzcuODU1NDcgNjAuNDUgNy45NTMxMiA2MC42NTA2IDguMDE1NjIgNjAuODc0NUM4LjA4MDczIDYxLjA5NTkgOC4xMTMyOCA2MS4zMjM3IDguMTEzMjggNjEuNTU4MUM4LjExMzI4IDYxLjgyNjMgOC4wNzU1MiA2Mi4wNzc2IDggNjIuMzEyQzcuOTI0NDggNjIuNTQ2NCA3LjgxMTIgNjIuNzUyMSA3LjY2MDE2IDYyLjkyOTJDNy41MTE3MiA2My4xMDYzIDcuMzI4MTIgNjMuMjQ0MyA3LjEwOTM4IDYzLjM0MzNDNi44OTA2MiA2My40NDIyIDYuNjM2NzIgNjMuNDkxNyA2LjM0NzY2IDYzLjQ5MTdDNi4wNDAzNiA2My40OTE3IDUuNzcyMTQgNjMuNDI5MiA1LjU0Mjk3IDYzLjMwNDJDNS4zMTM4IDYzLjE3NjYgNS4xMjM3IDYzLjAwNzMgNC45NzI2NiA2Mi43OTY0QzQuODIxNjEgNjIuNTg1NCA0LjcwODMzIDYyLjM1MTEgNC42MzI4MSA2Mi4wOTMzQzQuNTU3MjkgNjEuODM1NCA0LjUxOTUzIDYxLjU3MzcgNC41MTk1MyA2MS4zMDgxVjYwLjk2ODNDNC41MTk1MyA2MC41NjcyIDQuNTU5OSA2MC4xNzQgNC42NDA2MiA1OS43ODg2QzQuNzIxMzUgNTkuNDAzMiA0Ljg2MDY4IDU5LjA1NDIgNS4wNTg1OSA1OC43NDE3QzUuMjU5MTEgNTguNDI5MiA1LjUzNjQ2IDU4LjE4MDUgNS44OTA2MiA1Ny45OTU2QzYuMjQ0NzkgNTcuODEwNyA2LjY5NjYxIDU3LjcxODMgNy4yNDYwOSA1Ny43MTgzWk0xMi42NzUyIDYwLjExNjdWNjAuOTgzOUMxMi42NzUyIDYxLjQ1IDEyLjYzMzUgNjEuODQzMyAxMi41NTAyIDYyLjE2MzZDMTIuNDY2OCA2Mi40ODM5IDEyLjM0NyA2Mi43NDE3IDEyLjE5MDggNjIuOTM3QzEyLjAzNDUgNjMuMTMyMyAxMS44NDU3IDYzLjI3NDMgMTEuNjI0NCA2My4zNjI4QzExLjQwNTYgNjMuNDQ4NyAxMS4xNTgyIDYzLjQ5MTcgMTAuODgyMiA2My40OTE3QzEwLjY2MzUgNjMuNDkxNyAxMC40NjE2IDYzLjQ2NDQgMTAuMjc2NyA2My40MDk3QzEwLjA5MTggNjMuMzU1IDkuOTI1MTcgNjMuMjY3NyA5Ljc3NjczIDYzLjE0NzlDOS42MzA5IDYzLjAyNTYgOS41MDU5IDYyLjg2NjcgOS40MDE3MyA2Mi42NzE0QzkuMjk3NTcgNjIuNDc2MSA5LjIxODE0IDYyLjIzOTEgOS4xNjM0NSA2MS45NjA0QzkuMTA4NzcgNjEuNjgxOCA5LjA4MTQyIDYxLjM1NjMgOS4wODE0MiA2MC45ODM5VjYwLjExNjdDOS4wODE0MiA1OS42NTA2IDkuMTIzMDkgNTkuMjU5OSA5LjIwNjQyIDU4Ljk0NDhDOS4yOTIzNiA1OC42Mjk3IDkuNDEzNDUgNTguMzc3MSA5LjU2OTcgNTguMTg3QzkuNzI1OTUgNTcuOTk0MyA5LjkxMzQ1IDU3Ljg1NjMgMTAuMTMyMiA1Ny43NzI5QzEwLjM1MzYgNTcuNjg5NiAxMC42MDEgNTcuNjQ3OSAxMC44NzQ0IDU3LjY0NzlDMTEuMDk1NyA1Ny42NDc5IDExLjI5ODkgNTcuNjc1MyAxMS40ODM4IDU3LjczQzExLjY3MTMgNTcuNzgyMSAxMS44Mzc5IDU3Ljg2NjcgMTEuOTgzOCA1Ny45ODM5QzEyLjEyOTYgNTguMDk4NSAxMi4yNTMzIDU4LjI1MjEgMTIuMzU0OSA1OC40NDQ4QzEyLjQ1OSA1OC42MzQ5IDEyLjUzODUgNTguODY4IDEyLjU5MzEgNTkuMTQ0QzEyLjY0NzggNTkuNDIwMSAxMi42NzUyIDU5Ljc0NDMgMTIuNjc1MiA2MC4xMTY3Wk0xMS45NDg2IDYxLjEwMTFWNTkuOTk1NkMxMS45NDg2IDU5Ljc0MDQgMTEuOTMzIDU5LjUxNjQgMTEuOTAxNyA1OS4zMjM3QzExLjg3MzEgNTkuMTI4NCAxMS44MzAxIDU4Ljk2MTggMTEuNzcyOCA1OC44MjM3QzExLjcxNTUgNTguNjg1NyAxMS42NDI2IDU4LjU3MzcgMTEuNTU0MSA1OC40ODc4QzExLjQ2ODEgNTguNDAxOSAxMS4zNjc5IDU4LjMzOTQgMTEuMjUzMyA1OC4zMDAzQzExLjE0MTMgNTguMjU4NiAxMS4wMTUgNTguMjM3OCAxMC44NzQ0IDU4LjIzNzhDMTAuNzAyNSA1OC4yMzc4IDEwLjU1MDIgNTguMjcwMyAxMC40MTc0IDU4LjMzNTRDMTAuMjg0NSA1OC4zOTc5IDEwLjE3MjYgNTguNDk4MiAxMC4wODE0IDU4LjYzNjJDOS45OTI4OCA1OC43NzQzIDkuOTI1MTcgNTguOTU1MiA5Ljg3ODMgNTkuMTc5MkM5LjgzMTQyIDU5LjQwMzIgOS44MDc5OCA1OS42NzUzIDkuODA3OTggNTkuOTk1NlY2MS4xMDExQzkuODA3OTggNjEuMzU2MyA5LjgyMjMxIDYxLjU4MTUgOS44NTA5NSA2MS43NzY5QzkuODgyMiA2MS45NzIyIDkuOTI3NzggNjIuMTQxNCA5Ljk4NzY3IDYyLjI4NDdDMTAuMDQ3NiA2Mi40MjUzIDEwLjEyMDUgNjIuNTQxMiAxMC4yMDY0IDYyLjYzMjNDMTAuMjkyNCA2Mi43MjM1IDEwLjM5MTMgNjIuNzkxMiAxMC41MDMzIDYyLjgzNTRDMTAuNjE3OSA2Mi44NzcxIDEwLjc0NDIgNjIuODk3OSAxMC44ODIyIDYyLjg5NzlDMTEuMDU5MyA2Mi44OTc5IDExLjIxNDIgNjIuODY0MSAxMS4zNDcgNjIuNzk2NEMxMS40Nzk5IDYyLjcyODcgMTEuNTkwNSA2Mi42MjMyIDExLjY3OTEgNjIuNDhDMTEuNzcwMiA2Mi4zMzQxIDExLjgzNzkgNjIuMTQ3OSAxMS44ODIyIDYxLjkyMTRDMTEuOTI2NSA2MS42OTIyIDExLjk0ODYgNjEuNDE4OCAxMS45NDg2IDYxLjEwMTFaTTEzLjY3NDYgNTkuMTIwNlY1OC44MTk4QzEzLjY3NDYgNTguNjAzNyAxMy43MjE0IDU4LjQwNzEgMTMuODE1MiA1OC4yM0MxMy45MDg5IDU4LjA1MjkgMTQuMDQzMSA1Ny45MTEgMTQuMjE3NSA1Ny44MDQyQzE0LjM5MiA1Ny42OTc0IDE0LjU5OSA1Ny42NDQgMTQuODM4NiA1Ny42NDRDMTUuMDgzNCA1Ny42NDQgMTUuMjkxOCA1Ny42OTc0IDE1LjQ2MzYgNTcuODA0MkMxNS42MzgxIDU3LjkxMSAxNS43NzIyIDU4LjA1MjkgMTUuODY2IDU4LjIzQzE1Ljk1OTcgNTguNDA3MSAxNi4wMDY2IDU4LjYwMzcgMTYuMDA2NiA1OC44MTk4VjU5LjEyMDZDMTYuMDA2NiA1OS4zMzE1IDE1Ljk1OTcgNTkuNTI1NiAxNS44NjYgNTkuNzAyNkMxNS43NzQ4IDU5Ljg3OTcgMTUuNjQyIDYwLjAyMTYgMTUuNDY3NSA2MC4xMjg0QzE1LjI5NTcgNjAuMjM1MiAxNS4wODg2IDYwLjI4ODYgMTQuODQ2NCA2MC4yODg2QzE0LjYwNDMgNjAuMjg4NiAxNC4zOTQ2IDYwLjIzNTIgMTQuMjE3NSA2MC4xMjg0QzE0LjA0MzEgNjAuMDIxNiAxMy45MDg5IDU5Ljg3OTcgMTMuODE1MiA1OS43MDI2QzEzLjcyMTQgNTkuNTI1NiAxMy42NzQ2IDU5LjMzMTUgMTMuNjc0NiA1OS4xMjA2Wk0xNC4yMTc1IDU4LjgxOThWNTkuMTIwNkMxNC4yMTc1IDU5LjI0MDQgMTQuMjM5NyA1OS4zNTM3IDE0LjI4MzkgNTkuNDYwNEMxNC4zMzA4IDU5LjU2NzIgMTQuNDAxMSA1OS42NTQ1IDE0LjQ5NDkgNTkuNzIyMkMxNC41ODg2IDU5Ljc4NzMgMTQuNzA1OCA1OS44MTk4IDE0Ljg0NjQgNTkuODE5OEMxNC45ODcxIDU5LjgxOTggMTUuMTAyOSA1OS43ODczIDE1LjE5NDEgNTkuNzIyMkMxNS4yODUyIDU5LjY1NDUgMTUuMzUyOSA1OS41NjcyIDE1LjM5NzIgNTkuNDYwNEMxNS40NDE1IDU5LjM1MzcgMTUuNDYzNiA1OS4yNDA0IDE1LjQ2MzYgNTkuMTIwNlY1OC44MTk4QzE1LjQ2MzYgNTguNjk3NCAxNS40NDAyIDU4LjU4MjggMTUuMzkzMyA1OC40NzYxQzE1LjM0OSA1OC4zNjY3IDE1LjI4IDU4LjI3OTUgMTUuMTg2MyA1OC4yMTQ0QzE1LjA5NTEgNTguMTQ2NiAxNC45NzkzIDU4LjExMjggMTQuODM4NiA1OC4xMTI4QzE0LjcwMDYgNTguMTEyOCAxNC41ODQ3IDU4LjE0NjYgMTQuNDkxIDU4LjIxNDRDMTQuMzk5OCA1OC4yNzk1IDE0LjMzMDggNTguMzY2NyAxNC4yODM5IDU4LjQ3NjFDMTQuMjM5NyA1OC41ODI4IDE0LjIxNzUgNTguNjk3NCAxNC4yMTc1IDU4LjgxOThaTTE2LjQ0NDEgNjIuMzIzN1Y2Mi4wMTlDMTYuNDQ0MSA2MS44MDU1IDE2LjQ5MSA2MS42MTAyIDE2LjU4NDcgNjEuNDMzMUMxNi42Nzg1IDYxLjI1NiAxNi44MTI2IDYxLjExNDEgMTYuOTg3MSA2MS4wMDczQzE3LjE2MTUgNjAuOTAwNiAxNy4zNjg2IDYwLjg0NzIgMTcuNjA4MiA2MC44NDcyQzE3Ljg1MjkgNjAuODQ3MiAxOC4wNjEzIDYwLjkwMDYgMTguMjMzMiA2MS4wMDczQzE4LjQwNzYgNjEuMTE0MSAxOC41NDE4IDYxLjI1NiAxOC42MzU1IDYxLjQzMzFDMTguNzI5MyA2MS42MTAyIDE4Ljc3NjEgNjEuODA1NSAxOC43NzYxIDYyLjAxOVY2Mi4zMjM3QzE4Ljc3NjEgNjIuNTM3MyAxOC43MjkzIDYyLjczMjYgMTguNjM1NSA2Mi45MDk3QzE4LjU0NDQgNjMuMDg2OCAxOC40MTE1IDYzLjIyODcgMTguMjM3MSA2My4zMzU0QzE4LjA2NTIgNjMuNDQyMiAxNy44NTgyIDYzLjQ5NTYgMTcuNjE2IDYzLjQ5NTZDMTcuMzczOCA2My40OTU2IDE3LjE2NTQgNjMuNDQyMiAxNi45OTEgNjMuMzM1NEMxNi44MTY1IDYzLjIyODcgMTYuNjgxMSA2My4wODY4IDE2LjU4NDcgNjIuOTA5N0MxNi40OTEgNjIuNzMyNiAxNi40NDQxIDYyLjUzNzMgMTYuNDQ0MSA2Mi4zMjM3Wk0xNi45ODcxIDYyLjAxOVY2Mi4zMjM3QzE2Ljk4NzEgNjIuNDQzNSAxNy4wMDkyIDYyLjU1ODEgMTcuMDUzNSA2Mi42Njc1QzE3LjEwMDMgNjIuNzc0MyAxNy4xNzA3IDYyLjg2MTUgMTcuMjY0NCA2Mi45MjkyQzE3LjM1ODIgNjIuOTk0MyAxNy40NzUzIDYzLjAyNjkgMTcuNjE2IDYzLjAyNjlDMTcuNzU2NiA2My4wMjY5IDE3Ljg3MjUgNjIuOTk0MyAxNy45NjM2IDYyLjkyOTJDMTguMDU3NCA2Mi44NjE1IDE4LjEyNjQgNjIuNzc0MyAxOC4xNzA3IDYyLjY2NzVDMTguMjE0OSA2Mi41NjA3IDE4LjIzNzEgNjIuNDQ2MSAxOC4yMzcxIDYyLjMyMzdWNjIuMDE5QzE4LjIzNzEgNjEuODk2NiAxOC4yMTM2IDYxLjc4MjEgMTguMTY2OCA2MS42NzUzQzE4LjEyMjUgNjEuNTY4NSAxOC4wNTM1IDYxLjQ4MjYgMTcuOTU5NyA2MS40MTc1QzE3Ljg2ODYgNjEuMzQ5OCAxNy43NTE0IDYxLjMxNTkgMTcuNjA4MiA2MS4zMTU5QzE3LjQ3MDEgNjEuMzE1OSAxNy4zNTQzIDYxLjM0OTggMTcuMjYwNSA2MS40MTc1QzE3LjE2OTQgNjEuNDgyNiAxNy4xMDAzIDYxLjU2ODUgMTcuMDUzNSA2MS42NzUzQzE3LjAwOTIgNjEuNzgyMSAxNi45ODcxIDYxLjg5NjYgMTYuOTg3MSA2Mi4wMTlaTTE3Ljc4NzggNTguNTM0N0wxNS4wMTA1IDYyLjk4TDE0LjYwNDMgNjIuNzIyMkwxNy4zODE2IDU4LjI3NjlMMTcuNzg3OCA1OC41MzQ3WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNOC4zMTY0MSA4OS43MDYzVjkwLjNINC4yMDcwM1Y4OS44NzQzTDYuNzUzOTEgODUuOTMyOUg3LjM0Mzc1TDYuNzEwOTQgODcuMDczNUw1LjAyNzM0IDg5LjcwNjNIOC4zMTY0MVpNNy41MjM0NCA4NS45MzI5VjkxLjYyMDRINi44MDA3OFY4NS45MzI5SDcuNTIzNDRaTTEyLjY3NTIgODguMzIzNVY4OS4xOTA3QzEyLjY3NTIgODkuNjU2OCAxMi42MzM1IDkwLjA1IDEyLjU1MDIgOTAuMzcwNEMxMi40NjY4IDkwLjY5MDcgMTIuMzQ3IDkwLjk0ODUgMTIuMTkwOCA5MS4xNDM4QzEyLjAzNDUgOTEuMzM5MSAxMS44NDU3IDkxLjQ4MSAxMS42MjQ0IDkxLjU2OTZDMTEuNDA1NiA5MS42NTU1IDExLjE1ODIgOTEuNjk4NSAxMC44ODIyIDkxLjY5ODVDMTAuNjYzNSA5MS42OTg1IDEwLjQ2MTYgOTEuNjcxMSAxMC4yNzY3IDkxLjYxNjVDMTAuMDkxOCA5MS41NjE4IDkuOTI1MTcgOTEuNDc0NSA5Ljc3NjczIDkxLjM1NDdDOS42MzA5IDkxLjIzMjMgOS41MDU5IDkxLjA3MzUgOS40MDE3MyA5MC44NzgyQzkuMjk3NTcgOTAuNjgyOSA5LjIxODE0IDkwLjQ0NTkgOS4xNjM0NSA5MC4xNjcyQzkuMTA4NzcgODkuODg4NiA5LjA4MTQyIDg5LjU2MzEgOS4wODE0MiA4OS4xOTA3Vjg4LjMyMzVDOS4wODE0MiA4Ny44NTczIDkuMTIzMDkgODcuNDY2NyA5LjIwNjQyIDg3LjE1MTZDOS4yOTIzNiA4Ni44MzY1IDkuNDEzNDUgODYuNTgzOSA5LjU2OTcgODYuMzkzOEM5LjcyNTk1IDg2LjIwMTEgOS45MTM0NSA4Ni4wNjMxIDEwLjEzMjIgODUuOTc5N0MxMC4zNTM2IDg1Ljg5NjQgMTAuNjAxIDg1Ljg1NDcgMTAuODc0NCA4NS44NTQ3QzExLjA5NTcgODUuODU0NyAxMS4yOTg5IDg1Ljg4MjEgMTEuNDgzOCA4NS45MzY4QzExLjY3MTMgODUuOTg4OSAxMS44Mzc5IDg2LjA3MzUgMTEuOTgzOCA4Ni4xOTA3QzEyLjEyOTYgODYuMzA1MyAxMi4yNTMzIDg2LjQ1ODkgMTIuMzU0OSA4Ni42NTE2QzEyLjQ1OSA4Ni44NDE3IDEyLjUzODUgODcuMDc0OCAxMi41OTMxIDg3LjM1MDhDMTIuNjQ3OCA4Ny42MjY5IDEyLjY3NTIgODcuOTUxMSAxMi42NzUyIDg4LjMyMzVaTTExLjk0ODYgODkuMzA3OVY4OC4yMDI0QzExLjk0ODYgODcuOTQ3MiAxMS45MzMgODcuNzIzMiAxMS45MDE3IDg3LjUzMDVDMTEuODczMSA4Ny4zMzUyIDExLjgzMDEgODcuMTY4NSAxMS43NzI4IDg3LjAzMDVDMTEuNzE1NSA4Ni44OTI1IDExLjY0MjYgODYuNzgwNSAxMS41NTQxIDg2LjY5NDZDMTEuNDY4MSA4Ni42MDg2IDExLjM2NzkgODYuNTQ2MSAxMS4yNTMzIDg2LjUwNzFDMTEuMTQxMyA4Ni40NjU0IDExLjAxNSA4Ni40NDQ2IDEwLjg3NDQgODYuNDQ0NkMxMC43MDI1IDg2LjQ0NDYgMTAuNTUwMiA4Ni40NzcxIDEwLjQxNzQgODYuNTQyMkMxMC4yODQ1IDg2LjYwNDcgMTAuMTcyNiA4Ni43MDUgMTAuMDgxNCA4Ni44NDNDOS45OTI4OCA4Ni45ODEgOS45MjUxNyA4Ny4xNjIgOS44NzgzIDg3LjM4NkM5LjgzMTQyIDg3LjYwOTkgOS44MDc5OCA4Ny44ODIxIDkuODA3OTggODguMjAyNFY4OS4zMDc5QzkuODA3OTggODkuNTYzMSA5LjgyMjMxIDg5Ljc4ODMgOS44NTA5NSA4OS45ODM2QzkuODgyMiA5MC4xNzkgOS45Mjc3OCA5MC4zNDgyIDkuOTg3NjcgOTAuNDkxNUMxMC4wNDc2IDkwLjYzMjEgMTAuMTIwNSA5MC43NDggMTAuMjA2NCA5MC44MzkxQzEwLjI5MjQgOTAuOTMwMyAxMC4zOTEzIDkwLjk5OCAxMC41MDMzIDkxLjA0MjJDMTAuNjE3OSA5MS4wODM5IDEwLjc0NDIgOTEuMTA0NyAxMC44ODIyIDkxLjEwNDdDMTEuMDU5MyA5MS4xMDQ3IDExLjIxNDIgOTEuMDcwOSAxMS4zNDcgOTEuMDAzMkMxMS40Nzk5IDkwLjkzNTUgMTEuNTkwNSA5MC44MyAxMS42NzkxIDkwLjY4NjhDMTEuNzcwMiA5MC41NDA5IDExLjgzNzkgOTAuMzU0NyAxMS44ODIyIDkwLjEyODJDMTEuOTI2NSA4OS44OTkgMTEuOTQ4NiA4OS42MjU2IDExLjk0ODYgODkuMzA3OVpNMTMuNjc0NiA4Ny4zMjc0Vjg3LjAyNjZDMTMuNjc0NiA4Ni44MTA1IDEzLjcyMTQgODYuNjEzOSAxMy44MTUyIDg2LjQzNjhDMTMuOTA4OSA4Ni4yNTk3IDE0LjA0MzEgODYuMTE3OCAxNC4yMTc1IDg2LjAxMUMxNC4zOTIgODUuOTA0MiAxNC41OTkgODUuODUwOCAxNC44Mzg2IDg1Ljg1MDhDMTUuMDgzNCA4NS44NTA4IDE1LjI5MTggODUuOTA0MiAxNS40NjM2IDg2LjAxMUMxNS42MzgxIDg2LjExNzggMTUuNzcyMiA4Ni4yNTk3IDE1Ljg2NiA4Ni40MzY4QzE1Ljk1OTcgODYuNjEzOSAxNi4wMDY2IDg2LjgxMDUgMTYuMDA2NiA4Ny4wMjY2Vjg3LjMyNzRDMTYuMDA2NiA4Ny41MzgzIDE1Ljk1OTcgODcuNzMyMyAxNS44NjYgODcuOTA5NEMxNS43NzQ4IDg4LjA4NjUgMTUuNjQyIDg4LjIyODQgMTUuNDY3NSA4OC4zMzUyQzE1LjI5NTcgODguNDQyIDE1LjA4ODYgODguNDk1NCAxNC44NDY0IDg4LjQ5NTRDMTQuNjA0MyA4OC40OTU0IDE0LjM5NDYgODguNDQyIDE0LjIxNzUgODguMzM1MkMxNC4wNDMxIDg4LjIyODQgMTMuOTA4OSA4OC4wODY1IDEzLjgxNTIgODcuOTA5NEMxMy43MjE0IDg3LjczMjMgMTMuNjc0NiA4Ny41MzgzIDEzLjY3NDYgODcuMzI3NFpNMTQuMjE3NSA4Ny4wMjY2Vjg3LjMyNzRDMTQuMjE3NSA4Ny40NDcyIDE0LjIzOTcgODcuNTYwNSAxNC4yODM5IDg3LjY2NzJDMTQuMzMwOCA4Ny43NzQgMTQuNDAxMSA4Ny44NjEyIDE0LjQ5NDkgODcuOTI5QzE0LjU4ODYgODcuOTk0MSAxNC43MDU4IDg4LjAyNjYgMTQuODQ2NCA4OC4wMjY2QzE0Ljk4NzEgODguMDI2NiAxNS4xMDI5IDg3Ljk5NDEgMTUuMTk0MSA4Ny45MjlDMTUuMjg1MiA4Ny44NjEyIDE1LjM1MjkgODcuNzc0IDE1LjM5NzIgODcuNjY3MkMxNS40NDE1IDg3LjU2MDUgMTUuNDYzNiA4Ny40NDcyIDE1LjQ2MzYgODcuMzI3NFY4Ny4wMjY2QzE1LjQ2MzYgODYuOTA0MiAxNS40NDAyIDg2Ljc4OTYgMTUuMzkzMyA4Ni42ODI5QzE1LjM0OSA4Ni41NzM1IDE1LjI4IDg2LjQ4NjIgMTUuMTg2MyA4Ni40MjExQzE1LjA5NTEgODYuMzUzNCAxNC45NzkzIDg2LjMxOTYgMTQuODM4NiA4Ni4zMTk2QzE0LjcwMDYgODYuMzE5NiAxNC41ODQ3IDg2LjM1MzQgMTQuNDkxIDg2LjQyMTFDMTQuMzk5OCA4Ni40ODYyIDE0LjMzMDggODYuNTczNSAxNC4yODM5IDg2LjY4MjlDMTQuMjM5NyA4Ni43ODk2IDE0LjIxNzUgODYuOTA0MiAxNC4yMTc1IDg3LjAyNjZaTTE2LjQ0NDEgOTAuNTMwNVY5MC4yMjU4QzE2LjQ0NDEgOTAuMDEyMyAxNi40OTEgODkuODE3IDE2LjU4NDcgODkuNjM5OUMxNi42Nzg1IDg5LjQ2MjggMTYuODEyNiA4OS4zMjA5IDE2Ljk4NzEgODkuMjE0MUMxNy4xNjE1IDg5LjEwNzMgMTcuMzY4NiA4OS4wNTQgMTcuNjA4MiA4OS4wNTRDMTcuODUyOSA4OS4wNTQgMTguMDYxMyA4OS4xMDczIDE4LjIzMzIgODkuMjE0MUMxOC40MDc2IDg5LjMyMDkgMTguNTQxOCA4OS40NjI4IDE4LjYzNTUgODkuNjM5OUMxOC43MjkzIDg5LjgxNyAxOC43NzYxIDkwLjAxMjMgMTguNzc2MSA5MC4yMjU4VjkwLjUzMDVDMTguNzc2MSA5MC43NDQxIDE4LjcyOTMgOTAuOTM5NCAxOC42MzU1IDkxLjExNjVDMTguNTQ0NCA5MS4yOTM1IDE4LjQxMTUgOTEuNDM1NSAxOC4yMzcxIDkxLjU0MjJDMTguMDY1MiA5MS42NDkgMTcuODU4MiA5MS43MDI0IDE3LjYxNiA5MS43MDI0QzE3LjM3MzggOTEuNzAyNCAxNy4xNjU0IDkxLjY0OSAxNi45OTEgOTEuNTQyMkMxNi44MTY1IDkxLjQzNTUgMTYuNjgxMSA5MS4yOTM1IDE2LjU4NDcgOTEuMTE2NUMxNi40OTEgOTAuOTM5NCAxNi40NDQxIDkwLjc0NDEgMTYuNDQ0MSA5MC41MzA1Wk0xNi45ODcxIDkwLjIyNThWOTAuNTMwNUMxNi45ODcxIDkwLjY1MDMgMTcuMDA5MiA5MC43NjQ5IDE3LjA1MzUgOTAuODc0M0MxNy4xMDAzIDkwLjk4MSAxNy4xNzA3IDkxLjA2ODMgMTcuMjY0NCA5MS4xMzZDMTcuMzU4MiA5MS4yMDExIDE3LjQ3NTMgOTEuMjMzNiAxNy42MTYgOTEuMjMzNkMxNy43NTY2IDkxLjIzMzYgMTcuODcyNSA5MS4yMDExIDE3Ljk2MzYgOTEuMTM2QzE4LjA1NzQgOTEuMDY4MyAxOC4xMjY0IDkwLjk4MSAxOC4xNzA3IDkwLjg3NDNDMTguMjE0OSA5MC43Njc1IDE4LjIzNzEgOTAuNjUyOSAxOC4yMzcxIDkwLjUzMDVWOTAuMjI1OEMxOC4yMzcxIDkwLjEwMzQgMTguMjEzNiA4OS45ODg5IDE4LjE2NjggODkuODgyMUMxOC4xMjI1IDg5Ljc3NTMgMTguMDUzNSA4OS42ODk0IDE3Ljk1OTcgODkuNjI0M0MxNy44Njg2IDg5LjU1NjYgMTcuNzUxNCA4OS41MjI3IDE3LjYwODIgODkuNTIyN0MxNy40NzAxIDg5LjUyMjcgMTcuMzU0MyA4OS41NTY2IDE3LjI2MDUgODkuNjI0M0MxNy4xNjk0IDg5LjY4OTQgMTcuMTAwMyA4OS43NzUzIDE3LjA1MzUgODkuODgyMUMxNy4wMDkyIDg5Ljk4ODkgMTYuOTg3MSA5MC4xMDM0IDE2Ljk4NzEgOTAuMjI1OFpNMTcuNzg3OCA4Ni43NDE1TDE1LjAxMDUgOTEuMTg2OEwxNC42MDQzIDkwLjkyOUwxNy4zODE2IDg2LjQ4MzZMMTcuNzg3OCA4Ni43NDE1WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNOC4xOTkyMiAxMTkuMjMzVjExOS44MjdINC40NzY1NlYxMTkuMzA4TDYuMzM5ODQgMTE3LjIzM0M2LjU2OTAxIDExNi45NzggNi43NDYwOSAxMTYuNzYyIDYuODcxMDkgMTE2LjU4NUM2Ljk5ODcgMTE2LjQwNSA3LjA4NzI0IDExNi4yNDUgNy4xMzY3MiAxMTYuMTA0QzcuMTg4OCAxMTUuOTYxIDcuMjE0ODQgMTE1LjgxNSA3LjIxNDg0IDExNS42NjdDNy4yMTQ4NCAxMTUuNDc5IDcuMTc1NzggMTE1LjMxIDcuMDk3NjYgMTE1LjE1OUM3LjAyMjE0IDExNS4wMDYgNi45MTAxNiAxMTQuODgzIDYuNzYxNzIgMTE0Ljc5MkM2LjYxMzI4IDExNC43MDEgNi40MzM1OSAxMTQuNjU1IDYuMjIyNjYgMTE0LjY1NUM1Ljk3MDA1IDExNC42NTUgNS43NTkxMSAxMTQuNzA1IDUuNTg5ODQgMTE0LjgwNEM1LjQyMzE4IDExNC45IDUuMjk4MTggMTE1LjAzNSA1LjIxNDg0IDExNS4yMUM1LjEzMTUxIDExNS4zODQgNS4wODk4NCAxMTUuNTg1IDUuMDg5ODQgMTE1LjgxMkg0LjM2NzE5QzQuMzY3MTkgMTE1LjQ5MSA0LjQzNzUgMTE1LjE5OCA0LjU3ODEyIDExNC45MzNDNC43MTg3NSAxMTQuNjY3IDQuOTI3MDggMTE0LjQ1NiA1LjIwMzEyIDExNC4zQzUuNDc5MTcgMTE0LjE0MSA1LjgxOTAxIDExNC4wNjIgNi4yMjI2NiAxMTQuMDYyQzYuNTgyMDMgMTE0LjA2MiA2Ljg4OTMyIDExNC4xMjUgNy4xNDQ1MyAxMTQuMjUzQzcuMzk5NzQgMTE0LjM3OCA3LjU5NTA1IDExNC41NTUgNy43MzA0NyAxMTQuNzg0QzcuODY4NDkgMTE1LjAxMSA3LjkzNzUgMTE1LjI3NiA3LjkzNzUgMTE1LjU4MUM3LjkzNzUgMTE1Ljc0OCA3LjkwODg1IDExNS45MTcgNy44NTE1NiAxMTYuMDg5QzcuNzk2ODggMTE2LjI1OCA3LjcyMDA1IDExNi40MjcgNy42MjEwOSAxMTYuNTk3QzcuNTI0NzQgMTE2Ljc2NiA3LjQxMTQ2IDExNi45MzMgNy4yODEyNSAxMTcuMDk3QzcuMTUzNjUgMTE3LjI2MSA3LjAxNjkzIDExNy40MjIgNi44NzEwOSAxMTcuNTgxTDUuMzQ3NjYgMTE5LjIzM0g4LjE5OTIyWk0xMi42NzUyIDExNi41M1YxMTcuMzk3QzEyLjY3NTIgMTE3Ljg2NCAxMi42MzM1IDExOC4yNTcgMTIuNTUwMiAxMTguNTc3QzEyLjQ2NjggMTE4Ljg5NyAxMi4zNDcgMTE5LjE1NSAxMi4xOTA4IDExOS4zNTFDMTIuMDM0NSAxMTkuNTQ2IDExLjg0NTcgMTE5LjY4OCAxMS42MjQ0IDExOS43NzZDMTEuNDA1NiAxMTkuODYyIDExLjE1ODIgMTE5LjkwNSAxMC44ODIyIDExOS45MDVDMTAuNjYzNSAxMTkuOTA1IDEwLjQ2MTYgMTE5Ljg3OCAxMC4yNzY3IDExOS44MjNDMTAuMDkxOCAxMTkuNzY5IDkuOTI1MTcgMTE5LjY4MSA5Ljc3NjczIDExOS41NjJDOS42MzA5IDExOS40MzkgOS41MDU5IDExOS4yOCA5LjQwMTczIDExOS4wODVDOS4yOTc1NyAxMTguODkgOS4yMTgxNCAxMTguNjUzIDkuMTYzNDUgMTE4LjM3NEM5LjEwODc3IDExOC4wOTUgOS4wODE0MiAxMTcuNzcgOS4wODE0MiAxMTcuMzk3VjExNi41M0M5LjA4MTQyIDExNi4wNjQgOS4xMjMwOSAxMTUuNjc0IDkuMjA2NDIgMTE1LjM1OEM5LjI5MjM2IDExNS4wNDMgOS40MTM0NSAxMTQuNzkxIDkuNTY5NyAxMTQuNjAxQzkuNzI1OTUgMTE0LjQwOCA5LjkxMzQ1IDExNC4yNyAxMC4xMzIyIDExNC4xODdDMTAuMzUzNiAxMTQuMTAzIDEwLjYwMSAxMTQuMDYyIDEwLjg3NDQgMTE0LjA2MkMxMS4wOTU3IDExNC4wNjIgMTEuMjk4OSAxMTQuMDg5IDExLjQ4MzggMTE0LjE0NEMxMS42NzEzIDExNC4xOTYgMTEuODM3OSAxMTQuMjggMTEuOTgzOCAxMTQuMzk3QzEyLjEyOTYgMTE0LjUxMiAxMi4yNTMzIDExNC42NjYgMTIuMzU0OSAxMTQuODU4QzEyLjQ1OSAxMTUuMDQ5IDEyLjUzODUgMTE1LjI4MiAxMi41OTMxIDExNS41NThDMTIuNjQ3OCAxMTUuODM0IDEyLjY3NTIgMTE2LjE1OCAxMi42NzUyIDExNi41M1pNMTEuOTQ4NiAxMTcuNTE1VjExNi40MDlDMTEuOTQ4NiAxMTYuMTU0IDExLjkzMyAxMTUuOTMgMTEuOTAxNyAxMTUuNzM3QzExLjg3MzEgMTE1LjU0MiAxMS44MzAxIDExNS4zNzUgMTEuNzcyOCAxMTUuMjM3QzExLjcxNTUgMTE1LjA5OSAxMS42NDI2IDExNC45ODcgMTEuNTU0MSAxMTQuOTAxQzExLjQ2ODEgMTE0LjgxNSAxMS4zNjc5IDExNC43NTMgMTEuMjUzMyAxMTQuNzE0QzExLjE0MTMgMTE0LjY3MiAxMS4wMTUgMTE0LjY1MSAxMC44NzQ0IDExNC42NTFDMTAuNzAyNSAxMTQuNjUxIDEwLjU1MDIgMTE0LjY4NCAxMC40MTc0IDExNC43NDlDMTAuMjg0NSAxMTQuODEyIDEwLjE3MjYgMTE0LjkxMiAxMC4wODE0IDExNS4wNUM5Ljk5Mjg4IDExNS4xODggOS45MjUxNyAxMTUuMzY5IDkuODc4MyAxMTUuNTkzQzkuODMxNDIgMTE1LjgxNyA5LjgwNzk4IDExNi4wODkgOS44MDc5OCAxMTYuNDA5VjExNy41MTVDOS44MDc5OCAxMTcuNzcgOS44MjIzMSAxMTcuOTk1IDkuODUwOTUgMTE4LjE5QzkuODgyMiAxMTguMzg2IDkuOTI3NzggMTE4LjU1NSA5Ljk4NzY3IDExOC42OThDMTAuMDQ3NiAxMTguODM5IDEwLjEyMDUgMTE4Ljk1NSAxMC4yMDY0IDExOS4wNDZDMTAuMjkyNCAxMTkuMTM3IDEwLjM5MTMgMTE5LjIwNSAxMC41MDMzIDExOS4yNDlDMTAuNjE3OSAxMTkuMjkxIDEwLjc0NDIgMTE5LjMxMiAxMC44ODIyIDExOS4zMTJDMTEuMDU5MyAxMTkuMzEyIDExLjIxNDIgMTE5LjI3OCAxMS4zNDcgMTE5LjIxQzExLjQ3OTkgMTE5LjE0MiAxMS41OTA1IDExOS4wMzcgMTEuNjc5MSAxMTguODk0QzExLjc3MDIgMTE4Ljc0OCAxMS44Mzc5IDExOC41NjIgMTEuODgyMiAxMTguMzM1QzExLjkyNjUgMTE4LjEwNiAxMS45NDg2IDExNy44MzIgMTEuOTQ4NiAxMTcuNTE1Wk0xMy42NzQ2IDExNS41MzRWMTE1LjIzM0MxMy42NzQ2IDExNS4wMTcgMTMuNzIxNCAxMTQuODIxIDEzLjgxNTIgMTE0LjY0NEMxMy45MDg5IDExNC40NjYgMTQuMDQzMSAxMTQuMzI1IDE0LjIxNzUgMTE0LjIxOEMxNC4zOTIgMTE0LjExMSAxNC41OTkgMTE0LjA1OCAxNC44Mzg2IDExNC4wNThDMTUuMDgzNCAxMTQuMDU4IDE1LjI5MTggMTE0LjExMSAxNS40NjM2IDExNC4yMThDMTUuNjM4MSAxMTQuMzI1IDE1Ljc3MjIgMTE0LjQ2NiAxNS44NjYgMTE0LjY0NEMxNS45NTk3IDExNC44MjEgMTYuMDA2NiAxMTUuMDE3IDE2LjAwNjYgMTE1LjIzM1YxMTUuNTM0QzE2LjAwNjYgMTE1Ljc0NSAxNS45NTk3IDExNS45MzkgMTUuODY2IDExNi4xMTZDMTUuNzc0OCAxMTYuMjkzIDE1LjY0MiAxMTYuNDM1IDE1LjQ2NzUgMTE2LjU0MkMxNS4yOTU3IDExNi42NDkgMTUuMDg4NiAxMTYuNzAyIDE0Ljg0NjQgMTE2LjcwMkMxNC42MDQzIDExNi43MDIgMTQuMzk0NiAxMTYuNjQ5IDE0LjIxNzUgMTE2LjU0MkMxNC4wNDMxIDExNi40MzUgMTMuOTA4OSAxMTYuMjkzIDEzLjgxNTIgMTE2LjExNkMxMy43MjE0IDExNS45MzkgMTMuNjc0NiAxMTUuNzQ1IDEzLjY3NDYgMTE1LjUzNFpNMTQuMjE3NSAxMTUuMjMzVjExNS41MzRDMTQuMjE3NSAxMTUuNjU0IDE0LjIzOTcgMTE1Ljc2NyAxNC4yODM5IDExNS44NzRDMTQuMzMwOCAxMTUuOTgxIDE0LjQwMTEgMTE2LjA2OCAxNC40OTQ5IDExNi4xMzZDMTQuNTg4NiAxMTYuMjAxIDE0LjcwNTggMTE2LjIzMyAxNC44NDY0IDExNi4yMzNDMTQuOTg3MSAxMTYuMjMzIDE1LjEwMjkgMTE2LjIwMSAxNS4xOTQxIDExNi4xMzZDMTUuMjg1MiAxMTYuMDY4IDE1LjM1MjkgMTE1Ljk4MSAxNS4zOTcyIDExNS44NzRDMTUuNDQxNSAxMTUuNzY3IDE1LjQ2MzYgMTE1LjY1NCAxNS40NjM2IDExNS41MzRWMTE1LjIzM0MxNS40NjM2IDExNS4xMTEgMTUuNDQwMiAxMTQuOTk2IDE1LjM5MzMgMTE0Ljg5QzE1LjM0OSAxMTQuNzggMTUuMjggMTE0LjY5MyAxNS4xODYzIDExNC42MjhDMTUuMDk1MSAxMTQuNTYgMTQuOTc5MyAxMTQuNTI2IDE0LjgzODYgMTE0LjUyNkMxNC43MDA2IDExNC41MjYgMTQuNTg0NyAxMTQuNTYgMTQuNDkxIDExNC42MjhDMTQuMzk5OCAxMTQuNjkzIDE0LjMzMDggMTE0Ljc4IDE0LjI4MzkgMTE0Ljg5QzE0LjIzOTcgMTE0Ljk5NiAxNC4yMTc1IDExNS4xMTEgMTQuMjE3NSAxMTUuMjMzWk0xNi40NDQxIDExOC43MzdWMTE4LjQzM0MxNi40NDQxIDExOC4yMTkgMTYuNDkxIDExOC4wMjQgMTYuNTg0NyAxMTcuODQ3QzE2LjY3ODUgMTE3LjY3IDE2LjgxMjYgMTE3LjUyOCAxNi45ODcxIDExNy40MjFDMTcuMTYxNSAxMTcuMzE0IDE3LjM2ODYgMTE3LjI2MSAxNy42MDgyIDExNy4yNjFDMTcuODUyOSAxMTcuMjYxIDE4LjA2MTMgMTE3LjMxNCAxOC4yMzMyIDExNy40MjFDMTguNDA3NiAxMTcuNTI4IDE4LjU0MTggMTE3LjY3IDE4LjYzNTUgMTE3Ljg0N0MxOC43MjkzIDExOC4wMjQgMTguNzc2MSAxMTguMjE5IDE4Ljc3NjEgMTE4LjQzM1YxMTguNzM3QzE4Ljc3NjEgMTE4Ljk1MSAxOC43MjkzIDExOS4xNDYgMTguNjM1NSAxMTkuMzIzQzE4LjU0NDQgMTE5LjUgMTguNDExNSAxMTkuNjQyIDE4LjIzNzEgMTE5Ljc0OUMxOC4wNjUyIDExOS44NTYgMTcuODU4MiAxMTkuOTA5IDE3LjYxNiAxMTkuOTA5QzE3LjM3MzggMTE5LjkwOSAxNy4xNjU0IDExOS44NTYgMTYuOTkxIDExOS43NDlDMTYuODE2NSAxMTkuNjQyIDE2LjY4MTEgMTE5LjUgMTYuNTg0NyAxMTkuMzIzQzE2LjQ5MSAxMTkuMTQ2IDE2LjQ0NDEgMTE4Ljk1MSAxNi40NDQxIDExOC43MzdaTTE2Ljk4NzEgMTE4LjQzM1YxMTguNzM3QzE2Ljk4NzEgMTE4Ljg1NyAxNy4wMDkyIDExOC45NzIgMTcuMDUzNSAxMTkuMDgxQzE3LjEwMDMgMTE5LjE4OCAxNy4xNzA3IDExOS4yNzUgMTcuMjY0NCAxMTkuMzQzQzE3LjM1ODIgMTE5LjQwOCAxNy40NzUzIDExOS40NCAxNy42MTYgMTE5LjQ0QzE3Ljc1NjYgMTE5LjQ0IDE3Ljg3MjUgMTE5LjQwOCAxNy45NjM2IDExOS4zNDNDMTguMDU3NCAxMTkuMjc1IDE4LjEyNjQgMTE5LjE4OCAxOC4xNzA3IDExOS4wODFDMTguMjE0OSAxMTguOTc0IDE4LjIzNzEgMTE4Ljg2IDE4LjIzNzEgMTE4LjczN1YxMTguNDMzQzE4LjIzNzEgMTE4LjMxIDE4LjIxMzYgMTE4LjE5NiAxOC4xNjY4IDExOC4wODlDMTguMTIyNSAxMTcuOTgyIDE4LjA1MzUgMTE3Ljg5NiAxNy45NTk3IDExNy44MzFDMTcuODY4NiAxMTcuNzYzIDE3Ljc1MTQgMTE3LjcyOSAxNy42MDgyIDExNy43MjlDMTcuNDcwMSAxMTcuNzI5IDE3LjM1NDMgMTE3Ljc2MyAxNy4yNjA1IDExNy44MzFDMTcuMTY5NCAxMTcuODk2IDE3LjEwMDMgMTE3Ljk4MiAxNy4wNTM1IDExOC4wODlDMTcuMDA5MiAxMTguMTk2IDE2Ljk4NzEgMTE4LjMxIDE2Ljk4NzEgMTE4LjQzM1pNMTcuNzg3OCAxMTQuOTQ4TDE1LjAxMDUgMTE5LjM5NEwxNC42MDQzIDExOS4xMzZMMTcuMzgxNiAxMTQuNjlMMTcuNzg3OCAxMTQuOTQ4WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNMTMuMDQzIDE0NC43MzdWMTQ1LjYwNEMxMy4wNDMgMTQ2LjA3IDEzLjAwMTMgMTQ2LjQ2NCAxMi45MTggMTQ2Ljc4NEMxMi44MzQ2IDE0Ny4xMDQgMTIuNzE0OCAxNDcuMzYyIDEyLjU1ODYgMTQ3LjU1N0MxMi40MDIzIDE0Ny43NTMgMTIuMjEzNSAxNDcuODk1IDExLjk5MjIgMTQ3Ljk4M0MxMS43NzM0IDE0OC4wNjkgMTEuNTI2IDE0OC4xMTIgMTEuMjUgMTQ4LjExMkMxMS4wMzEyIDE0OC4xMTIgMTAuODI5NCAxNDguMDg1IDEwLjY0NDUgMTQ4LjAzQzEwLjQ1OTYgMTQ3Ljk3NSAxMC4yOTMgMTQ3Ljg4OCAxMC4xNDQ1IDE0Ny43NjhDOS45OTg3IDE0Ny42NDYgOS44NzM3IDE0Ny40ODcgOS43Njk1MyAxNDcuMjkyQzkuNjY1MzYgMTQ3LjA5NiA5LjU4NTk0IDE0Ni44NTkgOS41MzEyNSAxNDYuNTgxQzkuNDc2NTYgMTQ2LjMwMiA5LjQ0OTIyIDE0NS45NzcgOS40NDkyMiAxNDUuNjA0VjE0NC43MzdDOS40NDkyMiAxNDQuMjcxIDkuNDkwODkgMTQzLjg4IDkuNTc0MjIgMTQzLjU2NUM5LjY2MDE2IDE0My4yNSA5Ljc4MTI1IDE0Mi45OTcgOS45Mzc1IDE0Mi44MDdDMTAuMDkzOCAxNDIuNjE1IDEwLjI4MTIgMTQyLjQ3NyAxMC41IDE0Mi4zOTNDMTAuNzIxNCAxNDIuMzEgMTAuOTY4OCAxNDIuMjY4IDExLjI0MjIgMTQyLjI2OEMxMS40NjM1IDE0Mi4yNjggMTEuNjY2NyAxNDIuMjk2IDExLjg1MTYgMTQyLjM1QzEyLjAzOTEgMTQyLjQwMiAxMi4yMDU3IDE0Mi40ODcgMTIuMzUxNiAxNDIuNjA0QzEyLjQ5NzQgMTQyLjcxOSAxMi42MjExIDE0Mi44NzIgMTIuNzIyNyAxNDMuMDY1QzEyLjgyNjggMTQzLjI1NSAxMi45MDYyIDE0My40ODggMTIuOTYwOSAxNDMuNzY0QzEzLjAxNTYgMTQ0LjA0IDEzLjA0MyAxNDQuMzY1IDEzLjA0MyAxNDQuNzM3Wk0xMi4zMTY0IDE0NS43MjFWMTQ0LjYxNkMxMi4zMTY0IDE0NC4zNjEgMTIuMzAwOCAxNDQuMTM3IDEyLjI2OTUgMTQzLjk0NEMxMi4yNDA5IDE0My43NDkgMTIuMTk3OSAxNDMuNTgyIDEyLjE0MDYgMTQzLjQ0NEMxMi4wODMzIDE0My4zMDYgMTIuMDEwNCAxNDMuMTk0IDExLjkyMTkgMTQzLjEwOEMxMS44MzU5IDE0My4wMjIgMTEuNzM1NyAxNDIuOTYgMTEuNjIxMSAxNDIuOTIxQzExLjUwOTEgMTQyLjg3OSAxMS4zODI4IDE0Mi44NTggMTEuMjQyMiAxNDIuODU4QzExLjA3MDMgMTQyLjg1OCAxMC45MTggMTQyLjg5MSAxMC43ODUyIDE0Mi45NTZDMTAuNjUyMyAxNDMuMDE4IDEwLjU0MDQgMTQzLjExOSAxMC40NDkyIDE0My4yNTdDMTAuMzYwNyAxNDMuMzk1IDEwLjI5MyAxNDMuNTc2IDEwLjI0NjEgMTQzLjhDMTAuMTk5MiAxNDQuMDI0IDEwLjE3NTggMTQ0LjI5NiAxMC4xNzU4IDE0NC42MTZWMTQ1LjcyMUMxMC4xNzU4IDE0NS45NzcgMTAuMTkwMSAxNDYuMjAyIDEwLjIxODggMTQ2LjM5N0MxMC4yNSAxNDYuNTkzIDEwLjI5NTYgMTQ2Ljc2MiAxMC4zNTU1IDE0Ni45MDVDMTAuNDE1NCAxNDcuMDQ2IDEwLjQ4ODMgMTQ3LjE2MiAxMC41NzQyIDE0Ny4yNTNDMTAuNjYwMiAxNDcuMzQ0IDEwLjc1OTEgMTQ3LjQxMiAxMC44NzExIDE0Ny40NTZDMTAuOTg1NyAxNDcuNDk3IDExLjExMiAxNDcuNTE4IDExLjI1IDE0Ny41MThDMTEuNDI3MSAxNDcuNTE4IDExLjU4MiAxNDcuNDg0IDExLjcxNDggMTQ3LjQxN0MxMS44NDc3IDE0Ny4zNDkgMTEuOTU4MyAxNDcuMjQ0IDEyLjA0NjkgMTQ3LjFDMTIuMTM4IDE0Ni45NTUgMTIuMjA1NyAxNDYuNzY4IDEyLjI1IDE0Ni41NDJDMTIuMjk0MyAxNDYuMzEzIDEyLjMxNjQgMTQ2LjAzOSAxMi4zMTY0IDE0NS43MjFaTTE0LjA0MjQgMTQzLjc0MVYxNDMuNDRDMTQuMDQyNCAxNDMuMjI0IDE0LjA4OTIgMTQzLjAyNyAxNC4xODMgMTQyLjg1QzE0LjI3NjcgMTQyLjY3MyAxNC40MTA4IDE0Mi41MzEgMTQuNTg1MyAxNDIuNDI1QzE0Ljc1OTggMTQyLjMxOCAxNC45NjY4IDE0Mi4yNjQgMTUuMjA2NCAxNDIuMjY0QzE1LjQ1MTIgMTQyLjI2NCAxNS42NTk1IDE0Mi4zMTggMTUuODMxNCAxNDIuNDI1QzE2LjAwNTkgMTQyLjUzMSAxNi4xNCAxNDIuNjczIDE2LjIzMzggMTQyLjg1QzE2LjMyNzUgMTQzLjAyNyAxNi4zNzQ0IDE0My4yMjQgMTYuMzc0NCAxNDMuNDRWMTQzLjc0MUMxNi4zNzQ0IDE0My45NTIgMTYuMzI3NSAxNDQuMTQ2IDE2LjIzMzggMTQ0LjMyM0MxNi4xNDI2IDE0NC41IDE2LjAwOTggMTQ0LjY0MiAxNS44MzUzIDE0NC43NDlDMTUuNjYzNSAxNDQuODU2IDE1LjQ1NjQgMTQ0LjkwOSAxNS4yMTQyIDE0NC45MDlDMTQuOTcyIDE0NC45MDkgMTQuNzYyNCAxNDQuODU2IDE0LjU4NTMgMTQ0Ljc0OUMxNC40MTA4IDE0NC42NDIgMTQuMjc2NyAxNDQuNSAxNC4xODMgMTQ0LjMyM0MxNC4wODkyIDE0NC4xNDYgMTQuMDQyNCAxNDMuOTUyIDE0LjA0MjQgMTQzLjc0MVpNMTQuNTg1MyAxNDMuNDRWMTQzLjc0MUMxNC41ODUzIDE0My44NjEgMTQuNjA3NSAxNDMuOTc0IDE0LjY1MTcgMTQ0LjA4MUMxNC42OTg2IDE0NC4xODggMTQuNzY4OSAxNDQuMjc1IDE0Ljg2MjcgMTQ0LjM0M0MxNC45NTY0IDE0NC40MDggMTUuMDczNiAxNDQuNDQgMTUuMjE0MiAxNDQuNDRDMTUuMzU0OSAxNDQuNDQgMTUuNDcwNyAxNDQuNDA4IDE1LjU2MTkgMTQ0LjM0M0MxNS42NTMgMTQ0LjI3NSAxNS43MjA3IDE0NC4xODggMTUuNzY1IDE0NC4wODFDMTUuODA5MyAxNDMuOTc0IDE1LjgzMTQgMTQzLjg2MSAxNS44MzE0IDE0My43NDFWMTQzLjQ0QzE1LjgzMTQgMTQzLjMxOCAxNS44MDggMTQzLjIwMyAxNS43NjExIDE0My4wOTZDMTUuNzE2OCAxNDIuOTg3IDE1LjY0NzggMTQyLjkgMTUuNTU0MSAxNDIuODM1QzE1LjQ2MjkgMTQyLjc2NyAxNS4zNDcgMTQyLjczMyAxNS4yMDY0IDE0Mi43MzNDMTUuMDY4NCAxNDIuNzMzIDE0Ljk1MjUgMTQyLjc2NyAxNC44NTg4IDE0Mi44MzVDMTQuNzY3NiAxNDIuOSAxNC42OTg2IDE0Mi45ODcgMTQuNjUxNyAxNDMuMDk2QzE0LjYwNzUgMTQzLjIwMyAxNC41ODUzIDE0My4zMTggMTQuNTg1MyAxNDMuNDRaTTE2LjgxMTkgMTQ2Ljk0NFYxNDYuNjM5QzE2LjgxMTkgMTQ2LjQyNiAxNi44NTg4IDE0Ni4yMzEgMTYuOTUyNSAxNDYuMDUzQzE3LjA0NjMgMTQ1Ljg3NiAxNy4xODA0IDE0NS43MzQgMTcuMzU0OSAxNDUuNjI4QzE3LjUyOTMgMTQ1LjUyMSAxNy43MzY0IDE0NS40NjggMTcuOTc2IDE0NS40NjhDMTguMjIwNyAxNDUuNDY4IDE4LjQyOTEgMTQ1LjUyMSAxOC42MDEgMTQ1LjYyOEMxOC43NzU0IDE0NS43MzQgMTguOTA5NSAxNDUuODc2IDE5LjAwMzMgMTQ2LjA1M0MxOS4wOTcgMTQ2LjIzMSAxOS4xNDM5IDE0Ni40MjYgMTkuMTQzOSAxNDYuNjM5VjE0Ni45NDRDMTkuMTQzOSAxNDcuMTU4IDE5LjA5NyAxNDcuMzUzIDE5LjAwMzMgMTQ3LjUzQzE4LjkxMjIgMTQ3LjcwNyAxOC43NzkzIDE0Ny44NDkgMTguNjA0OSAxNDcuOTU2QzE4LjQzMyAxNDguMDYzIDE4LjIyNiAxNDguMTE2IDE3Ljk4MzggMTQ4LjExNkMxNy43NDE2IDE0OC4xMTYgMTcuNTMzMiAxNDguMDYzIDE3LjM1ODggMTQ3Ljk1NkMxNy4xODQzIDE0Ny44NDkgMTcuMDQ4OSAxNDcuNzA3IDE2Ljk1MjUgMTQ3LjUzQzE2Ljg1ODggMTQ3LjM1MyAxNi44MTE5IDE0Ny4xNTggMTYuODExOSAxNDYuOTQ0Wk0xNy4zNTQ5IDE0Ni42MzlWMTQ2Ljk0NEMxNy4zNTQ5IDE0Ny4wNjQgMTcuMzc3IDE0Ny4xNzggMTcuNDIxMyAxNDcuMjg4QzE3LjQ2ODEgMTQ3LjM5NSAxNy41Mzg1IDE0Ny40ODIgMTcuNjMyMiAxNDcuNTVDMTcuNzI2IDE0Ny42MTUgMTcuODQzMSAxNDcuNjQ3IDE3Ljk4MzggMTQ3LjY0N0MxOC4xMjQ0IDE0Ny42NDcgMTguMjQwMyAxNDcuNjE1IDE4LjMzMTQgMTQ3LjU1QzE4LjQyNTIgMTQ3LjQ4MiAxOC40OTQyIDE0Ny4zOTUgMTguNTM4NSAxNDcuMjg4QzE4LjU4MjcgMTQ3LjE4MSAxOC42MDQ5IDE0Ny4wNjYgMTguNjA0OSAxNDYuOTQ0VjE0Ni42MzlDMTguNjA0OSAxNDYuNTE3IDE4LjU4MTQgMTQ2LjQwMiAxOC41MzQ1IDE0Ni4yOTZDMTguNDkwMyAxNDYuMTg5IDE4LjQyMTMgMTQ2LjEwMyAxOC4zMjc1IDE0Ni4wMzhDMTguMjM2NCAxNDUuOTcgMTguMTE5MiAxNDUuOTM2IDE3Ljk3NiAxNDUuOTM2QzE3LjgzNzkgMTQ1LjkzNiAxNy43MjIgMTQ1Ljk3IDE3LjYyODMgMTQ2LjAzOEMxNy41MzcyIDE0Ni4xMDMgMTcuNDY4MSAxNDYuMTg5IDE3LjQyMTMgMTQ2LjI5NkMxNy4zNzcgMTQ2LjQwMiAxNy4zNTQ5IDE0Ni41MTcgMTcuMzU0OSAxNDYuNjM5Wk0xOC4xNTU2IDE0My4xNTVMMTUuMzc4MyAxNDcuNkwxNC45NzIgMTQ3LjM0M0wxNy43NDk0IDE0Mi44OTdMMTguMTU1NiAxNDMuMTU1WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNMjUgNC4xNjExM0wyMDAgNC4xNjExNiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiLz4KPHBhdGggZD0iTTI1IDMzLjE2MTFMMjAwIDMzLjE2MTIiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1vcGFjaXR5PSIwLjEyIi8+CjxwYXRoIGQ9Ik0yNSA2MS4xNjExTDIwMCA2MS4xNjEyIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC4xMiIvPgo8cGF0aCBkPSJNMjUgODkuMTYxMUwyMDAgODkuMTYxMiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiLz4KPHBhdGggZD0iTTI1IDExOC4xNjFMMjAwIDExOC4xNjEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1vcGFjaXR5PSIwLjEyIi8+CjxwYXRoIGQ9Ik0zNiA2MkMzNiA2MC44OTU0IDM2Ljg5NTQgNjAgMzggNjBINTJDNTMuMTA0NiA2MCA1NCA2MC44OTU0IDU0IDYyVjE0NkgzNlY2MloiIGZpbGw9IiNGRkMxMDciLz4KPHBhdGggZD0iTTU4IDkyQzU4IDkwLjg5NTQgNTguODk1NCA5MCA2MCA5MEg3NEM3NS4xMDQ2IDkwIDc2IDkwLjg5NTQgNzYgOTJWMTQ2SDU4VjkyWiIgZmlsbD0iIzRDQUY1MCIvPgo8cGF0aCBkPSJNODAgNzlDODAgNzcuODk1NCA4MC44OTU0IDc3IDgyIDc3SDk2Qzk3LjEwNDYgNzcgOTggNzcuODk1NCA5OCA3OVYxNDZIODBWNzlaIiBmaWxsPSIjMjE5NkYzIi8+CjxwYXRoIGQ9Ik0xMjUgNzhDMTI1IDc2Ljg5NTQgMTI1Ljg5NSA3NiAxMjcgNzZIMTQxQzE0Mi4xMDUgNzYgMTQzIDc2Ljg5NTQgMTQzIDc4VjE0NkgxMjVWNzhaIiBmaWxsPSIjRkZDMTA3Ii8+CjxwYXRoIGQ9Ik0xNDcgNTFDMTQ3IDQ5Ljg5NTQgMTQ3Ljg5NSA0OSAxNDkgNDlIMTYzQzE2NC4xMDUgNDkgMTY1IDQ5Ljg5NTQgMTY1IDUxVjE0NkgxNDdWNTFaIiBmaWxsPSIjNENBRjUwIi8+CjxwYXRoIGQ9Ik0xNjkgMzZDMTY5IDM0Ljg5NTQgMTY5Ljg5NSAzNCAxNzEgMzRIMTg1QzE4Ni4xMDUgMzQgMTg3IDM0Ljg5NTQgMTg3IDM2VjE0NkgxNjlWMzZaIiBmaWxsPSIjMjE5NkYzIi8+CjxsaW5lIHgxPSIyMy4yIiB5MT0iMTQ1Ljk2MSIgeDI9IjIwMi44IiB5Mj0iMTQ1Ljk2MSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuNyIgc3Ryb2tlLXdpZHRoPSIwLjQiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz4KPGxpbmUgeDE9IjY3IiB5MT0iMTQ4LjA3MiIgeDI9IjY3IiB5Mj0iMTQ3LjI1IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC41IiBzdHJva2Utd2lkdGg9IjAuNSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8cGF0aCBkPSJNNTkuMDU5MSAxNTIuMDI1VjE1Mi44OTNDNTkuMDU5MSAxNTMuMzU5IDU5LjAxNzQgMTUzLjc1MiA1OC45MzQxIDE1NC4wNzJDNTguODUwNyAxNTQuMzkzIDU4LjczMDkgMTU0LjY1IDU4LjU3NDcgMTU0Ljg0NkM1OC40MTg0IDE1NS4wNDEgNTguMjI5NiAxNTUuMTgzIDU4LjAwODMgMTU1LjI3MUM1Ny43ODk1IDE1NS4zNTcgNTcuNTQyMSAxNTUuNCA1Ny4yNjYxIDE1NS40QzU3LjA0NzMgMTU1LjQgNTYuODQ1NSAxNTUuMzczIDU2LjY2MDYgMTU1LjMxOEM1Ni40NzU3IDE1NS4yNjQgNTYuMzA5MSAxNTUuMTc2IDU2LjE2MDYgMTU1LjA1N0M1Ni4wMTQ4IDE1NC45MzQgNTUuODg5OCAxNTQuNzc1IDU1Ljc4NTYgMTU0LjU4QzU1LjY4MTUgMTU0LjM4NSA1NS42MDIgMTU0LjE0OCA1NS41NDczIDE1My44NjlDNTUuNDkyNyAxNTMuNTkgNTUuNDY1MyAxNTMuMjY1IDU1LjQ2NTMgMTUyLjg5M1YxNTIuMDI1QzU1LjQ2NTMgMTUxLjU1OSA1NS41MDcgMTUxLjE2OSA1NS41OTAzIDE1MC44NTRDNTUuNjc2MiAxNTAuNTM4IDU1Ljc5NzMgMTUwLjI4NiA1NS45NTM2IDE1MC4wOTZDNTYuMTA5OCAxNDkuOTAzIDU2LjI5NzMgMTQ5Ljc2NSA1Ni41MTYxIDE0OS42ODJDNTYuNzM3NCAxNDkuNTk4IDU2Ljk4NDggMTQ5LjU1NyA1Ny4yNTgzIDE0OS41NTdDNTcuNDc5NiAxNDkuNTU3IDU3LjY4MjggMTQ5LjU4NCA1Ny44Njc3IDE0OS42MzlDNTguMDU1MiAxNDkuNjkxIDU4LjIyMTggMTQ5Ljc3NSA1OC4zNjc3IDE0OS44OTNDNTguNTEzNSAxNTAuMDA3IDU4LjYzNzIgMTUwLjE2MSA1OC43Mzg3IDE1MC4zNTRDNTguODQyOSAxNTAuNTQ0IDU4LjkyMjMgMTUwLjc3NyA1OC45NzcgMTUxLjA1M0M1OS4wMzE3IDE1MS4zMjkgNTkuMDU5MSAxNTEuNjUzIDU5LjA1OTEgMTUyLjAyNVpNNTguMzMyNSAxNTMuMDFWMTUxLjkwNEM1OC4zMzI1IDE1MS42NDkgNTguMzE2OSAxNTEuNDI1IDU4LjI4NTYgMTUxLjIzMkM1OC4yNTcgMTUxLjAzNyA1OC4yMTQgMTUwLjg3IDU4LjE1NjcgMTUwLjczMkM1OC4wOTk0IDE1MC41OTQgNTguMDI2NSAxNTAuNDgyIDU3LjkzOCAxNTAuMzk2QzU3Ljg1MiAxNTAuMzExIDU3Ljc1MTggMTUwLjI0OCA1Ny42MzcyIDE1MC4yMDlDNTcuNTI1MiAxNTAuMTY3IDU3LjM5ODkgMTUwLjE0NiA1Ny4yNTgzIDE1MC4xNDZDNTcuMDg2NCAxNTAuMTQ2IDU2LjkzNDEgMTUwLjE3OSA1Ni44MDEyIDE1MC4yNDRDNTYuNjY4NCAxNTAuMzA3IDU2LjU1NjUgMTUwLjQwNyA1Ni40NjUzIDE1MC41NDVDNTYuMzc2OCAxNTAuNjgzIDU2LjMwOTEgMTUwLjg2NCA1Ni4yNjIyIDE1MS4wODhDNTYuMjE1MyAxNTEuMzEyIDU2LjE5MTkgMTUxLjU4NCA1Ni4xOTE5IDE1MS45MDRWMTUzLjAxQzU2LjE5MTkgMTUzLjI2NSA1Ni4yMDYyIDE1My40OSA1Ni4yMzQ4IDE1My42ODZDNTYuMjY2MSAxNTMuODgxIDU2LjMxMTcgMTU0LjA1IDU2LjM3MTYgMTU0LjE5M0M1Ni40MzE1IDE1NC4zMzQgNTYuNTA0NCAxNTQuNDUgNTYuNTkwMyAxNTQuNTQxQzU2LjY3NjIgMTU0LjYzMiA1Ni43NzUyIDE1NC43IDU2Ljg4NzIgMTU0Ljc0NEM1Ny4wMDE4IDE1NC43ODYgNTcuMTI4MSAxNTQuODA3IDU3LjI2NjEgMTU0LjgwN0M1Ny40NDMyIDE1NC44MDcgNTcuNTk4MSAxNTQuNzczIDU3LjczMDkgMTU0LjcwNUM1Ny44NjM3IDE1NC42MzcgNTcuOTc0NCAxNTQuNTMyIDU4LjA2MyAxNTQuMzg5QzU4LjE1NDEgMTU0LjI0MyA1OC4yMjE4IDE1NC4wNTcgNTguMjY2MSAxNTMuODNDNTguMzEwNCAxNTMuNjAxIDU4LjMzMjUgMTUzLjMyNyA1OC4zMzI1IDE1My4wMVpNNjIuNDQ2NCAxNDkuNjA0VjE1NS4zMjJINjEuNzIzN1YxNTAuNTA2TDYwLjI2NjcgMTUxLjAzN1YxNTAuMzg1TDYyLjMzMzEgMTQ5LjYwNEg2Mi40NDY0Wk02Ny42NjI0IDE0OS42MzVWMTU1LjMyMkg2Ni45MDg1VjE0OS42MzVINjcuNjYyNFpNNzAuMDQ1MiAxNTIuMTkzVjE1Mi44MTFINjcuNDk4M1YxNTIuMTkzSDcwLjA0NTJaTTcwLjQzMTkgMTQ5LjYzNVYxNTAuMjUySDY3LjQ5ODNWMTQ5LjYzNUg3MC40MzE5Wk03Mi45NzE2IDE1NS40QzcyLjY3NzMgMTU1LjQgNzIuNDEwNCAxNTUuMzUxIDcyLjE3MDggMTU1LjI1MkM3MS45MzM4IDE1NS4xNSA3MS43Mjk0IDE1NS4wMDggNzEuNTU3NSAxNTQuODI2QzcxLjM4ODMgMTU0LjY0NCA3MS4yNTgxIDE1NC40MjggNzEuMTY2OSAxNTQuMTc4QzcxLjA3NTggMTUzLjkyOCA3MS4wMzAyIDE1My42NTQgNzEuMDMwMiAxNTMuMzU3VjE1My4xOTNDNzEuMDMwMiAxNTIuODUgNzEuMDgxIDE1Mi41NDQgNzEuMTgyNSAxNTIuMjc1QzcxLjI4NDEgMTUyLjAwNSA3MS40MjIxIDE1MS43NzUgNzEuNTk2NiAxNTEuNTg4QzcxLjc3MTEgMTUxLjQgNzEuOTY5IDE1MS4yNTggNzIuMTkwMyAxNTEuMTYyQzcyLjQxMTcgMTUxLjA2NiA3Mi42NDA5IDE1MS4wMTggNzIuODc3OCAxNTEuMDE4QzczLjE3OTkgMTUxLjAxOCA3My40NDAzIDE1MS4wNyA3My42NTkxIDE1MS4xNzRDNzMuODgwNSAxNTEuMjc4IDc0LjA2MTQgMTUxLjQyNCA3NC4yMDIxIDE1MS42MTFDNzQuMzQyNyAxNTEuNzk2IDc0LjQ0NjkgMTUyLjAxNSA3NC41MTQ2IDE1Mi4yNjhDNzQuNTgyMyAxNTIuNTE4IDc0LjYxNjEgMTUyLjc5MSA3NC42MTYxIDE1My4wODhWMTUzLjQxMkg3MS40NTk5VjE1Mi44MjJINzMuODkzNVYxNTIuNzY4QzczLjg4MzEgMTUyLjU4IDczLjg0NCAxNTIuMzk4IDczLjc3NjMgMTUyLjIyMUM3My43MTEyIDE1Mi4wNDQgNzMuNjA3IDE1MS44OTggNzMuNDYzOCAxNTEuNzgzQzczLjMyMDYgMTUxLjY2OSA3My4xMjUyIDE1MS42MTEgNzIuODc3OCAxNTEuNjExQzcyLjcxMzggMTUxLjYxMSA3Mi41NjI3IDE1MS42NDYgNzIuNDI0NyAxNTEuNzE3QzcyLjI4NjcgMTUxLjc4NSA3Mi4xNjgyIDE1MS44ODYgNzIuMDY5MyAxNTIuMDIxQzcxLjk3MDMgMTUyLjE1NyA3MS44OTM1IDE1Mi4zMjIgNzEuODM4OCAxNTIuNTE4QzcxLjc4NDEgMTUyLjcxMyA3MS43NTY4IDE1Mi45MzggNzEuNzU2OCAxNTMuMTkzVjE1My4zNTdDNzEuNzU2OCAxNTMuNTU4IDcxLjc4NDEgMTUzLjc0NyA3MS44Mzg4IDE1My45MjRDNzEuODk2MSAxNTQuMDk4IDcxLjk3ODEgMTU0LjI1MiA3Mi4wODQ5IDE1NC4zODVDNzIuMTk0MyAxNTQuNTE4IDcyLjMyNTggMTU0LjYyMiA3Mi40Nzk0IDE1NC42OTdDNzIuNjM1NyAxNTQuNzczIDcyLjgxMjcgMTU0LjgxMSA3My4wMTA3IDE1NC44MTFDNzMuMjY1OSAxNTQuODExIDczLjQ4MiAxNTQuNzU4IDczLjY1OTEgMTU0LjY1NEM3My44MzYyIDE1NC41NSA3My45OTExIDE1NC40MTEgNzQuMTIzOSAxNTQuMjM2TDc0LjU2MTQgMTU0LjU4NEM3NC40NzAzIDE1NC43MjIgNzQuMzU0NCAxNTQuODU0IDc0LjIxMzggMTU0Ljk3OUM3NC4wNzMyIDE1NS4xMDQgNzMuOSAxNTUuMjA1IDczLjY5NDMgMTU1LjI4M0M3My40OTExIDE1NS4zNjEgNzMuMjUwMiAxNTUuNCA3Mi45NzE2IDE1NS40Wk03NS41Mzg2IDE0OS4zMjJINzYuMjY1MlYxNTQuNTAyTDc2LjIwMjcgMTU1LjMyMkg3NS41Mzg2VjE0OS4zMjJaTTc5LjEyMDYgMTUzLjE3NFYxNTMuMjU2Qzc5LjEyMDYgMTUzLjU2MyA3OS4wODQyIDE1My44NDggNzkuMDExMyAxNTQuMTExQzc4LjkzODMgMTU0LjM3MiA3OC44MzE2IDE1NC41OTggNzguNjkwOSAxNTQuNzkxQzc4LjU1MDMgMTU0Ljk4NCA3OC4zNzg0IDE1NS4xMzMgNzguMTc1MyAxNTUuMjRDNzcuOTcyMiAxNTUuMzQ3IDc3LjczOTEgMTU1LjQgNzcuNDc2MSAxNTUuNEM3Ny4yMDc5IDE1NS40IDc2Ljk3MjIgMTU1LjM1NSA3Ni43NjkxIDE1NS4yNjRDNzYuNTY4NSAxNTUuMTcgNzYuMzk5MyAxNTUuMDM2IDc2LjI2MTMgMTU0Ljg2MUM3Ni4xMjMyIDE1NC42ODcgNzYuMDEyNiAxNTQuNDc2IDc1LjkyOTIgMTU0LjIyOUM3NS44NDg1IDE1My45ODEgNzUuNzkyNSAxNTMuNzAyIDc1Ljc2MTMgMTUzLjM5M1YxNTMuMDMzQzc1Ljc5MjUgMTUyLjcyMSA3NS44NDg1IDE1Mi40NDEgNzUuOTI5MiAxNTIuMTkzQzc2LjAxMjYgMTUxLjk0NiA3Ni4xMjMyIDE1MS43MzUgNzYuMjYxMyAxNTEuNTYxQzc2LjM5OTMgMTUxLjM4MyA3Ni41Njg1IDE1MS4yNDkgNzYuNzY5MSAxNTEuMTU4Qzc2Ljk2OTYgMTUxLjA2NCA3Ny4yMDI3IDE1MS4wMTggNzcuNDY4MyAxNTEuMDE4Qzc3LjczMzkgMTUxLjAxOCA3Ny45Njk2IDE1MS4wNyA3OC4xNzUzIDE1MS4xNzRDNzguMzgxIDE1MS4yNzUgNzguNTUyOSAxNTEuNDIxIDc4LjY5MDkgMTUxLjYxMUM3OC44MzE2IDE1MS44MDEgNzguOTM4MyAxNTIuMDI5IDc5LjAxMTMgMTUyLjI5NUM3OS4wODQyIDE1Mi41NTggNzkuMTIwNiAxNTIuODUxIDc5LjEyMDYgMTUzLjE3NFpNNzguMzk0MSAxNTMuMjU2VjE1My4xNzRDNzguMzk0MSAxNTIuOTYzIDc4LjM3NDUgMTUyLjc2NSA3OC4zMzU1IDE1Mi41OEM3OC4yOTY0IDE1Mi4zOTMgNzguMjMzOSAxNTIuMjI5IDc4LjE0OCAxNTIuMDg4Qzc4LjA2MiAxNTEuOTQ1IDc3Ljk0ODggMTUxLjgzMyA3Ny44MDgxIDE1MS43NTJDNzcuNjY3NSAxNTEuNjY5IDc3LjQ5NDMgMTUxLjYyNyA3Ny4yODg2IDE1MS42MjdDNzcuMTA2MyAxNTEuNjI3IDc2Ljk0NzUgMTUxLjY1OCA3Ni44MTIgMTUxLjcyMUM3Ni42NzkyIDE1MS43ODMgNzYuNTY1OSAxNTEuODY4IDc2LjQ3MjIgMTUxLjk3NUM3Ni4zNzg0IDE1Mi4wNzkgNzYuMzAxNiAxNTIuMTk5IDc2LjI0MTcgMTUyLjMzNEM3Ni4xODQ0IDE1Mi40NjcgNzYuMTQxNSAxNTIuNjA1IDc2LjExMjggMTUyLjc0OFYxNTMuNjg5Qzc2LjE1NDUgMTUzLjg3MiA3Ni4yMjIyIDE1NC4wNDggNzYuMzE1OSAxNTQuMjE3Qzc2LjQxMjMgMTU0LjM4MyA3Ni41Mzk5IDE1NC41MiA3Ni42OTg4IDE1NC42MjdDNzYuODYwMiAxNTQuNzM0IDc3LjA1OTQgMTU0Ljc4NyA3Ny4yOTY0IDE1NC43ODdDNzcuNDkxNyAxNTQuNzg3IDc3LjY1ODQgMTU0Ljc0OCA3Ny43OTY0IDE1NC42N0M3Ny45MzcgMTU0LjU4OSA3OC4wNTAzIDE1NC40NzkgNzguMTM2MyAxNTQuMzM4Qzc4LjIyNDggMTU0LjE5NyA3OC4yODk5IDE1NC4wMzUgNzguMzMxNiAxNTMuODVDNzguMzczMiAxNTMuNjY1IDc4LjM5NDEgMTUzLjQ2NyA3OC4zOTQxIDE1My4yNTZaIiBmaWxsPSJibGFjayIgZmlsbC1vcGFjaXR5PSIwLjU0Ii8+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMV80MTgzXzkwODc3KSI+CjxsaW5lIHgxPSIxNTUuNSIgeTE9IjE0Ny4wNzIiIHgyPSIxNTUuNSIgeTI9IjE0Ni4yNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuNSIgc3Ryb2tlLXdpZHRoPSIwLjUiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz4KPHBhdGggZD0iTTE0Ny41NTkgMTUyLjAyNVYxNTIuODkyQzE0Ny41NTkgMTUzLjM1OCAxNDcuNTE3IDE1My43NTIgMTQ3LjQzNCAxNTQuMDcyQzE0Ny4zNTEgMTU0LjM5MiAxNDcuMjMxIDE1NC42NSAxNDcuMDc1IDE1NC44NDVDMTQ2LjkxOCAxNTUuMDQxIDE0Ni43MyAxNTUuMTgzIDE0Ni41MDggMTU1LjI3MUMxNDYuMjkgMTU1LjM1NyAxNDYuMDQyIDE1NS40IDE0NS43NjYgMTU1LjRDMTQ1LjU0NyAxNTUuNCAxNDUuMzQ2IDE1NS4zNzMgMTQ1LjE2MSAxNTUuMzE4QzE0NC45NzYgMTU1LjI2MyAxNDQuODA5IDE1NS4xNzYgMTQ0LjY2MSAxNTUuMDU2QzE0NC41MTUgMTU0LjkzNCAxNDQuMzkgMTU0Ljc3NSAxNDQuMjg2IDE1NC41OEMxNDQuMTgxIDE1NC4zODUgMTQ0LjEwMiAxNTQuMTQ4IDE0NC4wNDcgMTUzLjg2OUMxNDMuOTkzIDE1My41OSAxNDMuOTY1IDE1My4yNjUgMTQzLjk2NSAxNTIuODkyVjE1Mi4wMjVDMTQzLjk2NSAxNTEuNTU5IDE0NC4wMDcgMTUxLjE2OCAxNDQuMDkgMTUwLjg1M0MxNDQuMTc2IDE1MC41MzggMTQ0LjI5NyAxNTAuMjg2IDE0NC40NTQgMTUwLjA5NUMxNDQuNjEgMTQ5LjkwMyAxNDQuNzk3IDE0OS43NjUgMTQ1LjAxNiAxNDkuNjgxQzE0NS4yMzcgMTQ5LjU5OCAxNDUuNDg1IDE0OS41NTYgMTQ1Ljc1OCAxNDkuNTU2QzE0NS45OCAxNDkuNTU2IDE0Ni4xODMgMTQ5LjU4NCAxNDYuMzY4IDE0OS42MzhDMTQ2LjU1NSAxNDkuNjkxIDE0Ni43MjIgMTQ5Ljc3NSAxNDYuODY4IDE0OS44OTJDMTQ3LjAxMyAxNTAuMDA3IDE0Ny4xMzcgMTUwLjE2MSAxNDcuMjM5IDE1MC4zNTNDMTQ3LjM0MyAxNTAuNTQzIDE0Ny40MjIgMTUwLjc3NiAxNDcuNDc3IDE1MS4wNTJDMTQ3LjUzMiAxNTEuMzI5IDE0Ny41NTkgMTUxLjY1MyAxNDcuNTU5IDE1Mi4wMjVaTTE0Ni44MzIgMTUzLjAxVjE1MS45MDRDMTQ2LjgzMiAxNTEuNjQ5IDE0Ni44MTcgMTUxLjQyNSAxNDYuNzg2IDE1MS4yMzJDMTQ2Ljc1NyAxNTEuMDM3IDE0Ni43MTQgMTUwLjg3IDE0Ni42NTcgMTUwLjczMkMxNDYuNTk5IDE1MC41OTQgMTQ2LjUyNyAxNTAuNDgyIDE0Ni40MzggMTUwLjM5NkMxNDYuMzUyIDE1MC4zMSAxNDYuMjUyIDE1MC4yNDggMTQ2LjEzNyAxNTAuMjA5QzE0Ni4wMjUgMTUwLjE2NyAxNDUuODk5IDE1MC4xNDYgMTQ1Ljc1OCAxNTAuMTQ2QzE0NS41ODYgMTUwLjE0NiAxNDUuNDM0IDE1MC4xNzkgMTQ1LjMwMSAxNTAuMjQ0QzE0NS4xNjggMTUwLjMwNiAxNDUuMDU2IDE1MC40MDcgMTQ0Ljk2NSAxNTAuNTQ1QzE0NC44NzcgMTUwLjY4MyAxNDQuODA5IDE1MC44NjQgMTQ0Ljc2MiAxNTEuMDg4QzE0NC43MTUgMTUxLjMxMiAxNDQuNjkyIDE1MS41ODQgMTQ0LjY5MiAxNTEuOTA0VjE1My4wMUMxNDQuNjkyIDE1My4yNjUgMTQ0LjcwNiAxNTMuNDkgMTQ0LjczNSAxNTMuNjg1QzE0NC43NjYgMTUzLjg4MSAxNDQuODEyIDE1NC4wNSAxNDQuODcyIDE1NC4xOTNDMTQ0LjkzMSAxNTQuMzM0IDE0NS4wMDQgMTU0LjQ1IDE0NS4wOSAxNTQuNTQxQzE0NS4xNzYgMTU0LjYzMiAxNDUuMjc1IDE1NC43IDE0NS4zODcgMTU0Ljc0NEMxNDUuNTAyIDE1NC43ODYgMTQ1LjYyOCAxNTQuODA2IDE0NS43NjYgMTU0LjgwNkMxNDUuOTQzIDE1NC44MDYgMTQ2LjA5OCAxNTQuNzczIDE0Ni4yMzEgMTU0LjcwNUMxNDYuMzY0IDE1NC42MzcgMTQ2LjQ3NCAxNTQuNTMyIDE0Ni41NjMgMTU0LjM4OEMxNDYuNjU0IDE1NC4yNDMgMTQ2LjcyMiAxNTQuMDU2IDE0Ni43NjYgMTUzLjgzQzE0Ni44MSAxNTMuNjAxIDE0Ni44MzIgMTUzLjMyNyAxNDYuODMyIDE1My4wMVpNMTUyLjI5OCAxNTQuNzI4VjE1NS4zMjJIMTQ4LjU3NVYxNTQuODAyTDE1MC40MzkgMTUyLjcyOEMxNTAuNjY4IDE1Mi40NzMgMTUwLjg0NSAxNTIuMjU3IDE1MC45NyAxNTIuMDhDMTUxLjA5NyAxNTEuOSAxNTEuMTg2IDE1MS43NCAxNTEuMjM1IDE1MS41OTlDMTUxLjI4OCAxNTEuNDU2IDE1MS4zMTQgMTUxLjMxIDE1MS4zMTQgMTUxLjE2MkMxNTEuMzE0IDE1MC45NzQgMTUxLjI3NCAxNTAuODA1IDE1MS4xOTYgMTUwLjY1NEMxNTEuMTIxIDE1MC41IDE1MS4wMDkgMTUwLjM3OCAxNTAuODYgMTUwLjI4N0MxNTAuNzEyIDE1MC4xOTYgMTUwLjUzMiAxNTAuMTUgMTUwLjMyMSAxNTAuMTVDMTUwLjA2OSAxNTAuMTUgMTQ5Ljg1OCAxNTAuMiAxNDkuNjg5IDE1MC4yOTlDMTQ5LjUyMiAxNTAuMzk1IDE0OS4zOTcgMTUwLjUzIDE0OS4zMTQgMTUwLjcwNUMxNDkuMjMgMTUwLjg3OSAxNDkuMTg5IDE1MS4wOCAxNDkuMTg5IDE1MS4zMDZIMTQ4LjQ2NkMxNDguNDY2IDE1MC45ODYgMTQ4LjUzNiAxNTAuNjkzIDE0OC42NzcgMTUwLjQyN0MxNDguODE3IDE1MC4xNjIgMTQ5LjAyNiAxNDkuOTUxIDE0OS4zMDIgMTQ5Ljc5NUMxNDkuNTc4IDE0OS42MzYgMTQ5LjkxOCAxNDkuNTU2IDE1MC4zMjEgMTQ5LjU1NkMxNTAuNjgxIDE0OS41NTYgMTUwLjk4OCAxNDkuNjIgMTUxLjI0MyAxNDkuNzQ4QzE1MS40OTggMTQ5Ljg3MyAxNTEuNjk0IDE1MC4wNSAxNTEuODI5IDE1MC4yNzlDMTUxLjk2NyAxNTAuNTA2IDE1Mi4wMzYgMTUwLjc3MSAxNTIuMDM2IDE1MS4wNzZDMTUyLjAzNiAxNTEuMjQzIDE1Mi4wMDggMTUxLjQxMiAxNTEuOTUgMTUxLjU4NEMxNTEuODk2IDE1MS43NTMgMTUxLjgxOSAxNTEuOTIyIDE1MS43MiAxNTIuMDkyQzE1MS42MjMgMTUyLjI2MSAxNTEuNTEgMTUyLjQyNyAxNTEuMzggMTUyLjU5MkMxNTEuMjUyIDE1Mi43NTYgMTUxLjExNiAxNTIuOTE3IDE1MC45NyAxNTMuMDc2TDE0OS40NDYgMTU0LjcyOEgxNTIuMjk4Wk0xNTYuMTYyIDE0OS42MzVWMTU1LjMyMkgxNTUuNDA5VjE0OS42MzVIMTU2LjE2MlpNMTU4LjU0NSAxNTIuMTkzVjE1Mi44MUgxNTUuOTk4VjE1Mi4xOTNIMTU4LjU0NVpNMTU4LjkzMiAxNDkuNjM1VjE1MC4yNTJIMTU1Ljk5OFYxNDkuNjM1SDE1OC45MzJaTTE2MS40NzIgMTU1LjRDMTYxLjE3NyAxNTUuNCAxNjAuOTEgMTU1LjM1MSAxNjAuNjcxIDE1NS4yNTJDMTYwLjQzNCAxNTUuMTUgMTYwLjIyOSAxNTUuMDA4IDE2MC4wNTggMTU0LjgyNkMxNTkuODg4IDE1NC42NDQgMTU5Ljc1OCAxNTQuNDI3IDE1OS42NjcgMTU0LjE3N0MxNTkuNTc2IDE1My45MjcgMTU5LjUzIDE1My42NTQgMTU5LjUzIDE1My4zNTdWMTUzLjE5M0MxNTkuNTMgMTUyLjg0OSAxNTkuNTgxIDE1Mi41NDMgMTU5LjY4MyAxNTIuMjc1QzE1OS43ODQgMTUyLjAwNCAxNTkuOTIyIDE1MS43NzUgMTYwLjA5NyAxNTEuNTg4QzE2MC4yNzEgMTUxLjQgMTYwLjQ2OSAxNTEuMjU4IDE2MC42OSAxNTEuMTYyQzE2MC45MTIgMTUxLjA2NiAxNjEuMTQxIDE1MS4wMTcgMTYxLjM3OCAxNTEuMDE3QzE2MS42OCAxNTEuMDE3IDE2MS45NCAxNTEuMDY5IDE2Mi4xNTkgMTUxLjE3NEMxNjIuMzggMTUxLjI3OCAxNjIuNTYxIDE1MS40MjQgMTYyLjcwMiAxNTEuNjExQzE2Mi44NDMgMTUxLjc5NiAxNjIuOTQ3IDE1Mi4wMTUgMTYzLjAxNSAxNTIuMjY3QzE2My4wODIgMTUyLjUxNyAxNjMuMTE2IDE1Mi43OTEgMTYzLjExNiAxNTMuMDg4VjE1My40MTJIMTU5Ljk2VjE1Mi44MjJIMTYyLjM5M1YxNTIuNzY3QzE2Mi4zODMgMTUyLjU4IDE2Mi4zNDQgMTUyLjM5OCAxNjIuMjc2IDE1Mi4yMkMxNjIuMjExIDE1Mi4wNDMgMTYyLjEwNyAxNTEuODk4IDE2MS45NjQgMTUxLjc4M0MxNjEuODIxIDE1MS42NjggMTYxLjYyNSAxNTEuNjExIDE2MS4zNzggMTUxLjYxMUMxNjEuMjE0IDE1MS42MTEgMTYxLjA2MyAxNTEuNjQ2IDE2MC45MjUgMTUxLjcxN0MxNjAuNzg3IDE1MS43ODQgMTYwLjY2OCAxNTEuODg2IDE2MC41NjkgMTUyLjAyMUMxNjAuNDcgMTUyLjE1NyAxNjAuMzkzIDE1Mi4zMjIgMTYwLjMzOSAxNTIuNTE3QzE2MC4yODQgMTUyLjcxMyAxNjAuMjU3IDE1Mi45MzggMTYwLjI1NyAxNTMuMTkzVjE1My4zNTdDMTYwLjI1NyAxNTMuNTU4IDE2MC4yODQgMTUzLjc0NyAxNjAuMzM5IDE1My45MjRDMTYwLjM5NiAxNTQuMDk4IDE2MC40NzggMTU0LjI1MiAxNjAuNTg1IDE1NC4zODVDMTYwLjY5NCAxNTQuNTE3IDE2MC44MjYgMTU0LjYyMiAxNjAuOTc5IDE1NC42OTdDMTYxLjEzNiAxNTQuNzczIDE2MS4zMTMgMTU0LjgxIDE2MS41MTEgMTU0LjgxQzE2MS43NjYgMTU0LjgxIDE2MS45ODIgMTU0Ljc1OCAxNjIuMTU5IDE1NC42NTRDMTYyLjMzNiAxNTQuNTUgMTYyLjQ5MSAxNTQuNDExIDE2Mi42MjQgMTU0LjIzNkwxNjMuMDYxIDE1NC41ODRDMTYyLjk3IDE1NC43MjIgMTYyLjg1NCAxNTQuODUzIDE2Mi43MTQgMTU0Ljk3OEMxNjIuNTczIDE1NS4xMDMgMTYyLjQgMTU1LjIwNSAxNjIuMTk0IDE1NS4yODNDMTYxLjk5MSAxNTUuMzYxIDE2MS43NSAxNTUuNCAxNjEuNDcyIDE1NS40Wk0xNjQuMDM5IDE0OS4zMjJIMTY0Ljc2NVYxNTQuNTAyTDE2NC43MDMgMTU1LjMyMkgxNjQuMDM5VjE0OS4zMjJaTTE2Ny42MjEgMTUzLjE3NFYxNTMuMjU2QzE2Ny42MjEgMTUzLjU2MyAxNjcuNTg0IDE1My44NDggMTY3LjUxMSAxNTQuMTExQzE2Ny40MzggMTU0LjM3MiAxNjcuMzMyIDE1NC41OTggMTY3LjE5MSAxNTQuNzkxQzE2Ny4wNSAxNTQuOTgzIDE2Ni44NzggMTU1LjEzMyAxNjYuNjc1IDE1NS4yNEMxNjYuNDcyIDE1NS4zNDcgMTY2LjIzOSAxNTUuNCAxNjUuOTc2IDE1NS40QzE2NS43MDggMTU1LjQgMTY1LjQ3MiAxNTUuMzU1IDE2NS4yNjkgMTU1LjI2M0MxNjUuMDY5IDE1NS4xNyAxNjQuODk5IDE1NS4wMzYgMTY0Ljc2MSAxNTQuODYxQzE2NC42MjMgMTU0LjY4NyAxNjQuNTEzIDE1NC40NzYgMTY0LjQyOSAxNTQuMjI4QzE2NC4zNDggMTUzLjk4MSAxNjQuMjkzIDE1My43MDIgMTY0LjI2MSAxNTMuMzkyVjE1My4wMzNDMTY0LjI5MyAxNTIuNzIgMTY0LjM0OCAxNTIuNDQxIDE2NC40MjkgMTUyLjE5M0MxNjQuNTEzIDE1MS45NDYgMTY0LjYyMyAxNTEuNzM1IDE2NC43NjEgMTUxLjU2QzE2NC44OTkgMTUxLjM4MyAxNjUuMDY5IDE1MS4yNDkgMTY1LjI2OSAxNTEuMTU4QzE2NS40NyAxNTEuMDY0IDE2NS43MDMgMTUxLjAxNyAxNjUuOTY4IDE1MS4wMTdDMTY2LjIzNCAxNTEuMDE3IDE2Ni40NyAxNTEuMDY5IDE2Ni42NzUgMTUxLjE3NEMxNjYuODgxIDE1MS4yNzUgMTY3LjA1MyAxNTEuNDIxIDE2Ny4xOTEgMTUxLjYxMUMxNjcuMzMyIDE1MS44MDEgMTY3LjQzOCAxNTIuMDI5IDE2Ny41MTEgMTUyLjI5NUMxNjcuNTg0IDE1Mi41NTggMTY3LjYyMSAxNTIuODUxIDE2Ny42MjEgMTUzLjE3NFpNMTY2Ljg5NCAxNTMuMjU2VjE1My4xNzRDMTY2Ljg5NCAxNTIuOTYzIDE2Ni44NzUgMTUyLjc2NSAxNjYuODM1IDE1Mi41OEMxNjYuNzk2IDE1Mi4zOTIgMTY2LjczNCAxNTIuMjI4IDE2Ni42NDggMTUyLjA4OEMxNjYuNTYyIDE1MS45NDQgMTY2LjQ0OSAxNTEuODMyIDE2Ni4zMDggMTUxLjc1MkMxNjYuMTY4IDE1MS42NjggMTY1Ljk5NCAxNTEuNjI3IDE2NS43ODkgMTUxLjYyN0MxNjUuNjA2IDE1MS42MjcgMTY1LjQ0NyAxNTEuNjU4IDE2NS4zMTIgMTUxLjcyQzE2NS4xNzkgMTUxLjc4MyAxNjUuMDY2IDE1MS44NjggMTY0Ljk3MiAxNTEuOTc0QzE2NC44NzggMTUyLjA3OSAxNjQuODAyIDE1Mi4xOTggMTY0Ljc0MiAxNTIuMzM0QzE2NC42ODQgMTUyLjQ2NyAxNjQuNjQxIDE1Mi42MDUgMTY0LjYxMyAxNTIuNzQ4VjE1My42ODlDMTY0LjY1NCAxNTMuODcyIDE2NC43MjIgMTU0LjA0NyAxNjQuODE2IDE1NC4yMTdDMTY0LjkxMiAxNTQuMzgzIDE2NS4wNCAxNTQuNTIgMTY1LjE5OSAxNTQuNjI3QzE2NS4zNiAxNTQuNzMzIDE2NS41NTkgMTU0Ljc4NyAxNjUuNzk2IDE1NC43ODdDMTY1Ljk5MiAxNTQuNzg3IDE2Ni4xNTggMTU0Ljc0OCAxNjYuMjk2IDE1NC42N0MxNjYuNDM3IDE1NC41ODkgMTY2LjU1IDE1NC40NzggMTY2LjYzNiAxNTQuMzM4QzE2Ni43MjUgMTU0LjE5NyAxNjYuNzkgMTU0LjAzNCAxNjYuODMyIDE1My44NDlDMTY2Ljg3MyAxNTMuNjY0IDE2Ni44OTQgMTUzLjQ2NyAxNjYuODk0IDE1My4yNTZaIiBmaWxsPSJibGFjayIgZmlsbC1vcGFjaXR5PSIwLjU0Ii8+CjwvZz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF80MTgzXzkwODc3Ij4KPHJlY3Qgd2lkdGg9IjIwMCIgaGVpZ2h0PSIxNjAiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjxjbGlwUGF0aCBpZD0iY2xpcDFfNDE4M185MDg3NyI+CjxyZWN0IHdpZHRoPSI4OC41IiBoZWlnaHQ9IjEwLjMyMiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExMS41IDE0NikiLz4KPC9jbGlwUGF0aD4KPC9kZWZzPgo8L3N2Zz4K", + "description": "Displays changes to time-series data over time—for example, temperature or humidity readings.", + "descriptor": { + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "resources": [], + "templateHtml": "\n", + "templateCss": "", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'bar',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('bar'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", + "settingsSchema": "{}", + "dataKeySettingsSchema": "{}", + "latestDataKeySettingsSchema": "{}", + "settingsDirective": "tb-time-series-chart-widget-settings", + "dataKeySettingsDirective": "tb-time-series-chart-key-settings", + "latestDataKeySettingsDirective": "", + "hasBasicMode": true, + "basicModeDirective": "tb-time-series-chart-basic-config", + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"dd MMM yyyy HH:mm:ss\",\"lastUpdateAgo\":false,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Bar chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + }, + "tags": [ + "chart", + "time series", + "time-series", + "bar", + "bar chart" + ] +} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/line_chart.json b/application/src/main/data/json/system/widget_types/line_chart.json new file mode 100644 index 0000000000..5fff201c28 --- /dev/null +++ b/application/src/main/data/json/system/widget_types/line_chart.json @@ -0,0 +1,32 @@ +{ + "fqn": "line_chart", + "name": "Line chart", + "deprecated": false, + "image": "tb-image:Y2hhcnRfKDEpLnN2Zw==:IkxpbmUgY2hhcnQiIHN5c3RlbSB3aWRnZXQgaW1hZ2U=;data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE2MCIgdmlld0JveD0iMCAwIDIwMCAxNjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF80MTg0Xzk0NTI3KSI+CjxwYXRoIGQ9Ik0yLjg0NzY2IDEuMjgxMjVWN0gyLjEyNVYyLjE4MzU5TDAuNjY3OTY5IDIuNzE0ODRWMi4wNjI1TDIuNzM0MzggMS4yODEyNUgyLjg0NzY2Wk04LjY3NTE3IDMuNzAzMTJWNC41NzAzMUM4LjY3NTE3IDUuMDM2NDYgOC42MzM1MSA1LjQyOTY5IDguNTUwMTcgNS43NUM4LjQ2Njg0IDYuMDcwMzEgOC4zNDcwNSA2LjMyODEyIDguMTkwOCA2LjUyMzQ0QzguMDM0NTUgNi43MTg3NSA3Ljg0NTc1IDYuODYwNjggNy42MjQzOSA2Ljk0OTIyQzcuNDA1NjQgNy4wMzUxNiA3LjE1ODI1IDcuMDc4MTIgNi44ODIyIDcuMDc4MTJDNi42NjM0NSA3LjA3ODEyIDYuNDYxNjMgNy4wNTA3OCA2LjI3NjczIDYuOTk2MDlDNi4wOTE4NCA2Ljk0MTQxIDUuOTI1MTcgNi44NTQxNyA1Ljc3NjczIDYuNzM0MzhDNS42MzA5IDYuNjExOTggNS41MDU5IDYuNDUzMTIgNS40MDE3MyA2LjI1NzgxQzUuMjk3NTcgNi4wNjI1IDUuMjE4MTQgNS44MjU1MiA1LjE2MzQ1IDUuNTQ2ODhDNS4xMDg3NyA1LjI2ODIzIDUuMDgxNDIgNC45NDI3MSA1LjA4MTQyIDQuNTcwMzFWMy43MDMxMkM1LjA4MTQyIDMuMjM2OTggNS4xMjMwOSAyLjg0NjM1IDUuMjA2NDIgMi41MzEyNUM1LjI5MjM2IDIuMjE2MTUgNS40MTM0NSAxLjk2MzU0IDUuNTY5NyAxLjc3MzQ0QzUuNzI1OTUgMS41ODA3MyA1LjkxMzQ1IDEuNDQyNzEgNi4xMzIyIDEuMzU5MzhDNi4zNTM1NiAxLjI3NjA0IDYuNjAwOTUgMS4yMzQzOCA2Ljg3NDM5IDEuMjM0MzhDNy4wOTU3NSAxLjIzNDM4IDcuMjk4ODcgMS4yNjE3MiA3LjQ4Mzc3IDEuMzE2NDFDNy42NzEyNyAxLjM2ODQ5IDcuODM3OTMgMS40NTMxMiA3Ljk4Mzc3IDEuNTcwMzFDOC4xMjk2IDEuNjg0OSA4LjI1MzMgMS44Mzg1NCA4LjM1NDg2IDIuMDMxMjVDOC40NTkwMyAyLjIyMTM1IDguNTM4NDUgMi40NTQ0MyA4LjU5MzE0IDIuNzMwNDdDOC42NDc4MyAzLjAwNjUxIDguNjc1MTcgMy4zMzA3MyA4LjY3NTE3IDMuNzAzMTJaTTcuOTQ4NjEgNC42ODc1VjMuNTgyMDNDNy45NDg2MSAzLjMyNjgyIDcuOTMyOTggMy4xMDI4NiA3LjkwMTczIDIuOTEwMTZDNy44NzMwOSAyLjcxNDg0IDcuODMwMTIgMi41NDgxOCA3Ljc3MjgzIDIuNDEwMTZDNy43MTU1NCAyLjI3MjE0IDcuNjQyNjIgMi4xNjAxNiA3LjU1NDA4IDIuMDc0MjJDNy40NjgxNCAxLjk4ODI4IDcuMzY3ODggMS45MjU3OCA3LjI1MzMgMS44ODY3MkM3LjE0MTMyIDEuODQ1MDUgNy4wMTUwMiAxLjgyNDIyIDYuODc0MzkgMS44MjQyMkM2LjcwMjUyIDEuODI0MjIgNi41NTAxNyAxLjg1Njc3IDYuNDE3MzYgMS45MjE4OEM2LjI4NDU1IDEuOTg0MzggNi4xNzI1NyAyLjA4NDY0IDYuMDgxNDIgMi4yMjI2NkM1Ljk5Mjg4IDIuMzYwNjggNS45MjUxNyAyLjU0MTY3IDUuODc4MyAyLjc2NTYyQzUuODMxNDIgMi45ODk1OCA1LjgwNzk4IDMuMjYxNzIgNS44MDc5OCAzLjU4MjAzVjQuNjg3NUM1LjgwNzk4IDQuOTQyNzEgNS44MjIzMSA1LjE2Nzk3IDUuODUwOTUgNS4zNjMyOEM1Ljg4MjIgNS41NTg1OSA1LjkyNzc4IDUuNzI3ODYgNS45ODc2NyA1Ljg3MTA5QzYuMDQ3NTcgNi4wMTE3MiA2LjEyMDQ4IDYuMTI3NiA2LjIwNjQyIDYuMjE4NzVDNi4yOTIzNiA2LjMwOTkgNi4zOTEzMiA2LjM3NzYgNi41MDMzIDYuNDIxODhDNi42MTc4OCA2LjQ2MzU0IDYuNzQ0MTggNi40ODQzOCA2Ljg4MjIgNi40ODQzOEM3LjA1OTI5IDYuNDg0MzggNy4yMTQyMyA2LjQ1MDUyIDcuMzQ3MDUgNi4zODI4MUM3LjQ3OTg2IDYuMzE1MSA3LjU5MDU0IDYuMjA5NjQgNy42NzkwOCA2LjA2NjQxQzcuNzcwMjIgNS45MjA1NyA3LjgzNzkzIDUuNzM0MzggNy44ODIyIDUuNTA3ODFDNy45MjY0NyA1LjI3ODY1IDcuOTQ4NjEgNS4wMDUyMSA3Ljk0ODYxIDQuNjg3NVpNMTMuMzA3NCAzLjcwMzEyVjQuNTcwMzFDMTMuMzA3NCA1LjAzNjQ2IDEzLjI2NTcgNS40Mjk2OSAxMy4xODI0IDUuNzVDMTMuMDk5IDYuMDcwMzEgMTIuOTc5MyA2LjMyODEyIDEyLjgyMyA2LjUyMzQ0QzEyLjY2NjggNi43MTg3NSAxMi40Nzc5IDYuODYwNjggMTIuMjU2NiA2Ljk0OTIyQzEyLjAzNzggNy4wMzUxNiAxMS43OTA0IDcuMDc4MTIgMTEuNTE0NCA3LjA3ODEyQzExLjI5NTcgNy4wNzgxMiAxMS4wOTM4IDcuMDUwNzggMTAuOTA4OSA2Ljk5NjA5QzEwLjcyNCA2Ljk0MTQxIDEwLjU1NzQgNi44NTQxNyAxMC40MDg5IDYuNzM0MzhDMTAuMjYzMSA2LjYxMTk4IDEwLjEzODEgNi40NTMxMiAxMC4wMzM5IDYuMjU3ODFDOS45Mjk3NyA2LjA2MjUgOS44NTAzNCA1LjgyNTUyIDkuNzk1NjYgNS41NDY4OEM5Ljc0MDk3IDUuMjY4MjMgOS43MTM2MyA0Ljk0MjcxIDkuNzEzNjMgNC41NzAzMVYzLjcwMzEyQzkuNzEzNjMgMy4yMzY5OCA5Ljc1NTI5IDIuODQ2MzUgOS44Mzg2MyAyLjUzMTI1QzkuOTI0NTYgMi4yMTYxNSAxMC4wNDU3IDEuOTYzNTQgMTAuMjAxOSAxLjc3MzQ0QzEwLjM1ODIgMS41ODA3MyAxMC41NDU3IDEuNDQyNzEgMTAuNzY0NCAxLjM1OTM4QzEwLjk4NTggMS4yNzYwNCAxMS4yMzMyIDEuMjM0MzggMTEuNTA2NiAxLjIzNDM4QzExLjcyNzkgMS4yMzQzOCAxMS45MzExIDEuMjYxNzIgMTIuMTE2IDEuMzE2NDFDMTIuMzAzNSAxLjM2ODQ5IDEyLjQ3MDEgMS40NTMxMiAxMi42MTYgMS41NzAzMUMxMi43NjE4IDEuNjg0OSAxMi44ODU1IDEuODM4NTQgMTIuOTg3MSAyLjAzMTI1QzEzLjA5MTIgMi4yMjEzNSAxMy4xNzA3IDIuNDU0NDMgMTMuMjI1MyAyLjczMDQ3QzEzLjI4IDMuMDA2NTEgMTMuMzA3NCAzLjMzMDczIDEzLjMwNzQgMy43MDMxMlpNMTIuNTgwOCA0LjY4NzVWMy41ODIwM0MxMi41ODA4IDMuMzI2ODIgMTIuNTY1MiAzLjEwMjg2IDEyLjUzMzkgMi45MTAxNkMxMi41MDUzIDIuNzE0ODQgMTIuNDYyMyAyLjU0ODE4IDEyLjQwNSAyLjQxMDE2QzEyLjM0NzcgMi4yNzIxNCAxMi4yNzQ4IDIuMTYwMTYgMTIuMTg2MyAyLjA3NDIyQzEyLjEwMDMgMS45ODgyOCAxMi4wMDAxIDEuOTI1NzggMTEuODg1NSAxLjg4NjcyQzExLjc3MzUgMS44NDUwNSAxMS42NDcyIDEuODI0MjIgMTEuNTA2NiAxLjgyNDIyQzExLjMzNDcgMS44MjQyMiAxMS4xODI0IDEuODU2NzcgMTEuMDQ5NiAxLjkyMTg4QzEwLjkxNjggMS45ODQzOCAxMC44MDQ4IDIuMDg0NjQgMTAuNzEzNiAyLjIyMjY2QzEwLjYyNTEgMi4zNjA2OCAxMC41NTc0IDIuNTQxNjcgMTAuNTEwNSAyLjc2NTYyQzEwLjQ2MzYgMi45ODk1OCAxMC40NDAyIDMuMjYxNzIgMTAuNDQwMiAzLjU4MjAzVjQuNjg3NUMxMC40NDAyIDQuOTQyNzEgMTAuNDU0NSA1LjE2Nzk3IDEwLjQ4MzIgNS4zNjMyOEMxMC41MTQ0IDUuNTU4NTkgMTAuNTYgNS43Mjc4NiAxMC42MTk5IDUuODcxMDlDMTAuNjc5OCA2LjAxMTcyIDEwLjc1MjcgNi4xMjc2IDEwLjgzODYgNi4yMTg3NUMxMC45MjQ2IDYuMzA5OSAxMS4wMjM1IDYuMzc3NiAxMS4xMzU1IDYuNDIxODhDMTEuMjUwMSA2LjQ2MzU0IDExLjM3NjQgNi40ODQzOCAxMS41MTQ0IDYuNDg0MzhDMTEuNjkxNSA2LjQ4NDM4IDExLjg0NjQgNi40NTA1MiAxMS45NzkzIDYuMzgyODFDMTIuMTEyMSA2LjMxNTEgMTIuMjIyNyA2LjIwOTY0IDEyLjMxMTMgNi4wNjY0MUMxMi40MDI0IDUuOTIwNTcgMTIuNDcwMSA1LjczNDM4IDEyLjUxNDQgNS41MDc4MUMxMi41NTg3IDUuMjc4NjUgMTIuNTgwOCA1LjAwNTIxIDEyLjU4MDggNC42ODc1Wk0xNC4zMDY4IDIuNzA3MDNWMi40MDYyNUMxNC4zMDY4IDIuMTkwMSAxNC4zNTM2IDEuOTkzNDkgMTQuNDQ3NCAxLjgxNjQxQzE0LjU0MTEgMS42MzkzMiAxNC42NzUzIDEuNDk3NCAxNC44NDk3IDEuMzkwNjJDMTUuMDI0MiAxLjI4Mzg1IDE1LjIzMTIgMS4yMzA0NyAxNS40NzA4IDEuMjMwNDdDMTUuNzE1NiAxLjIzMDQ3IDE1LjkyNCAxLjI4Mzg1IDE2LjA5NTggMS4zOTA2MkMxNi4yNzAzIDEuNDk3NCAxNi40MDQ0IDEuNjM5MzIgMTYuNDk4MiAxLjgxNjQxQzE2LjU5MTkgMS45OTM0OSAxNi42Mzg4IDIuMTkwMSAxNi42Mzg4IDIuNDA2MjVWMi43MDcwM0MxNi42Mzg4IDIuOTE3OTcgMTYuNTkxOSAzLjExMTk4IDE2LjQ5ODIgMy4yODkwNkMxNi40MDcgMy40NjYxNSAxNi4yNzQyIDMuNjA4MDcgMTYuMDk5NyAzLjcxNDg0QzE1LjkyNzkgMy44MjE2MSAxNS43MjA4IDMuODc1IDE1LjQ3ODYgMy44NzVDMTUuMjM2NSAzLjg3NSAxNS4wMjY4IDMuODIxNjEgMTQuODQ5NyAzLjcxNDg0QzE0LjY3NTMgMy42MDgwNyAxNC41NDExIDMuNDY2MTUgMTQuNDQ3NCAzLjI4OTA2QzE0LjM1MzYgMy4xMTE5OCAxNC4zMDY4IDIuOTE3OTcgMTQuMzA2OCAyLjcwNzAzWk0xNC44NDk3IDIuNDA2MjVWMi43MDcwM0MxNC44NDk3IDIuODI2ODIgMTQuODcxOSAyLjk0MDEgMTQuOTE2MSAzLjA0Njg4QzE0Ljk2MyAzLjE1MzY1IDE1LjAzMzMgMy4yNDA4OSAxNS4xMjcxIDMuMzA4NTlDMTUuMjIwOCAzLjM3MzcgMTUuMzM4IDMuNDA2MjUgMTUuNDc4NiAzLjQwNjI1QzE1LjYxOTMgMy40MDYyNSAxNS43MzUyIDMuMzczNyAxNS44MjYzIDMuMzA4NTlDMTUuOTE3NCAzLjI0MDg5IDE1Ljk4NTIgMy4xNTM2NSAxNi4wMjk0IDMuMDQ2ODhDMTYuMDczNyAyLjk0MDEgMTYuMDk1OCAyLjgyNjgyIDE2LjA5NTggMi43MDcwM1YyLjQwNjI1QzE2LjA5NTggMi4yODM4NSAxNi4wNzI0IDIuMTY5MjcgMTYuMDI1NSAyLjA2MjVDMTUuOTgxMiAxLjk1MzEyIDE1LjkxMjIgMS44NjU4OSAxNS44MTg1IDEuODAwNzhDMTUuNzI3MyAxLjczMzA3IDE1LjYxMTUgMS42OTkyMiAxNS40NzA4IDEuNjk5MjJDMTUuMzMyOCAxLjY5OTIyIDE1LjIxNjkgMS43MzMwNyAxNS4xMjMyIDEuODAwNzhDMTUuMDMyIDEuODY1ODkgMTQuOTYzIDEuOTUzMTIgMTQuOTE2MSAyLjA2MjVDMTQuODcxOSAyLjE2OTI3IDE0Ljg0OTcgMi4yODM4NSAxNC44NDk3IDIuNDA2MjVaTTE3LjA3NjMgNS45MTAxNlY1LjYwNTQ3QzE3LjA3NjMgNS4zOTE5MyAxNy4xMjMyIDUuMTk2NjEgMTcuMjE2OSA1LjAxOTUzQzE3LjMxMDcgNC44NDI0NSAxNy40NDQ4IDQuNzAwNTIgMTcuNjE5MyA0LjU5Mzc1QzE3Ljc5MzcgNC40ODY5OCAxOC4wMDA4IDQuNDMzNTkgMTguMjQwNCA0LjQzMzU5QzE4LjQ4NTIgNC40MzM1OSAxOC42OTM1IDQuNDg2OTggMTguODY1NCA0LjU5Mzc1QzE5LjAzOTggNC43MDA1MiAxOS4xNzQgNC44NDI0NSAxOS4yNjc3IDUuMDE5NTNDMTkuMzYxNSA1LjE5NjYxIDE5LjQwODMgNS4zOTE5MyAxOS40MDgzIDUuNjA1NDdWNS45MTAxNkMxOS40MDgzIDYuMTIzNyAxOS4zNjE1IDYuMzE5MDEgMTkuMjY3NyA2LjQ5NjA5QzE5LjE3NjYgNi42NzMxOCAxOS4wNDM3IDYuODE1MSAxOC44NjkzIDYuOTIxODhDMTguNjk3NCA3LjAyODY1IDE4LjQ5MDQgNy4wODIwMyAxOC4yNDgyIDcuMDgyMDNDMTguMDA2IDcuMDgyMDMgMTcuNzk3NyA3LjAyODY1IDE3LjYyMzIgNi45MjE4OEMxNy40NDg3IDYuODE1MSAxNy4zMTMzIDYuNjczMTggMTcuMjE2OSA2LjQ5NjA5QzE3LjEyMzIgNi4zMTkwMSAxNy4wNzYzIDYuMTIzNyAxNy4wNzYzIDUuOTEwMTZaTTE3LjYxOTMgNS42MDU0N1Y1LjkxMDE2QzE3LjYxOTMgNi4wMjk5NSAxNy42NDE0IDYuMTQ0NTMgMTcuNjg1NyA2LjI1MzkxQzE3LjczMjUgNi4zNjA2OCAxNy44MDI5IDYuNDQ3OTIgMTcuODk2NiA2LjUxNTYyQzE3Ljk5MDQgNi41ODA3MyAxOC4xMDc1IDYuNjEzMjggMTguMjQ4MiA2LjYxMzI4QzE4LjM4ODggNi42MTMyOCAxOC41MDQ3IDYuNTgwNzMgMTguNTk1OCA2LjUxNTYyQzE4LjY4OTYgNi40NDc5MiAxOC43NTg2IDYuMzYwNjggMTguODAyOSA2LjI1MzkxQzE4Ljg0NzEgNi4xNDcxNCAxOC44NjkzIDYuMDMyNTUgMTguODY5MyA1LjkxMDE2VjUuNjA1NDdDMTguODY5MyA1LjQ4MzA3IDE4Ljg0NTggNS4zNjg0OSAxOC43OTkgNS4yNjE3MkMxOC43NTQ3IDUuMTU0OTUgMTguNjg1NyA1LjA2OTAxIDE4LjU5MTkgNS4wMDM5MUMxOC41MDA4IDQuOTM2MiAxOC4zODM2IDQuOTAyMzQgMTguMjQwNCA0LjkwMjM0QzE4LjEwMjMgNC45MDIzNCAxNy45ODY1IDQuOTM2MiAxNy44OTI3IDUuMDAzOTFDMTcuODAxNiA1LjA2OTAxIDE3LjczMjUgNS4xNTQ5NSAxNy42ODU3IDUuMjYxNzJDMTcuNjQxNCA1LjM2ODQ5IDE3LjYxOTMgNS40ODMwNyAxNy42MTkzIDUuNjA1NDdaTTE4LjQyIDIuMTIxMDlMMTUuNjQyNyA2LjU2NjQxTDE1LjIzNjUgNi4zMDg1OUwxOC4wMTM4IDEuODYzMjhMMTguNDIgMi4xMjEwOVoiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuNTQiLz4KPHBhdGggZD0iTTguMDU4NTkgMzMuNjY3N0M4LjA1ODU5IDM0LjAxNDEgNy45Nzc4NiAzNC4zMDgzIDcuODE2NDEgMzQuNTUwNUM3LjY1NzU1IDM0Ljc5MDEgNy40NDE0MSAzNC45NzI0IDcuMTY3OTcgMzUuMDk3NEM2Ljg5NzE0IDM1LjIyMjQgNi41OTExNSAzNS4yODQ5IDYuMjUgMzUuMjg0OUM1LjkwODg1IDM1LjI4NDkgNS42MDE1NiAzNS4yMjI0IDUuMzI4MTIgMzUuMDk3NEM1LjA1NDY5IDM0Ljk3MjQgNC44Mzg1NCAzNC43OTAxIDQuNjc5NjkgMzQuNTUwNUM0LjUyMDgzIDM0LjMwODMgNC40NDE0MSAzNC4wMTQxIDQuNDQxNDEgMzMuNjY3N0M0LjQ0MTQxIDMzLjQ0MTIgNC40ODQzOCAzMy4yMzQxIDQuNTcwMzEgMzMuMDQ2NkM0LjY1ODg1IDMyLjg1NjUgNC43ODI1NSAzMi42OTEyIDQuOTQxNDEgMzIuNTUwNUM1LjEwMjg2IDMyLjQwOTkgNS4yOTI5NyAzMi4zMDE4IDUuNTExNzIgMzIuMjI2M0M1LjczMzA3IDMyLjE0ODIgNS45NzY1NiAzMi4xMDkxIDYuMjQyMTkgMzIuMTA5MUM2LjU5MTE1IDMyLjEwOTEgNi45MDIzNCAzMi4xNzY4IDcuMTc1NzggMzIuMzEyM0M3LjQ0OTIyIDMyLjQ0NTEgNy42NjQwNiAzMi42Mjg3IDcuODIwMzEgMzIuODYzQzcuOTc5MTcgMzMuMDk3NCA4LjA1ODU5IDMzLjM2NTYgOC4wNTg1OSAzMy42Njc3Wk03LjMzMjAzIDMzLjY1MjFDNy4zMzIwMyAzMy40NDEyIDcuMjg2NDYgMzMuMjU1IDcuMTk1MzEgMzMuMDkzNUM3LjEwNDE3IDMyLjkyOTQgNi45NzY1NiAzMi44MDE4IDYuODEyNSAzMi43MTA3QzYuNjQ4NDQgMzIuNjE5NSA2LjQ1ODMzIDMyLjU3NCA2LjI0MjE5IDMyLjU3NEM2LjAyMDgzIDMyLjU3NCA1LjgyOTQzIDMyLjYxOTUgNS42Njc5NyAzMi43MTA3QzUuNTA5MTEgMzIuODAxOCA1LjM4NTQyIDMyLjkyOTQgNS4yOTY4OCAzMy4wOTM1QzUuMjA4MzMgMzMuMjU1IDUuMTY0MDYgMzMuNDQxMiA1LjE2NDA2IDMzLjY1MjFDNS4xNjQwNiAzMy44NzA4IDUuMjA3MDMgMzQuMDU4MyA1LjI5Mjk3IDM0LjIxNDZDNS4zODE1MSAzNC4zNjgyIDUuNTA2NTEgMzQuNDg2NyA1LjY2Nzk3IDM0LjU3MDFDNS44MzIwMyAzNC42NTA4IDYuMDI2MDQgMzQuNjkxMiA2LjI1IDM0LjY5MTJDNi40NzM5NiAzNC42OTEyIDYuNjY2NjcgMzQuNjUwOCA2LjgyODEyIDM0LjU3MDFDNi45ODk1OCAzNC40ODY3IDcuMTEzMjggMzQuMzY4MiA3LjE5OTIyIDM0LjIxNDZDNy4yODc3NiAzNC4wNTgzIDcuMzMyMDMgMzMuODcwOCA3LjMzMjAzIDMzLjY1MjFaTTcuOTI1NzggMzAuOTk5OEM3LjkyNTc4IDMxLjI3NTggNy44NTI4NiAzMS41MjQ1IDcuNzA3MDMgMzEuNzQ1OEM3LjU2MTIgMzEuOTY3MiA3LjM2MTk4IDMyLjE0MTcgNy4xMDkzOCAzMi4yNjkzQzYuODU2NzcgMzIuMzk2OSA2LjU3MDMxIDMyLjQ2MDcgNi4yNSAzMi40NjA3QzUuOTI0NDggMzIuNDYwNyA1LjYzNDExIDMyLjM5NjkgNS4zNzg5MSAzMi4yNjkzQzUuMTI2MyAzMi4xNDE3IDQuOTI4MzkgMzEuOTY3MiA0Ljc4NTE2IDMxLjc0NThDNC42NDE5MyAzMS41MjQ1IDQuNTcwMzEgMzEuMjc1OCA0LjU3MDMxIDMwLjk5OThDNC41NzAzMSAzMC42NjkgNC42NDE5MyAzMC4zODc4IDQuNzg1MTYgMzAuMTU2QzQuOTMwOTkgMjkuOTI0MiA1LjEzMDIxIDI5Ljc0NzIgNS4zODI4MSAyOS42MjQ4QzUuNjM1NDIgMjkuNTAyNCA1LjkyMzE4IDI5LjQ0MTIgNi4yNDYwOSAyOS40NDEyQzYuNTcxNjEgMjkuNDQxMiA2Ljg2MDY4IDI5LjUwMjQgNy4xMTMyOCAyOS42MjQ4QzcuMzY1ODkgMjkuNzQ3MiA3LjU2MzggMjkuOTI0MiA3LjcwNzAzIDMwLjE1NkM3Ljg1Mjg2IDMwLjM4NzggNy45MjU3OCAzMC42NjkgNy45MjU3OCAzMC45OTk4Wk03LjIwMzEyIDMxLjAxMTVDNy4yMDMxMiAzMC44MjE0IDcuMTYyNzYgMzAuNjUzNCA3LjA4MjAzIDMwLjUwNzZDNy4wMDEzIDMwLjM2MTcgNi44ODkzMiAzMC4yNDcyIDYuNzQ2MDkgMzAuMTYzOEM2LjYwMjg2IDMwLjA3NzkgNi40MzYyIDMwLjAzNDkgNi4yNDYwOSAzMC4wMzQ5QzYuMDU1OTkgMzAuMDM0OSA1Ljg4OTMyIDMwLjA3NTMgNS43NDYwOSAzMC4xNTZDNS42MDU0NyAzMC4yMzQxIDUuNDk0NzkgMzAuMzQ2MSA1LjQxNDA2IDMwLjQ5MTlDNS4zMzU5NCAzMC42Mzc4IDUuMjk2ODggMzAuODExIDUuMjk2ODggMzEuMDExNUM1LjI5Njg4IDMxLjIwNjggNS4zMzU5NCAzMS4zNzc0IDUuNDE0MDYgMzEuNTIzMkM1LjQ5NDc5IDMxLjY2OSA1LjYwNjc3IDMxLjc4MjMgNS43NSAzMS44NjNDNS44OTMyMyAzMS45NDM4IDYuMDU5OSAzMS45ODQxIDYuMjUgMzEuOTg0MUM2LjQ0MDEgMzEuOTg0MSA2LjYwNTQ3IDMxLjk0MzggNi43NDYwOSAzMS44NjNDNi44ODkzMiAzMS43ODIzIDcuMDAxMyAzMS42NjkgNy4wODIwMyAzMS41MjMyQzcuMTYyNzYgMzEuMzc3NCA3LjIwMzEyIDMxLjIwNjggNy4yMDMxMiAzMS4wMTE1Wk0xMi42NzUyIDMxLjkwOTlWMzIuNzc3MUMxMi42NzUyIDMzLjI0MzIgMTIuNjMzNSAzMy42MzY1IDEyLjU1MDIgMzMuOTU2OEMxMi40NjY4IDM0LjI3NzEgMTIuMzQ3IDM0LjUzNDkgMTIuMTkwOCAzNC43MzAyQzEyLjAzNDUgMzQuOTI1NSAxMS44NDU3IDM1LjA2NzUgMTEuNjI0NCAzNS4xNTZDMTEuNDA1NiAzNS4yNDE5IDExLjE1ODIgMzUuMjg0OSAxMC44ODIyIDM1LjI4NDlDMTAuNjYzNSAzNS4yODQ5IDEwLjQ2MTYgMzUuMjU3NiAxMC4yNzY3IDM1LjIwMjlDMTAuMDkxOCAzNS4xNDgyIDkuOTI1MTcgMzUuMDYxIDkuNzc2NzMgMzQuOTQxMkM5LjYzMDkgMzQuODE4OCA5LjUwNTkgMzQuNjU5OSA5LjQwMTczIDM0LjQ2NDZDOS4yOTc1NyAzNC4yNjkzIDkuMjE4MTQgMzQuMDMyMyA5LjE2MzQ1IDMzLjc1MzdDOS4xMDg3NyAzMy40NzUgOS4wODE0MiAzMy4xNDk1IDkuMDgxNDIgMzIuNzc3MVYzMS45MDk5QzkuMDgxNDIgMzEuNDQzOCA5LjEyMzA5IDMxLjA1MzEgOS4yMDY0MiAzMC43MzhDOS4yOTIzNiAzMC40MjI5IDkuNDEzNDUgMzAuMTcwMyA5LjU2OTcgMjkuOTgwMkM5LjcyNTk1IDI5Ljc4NzUgOS45MTM0NSAyOS42NDk1IDEwLjEzMjIgMjkuNTY2MkMxMC4zNTM2IDI5LjQ4MjggMTAuNjAxIDI5LjQ0MTIgMTAuODc0NCAyOS40NDEyQzExLjA5NTcgMjkuNDQxMiAxMS4yOTg5IDI5LjQ2ODUgMTEuNDgzOCAyOS41MjMyQzExLjY3MTMgMjkuNTc1MyAxMS44Mzc5IDI5LjY1OTkgMTEuOTgzOCAyOS43NzcxQzEyLjEyOTYgMjkuODkxNyAxMi4yNTMzIDMwLjA0NTMgMTIuMzU0OSAzMC4yMzhDMTIuNDU5IDMwLjQyODEgMTIuNTM4NSAzMC42NjEyIDEyLjU5MzEgMzAuOTM3M0MxMi42NDc4IDMxLjIxMzMgMTIuNjc1MiAzMS41Mzc1IDEyLjY3NTIgMzEuOTA5OVpNMTEuOTQ4NiAzMi44OTQzVjMxLjc4ODhDMTEuOTQ4NiAzMS41MzM2IDExLjkzMyAzMS4zMDk3IDExLjkwMTcgMzEuMTE2OUMxMS44NzMxIDMwLjkyMTYgMTEuODMwMSAzMC43NTUgMTEuNzcyOCAzMC42MTY5QzExLjcxNTUgMzAuNDc4OSAxMS42NDI2IDMwLjM2NjkgMTEuNTU0MSAzMC4yODFDMTEuNDY4MSAzMC4xOTUxIDExLjM2NzkgMzAuMTMyNiAxMS4yNTMzIDMwLjA5MzVDMTEuMTQxMyAzMC4wNTE4IDExLjAxNSAzMC4wMzEgMTAuODc0NCAzMC4wMzFDMTAuNzAyNSAzMC4wMzEgMTAuNTUwMiAzMC4wNjM2IDEwLjQxNzQgMzAuMTI4N0MxMC4yODQ1IDMwLjE5MTIgMTAuMTcyNiAzMC4yOTE0IDEwLjA4MTQgMzAuNDI5NEM5Ljk5Mjg4IDMwLjU2NzUgOS45MjUxNyAzMC43NDg1IDkuODc4MyAzMC45NzI0QzkuODMxNDIgMzEuMTk2NCA5LjgwNzk4IDMxLjQ2ODUgOS44MDc5OCAzMS43ODg4VjMyLjg5NDNDOS44MDc5OCAzMy4xNDk1IDkuODIyMzEgMzMuMzc0OCA5Ljg1MDk1IDMzLjU3MDFDOS44ODIyIDMzLjc2NTQgOS45Mjc3OCAzMy45MzQ3IDkuOTg3NjcgMzQuMDc3OUMxMC4wNDc2IDM0LjIxODUgMTAuMTIwNSAzNC4zMzQ0IDEwLjIwNjQgMzQuNDI1NUMxMC4yOTI0IDM0LjUxNjcgMTAuMzkxMyAzNC41ODQ0IDEwLjUwMzMgMzQuNjI4N0MxMC42MTc5IDM0LjY3MDMgMTAuNzQ0MiAzNC42OTEyIDEwLjg4MjIgMzQuNjkxMkMxMS4wNTkzIDM0LjY5MTIgMTEuMjE0MiAzNC42NTczIDExLjM0NyAzNC41ODk2QzExLjQ3OTkgMzQuNTIxOSAxMS41OTA1IDM0LjQxNjQgMTEuNjc5MSAzNC4yNzMyQzExLjc3MDIgMzQuMTI3NCAxMS44Mzc5IDMzLjk0MTIgMTEuODgyMiAzMy43MTQ2QzExLjkyNjUgMzMuNDg1NCAxMS45NDg2IDMzLjIxMiAxMS45NDg2IDMyLjg5NDNaTTEzLjY3NDYgMzAuOTEzOFYzMC42MTNDMTMuNjc0NiAzMC4zOTY5IDEzLjcyMTQgMzAuMjAwMyAxMy44MTUyIDMwLjAyMzJDMTMuOTA4OSAyOS44NDYxIDE0LjA0MzEgMjkuNzA0MiAxNC4yMTc1IDI5LjU5NzRDMTQuMzkyIDI5LjQ5MDYgMTQuNTk5IDI5LjQzNzMgMTQuODM4NiAyOS40MzczQzE1LjA4MzQgMjkuNDM3MyAxNS4yOTE4IDI5LjQ5MDYgMTUuNDYzNiAyOS41OTc0QzE1LjYzODEgMjkuNzA0MiAxNS43NzIyIDI5Ljg0NjEgMTUuODY2IDMwLjAyMzJDMTUuOTU5NyAzMC4yMDAzIDE2LjAwNjYgMzAuMzk2OSAxNi4wMDY2IDMwLjYxM1YzMC45MTM4QzE2LjAwNjYgMzEuMTI0OCAxNS45NTk3IDMxLjMxODggMTUuODY2IDMxLjQ5NThDMTUuNzc0OCAzMS42NzI5IDE1LjY0MiAzMS44MTQ5IDE1LjQ2NzUgMzEuOTIxNkMxNS4yOTU3IDMyLjAyODQgMTUuMDg4NiAzMi4wODE4IDE0Ljg0NjQgMzIuMDgxOEMxNC42MDQzIDMyLjA4MTggMTQuMzk0NiAzMi4wMjg0IDE0LjIxNzUgMzEuOTIxNkMxNC4wNDMxIDMxLjgxNDkgMTMuOTA4OSAzMS42NzI5IDEzLjgxNTIgMzEuNDk1OEMxMy43MjE0IDMxLjMxODggMTMuNjc0NiAzMS4xMjQ4IDEzLjY3NDYgMzAuOTEzOFpNMTQuMjE3NSAzMC42MTNWMzAuOTEzOEMxNC4yMTc1IDMxLjAzMzYgMTQuMjM5NyAzMS4xNDY5IDE0LjI4MzkgMzEuMjUzN0MxNC4zMzA4IDMxLjM2MDQgMTQuNDAxMSAzMS40NDc3IDE0LjQ5NDkgMzEuNTE1NEMxNC41ODg2IDMxLjU4MDUgMTQuNzA1OCAzMS42MTMgMTQuODQ2NCAzMS42MTNDMTQuOTg3MSAzMS42MTMgMTUuMTAyOSAzMS41ODA1IDE1LjE5NDEgMzEuNTE1NEMxNS4yODUyIDMxLjQ0NzcgMTUuMzUyOSAzMS4zNjA0IDE1LjM5NzIgMzEuMjUzN0MxNS40NDE1IDMxLjE0NjkgMTUuNDYzNiAzMS4wMzM2IDE1LjQ2MzYgMzAuOTEzOFYzMC42MTNDMTUuNDYzNiAzMC40OTA2IDE1LjQ0MDIgMzAuMzc2MSAxNS4zOTMzIDMwLjI2OTNDMTUuMzQ5IDMwLjE1OTkgMTUuMjggMzAuMDcyNyAxNS4xODYzIDMwLjAwNzZDMTUuMDk1MSAyOS45Mzk5IDE0Ljk3OTMgMjkuOTA2IDE0LjgzODYgMjkuOTA2QzE0LjcwMDYgMjkuOTA2IDE0LjU4NDcgMjkuOTM5OSAxNC40OTEgMzAuMDA3NkMxNC4zOTk4IDMwLjA3MjcgMTQuMzMwOCAzMC4xNTk5IDE0LjI4MzkgMzAuMjY5M0MxNC4yMzk3IDMwLjM3NjEgMTQuMjE3NSAzMC40OTA2IDE0LjIxNzUgMzAuNjEzWk0xNi40NDQxIDM0LjExNjlWMzMuODEyM0MxNi40NDQxIDMzLjU5ODcgMTYuNDkxIDMzLjQwMzQgMTYuNTg0NyAzMy4yMjYzQzE2LjY3ODUgMzMuMDQ5MiAxNi44MTI2IDMyLjkwNzMgMTYuOTg3MSAzMi44MDA1QzE3LjE2MTUgMzIuNjkzOCAxNy4zNjg2IDMyLjY0MDQgMTcuNjA4MiAzMi42NDA0QzE3Ljg1MjkgMzIuNjQwNCAxOC4wNjEzIDMyLjY5MzggMTguMjMzMiAzMi44MDA1QzE4LjQwNzYgMzIuOTA3MyAxOC41NDE4IDMzLjA0OTIgMTguNjM1NSAzMy4yMjYzQzE4LjcyOTMgMzMuNDAzNCAxOC43NzYxIDMzLjU5ODcgMTguNzc2MSAzMy44MTIzVjM0LjExNjlDMTguNzc2MSAzNC4zMzA1IDE4LjcyOTMgMzQuNTI1OCAxOC42MzU1IDM0LjcwMjlDMTguNTQ0NCAzNC44OCAxOC40MTE1IDM1LjAyMTkgMTguMjM3MSAzNS4xMjg3QzE4LjA2NTIgMzUuMjM1NCAxNy44NTgyIDM1LjI4ODggMTcuNjE2IDM1LjI4ODhDMTcuMzczOCAzNS4yODg4IDE3LjE2NTQgMzUuMjM1NCAxNi45OTEgMzUuMTI4N0MxNi44MTY1IDM1LjAyMTkgMTYuNjgxMSAzNC44OCAxNi41ODQ3IDM0LjcwMjlDMTYuNDkxIDM0LjUyNTggMTYuNDQ0MSAzNC4zMzA1IDE2LjQ0NDEgMzQuMTE2OVpNMTYuOTg3MSAzMy44MTIzVjM0LjExNjlDMTYuOTg3MSAzNC4yMzY3IDE3LjAwOTIgMzQuMzUxMyAxNy4wNTM1IDM0LjQ2MDdDMTcuMTAwMyAzNC41Njc1IDE3LjE3MDcgMzQuNjU0NyAxNy4yNjQ0IDM0LjcyMjRDMTcuMzU4MiAzNC43ODc1IDE3LjQ3NTMgMzQuODIwMSAxNy42MTYgMzQuODIwMUMxNy43NTY2IDM0LjgyMDEgMTcuODcyNSAzNC43ODc1IDE3Ljk2MzYgMzQuNzIyNEMxOC4wNTc0IDM0LjY1NDcgMTguMTI2NCAzNC41Njc1IDE4LjE3MDcgMzQuNDYwN0MxOC4yMTQ5IDM0LjM1MzkgMTguMjM3MSAzNC4yMzkzIDE4LjIzNzEgMzQuMTE2OVYzMy44MTIzQzE4LjIzNzEgMzMuNjg5OSAxOC4yMTM2IDMzLjU3NTMgMTguMTY2OCAzMy40Njg1QzE4LjEyMjUgMzMuMzYxNyAxOC4wNTM1IDMzLjI3NTggMTcuOTU5NyAzMy4yMTA3QzE3Ljg2ODYgMzMuMTQzIDE3Ljc1MTQgMzMuMTA5MSAxNy42MDgyIDMzLjEwOTFDMTcuNDcwMSAzMy4xMDkxIDE3LjM1NDMgMzMuMTQzIDE3LjI2MDUgMzMuMjEwN0MxNy4xNjk0IDMzLjI3NTggMTcuMTAwMyAzMy4zNjE3IDE3LjA1MzUgMzMuNDY4NUMxNy4wMDkyIDMzLjU3NTMgMTYuOTg3MSAzMy42ODk5IDE2Ljk4NzEgMzMuODEyM1pNMTcuNzg3OCAzMC4zMjc5TDE1LjAxMDUgMzQuNzczMkwxNC42MDQzIDM0LjUxNTRMMTcuMzgxNiAzMC4wNzAxTDE3Ljc4NzggMzAuMzI3OVoiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuNTQiLz4KPHBhdGggZD0iTTcuMjQ2MDkgNTcuNzE4M0g3LjMwODU5VjU4LjMzMTVINy4yNDYwOUM2Ljg2MzI4IDU4LjMzMTUgNi41NDI5NyA1OC4zOTQgNi4yODUxNiA1OC41MTlDNi4wMjczNCA1OC42NDE0IDUuODIyOTIgNTguODA2OCA1LjY3MTg4IDU5LjAxNTFDNS41MjA4MyA1OS4yMjA5IDUuNDExNDYgNTkuNDUyNiA1LjM0Mzc1IDU5LjcxMDRDNS4yNzg2NSA1OS45NjgzIDUuMjQ2MDkgNjAuMjMgNS4yNDYwOSA2MC40OTU2VjYxLjMzMTVDNS4yNDYwOSA2MS41ODQxIDUuMjc2MDQgNjEuODA4MSA1LjMzNTk0IDYyLjAwMzRDNS4zOTU4MyA2Mi4xOTYxIDUuNDc3ODYgNjIuMzU4OSA1LjU4MjAzIDYyLjQ5MTdDNS42ODYyIDYyLjYyNDUgNS44MDMzOSA2Mi43MjQ4IDUuOTMzNTkgNjIuNzkyNUM2LjA2NjQxIDYyLjg2MDIgNi4yMDQ0MyA2Mi44OTQgNi4zNDc2NiA2Mi44OTRDNi41MTQzMiA2Mi44OTQgNi42NjI3NiA2Mi44NjI4IDYuNzkyOTcgNjIuODAwM0M2LjkyMzE4IDYyLjczNTIgNy4wMzI1NSA2Mi42NDUzIDcuMTIxMDkgNjIuNTMwOEM3LjIxMjI0IDYyLjQxMzYgNy4yODEyNSA2Mi4yNzU2IDcuMzI4MTIgNjIuMTE2N0M3LjM3NSA2MS45NTc4IDcuMzk4NDQgNjEuNzgzNCA3LjM5ODQ0IDYxLjU5MzNDNy4zOTg0NCA2MS40MjQgNy4zNzc2IDYxLjI2MTIgNy4zMzU5NCA2MS4xMDVDNy4yOTQyNyA2MC45NDYxIDcuMjMwNDcgNjAuODA1NSA3LjE0NDUzIDYwLjY4MzFDNy4wNTg1OSA2MC41NTgxIDYuOTUwNTIgNjAuNDYwNCA2LjgyMDMxIDYwLjM5MDFDNi42OTI3MSA2MC4zMTcyIDYuNTQwMzYgNjAuMjgwOCA2LjM2MzI4IDYwLjI4MDhDNi4xNjI3NiA2MC4yODA4IDUuOTc1MjYgNjAuMzMwMiA1LjgwMDc4IDYwLjQyOTJDNS42Mjg5MSA2MC41MjU2IDUuNDg2OTggNjAuNjUzMiA1LjM3NSA2MC44MTJDNS4yNjU2MiA2MC45NjgzIDUuMjAzMTIgNjEuMTM4OCA1LjE4NzUgNjEuMzIzN0w0LjgwNDY5IDYxLjMxOThDNC44NDExNSA2MS4wMjgyIDQuOTA4ODUgNjAuNzc5NSA1LjAwNzgxIDYwLjU3MzdDNS4xMDkzOCA2MC4zNjU0IDUuMjM0MzggNjAuMTk2MSA1LjM4MjgxIDYwLjA2NTlDNS41MzM4NSA1OS45MzMxIDUuNzAxODIgNTkuODM2OCA1Ljg4NjcyIDU5Ljc3NjlDNi4wNzQyMiA1OS43MTQ0IDYuMjcyMTQgNTkuNjgzMSA2LjQ4MDQ3IDU5LjY4MzFDNi43NjQzMiA1OS42ODMxIDcuMDA5MTEgNTkuNzM2NSA3LjIxNDg0IDU5Ljg0MzNDNy40MjA1NyA1OS45NSA3LjU4OTg0IDYwLjA5MzMgNy43MjI2NiA2MC4yNzI5QzcuODU1NDcgNjAuNDUgNy45NTMxMiA2MC42NTA2IDguMDE1NjIgNjAuODc0NUM4LjA4MDczIDYxLjA5NTkgOC4xMTMyOCA2MS4zMjM3IDguMTEzMjggNjEuNTU4MUM4LjExMzI4IDYxLjgyNjMgOC4wNzU1MiA2Mi4wNzc2IDggNjIuMzEyQzcuOTI0NDggNjIuNTQ2NCA3LjgxMTIgNjIuNzUyMSA3LjY2MDE2IDYyLjkyOTJDNy41MTE3MiA2My4xMDYzIDcuMzI4MTIgNjMuMjQ0MyA3LjEwOTM4IDYzLjM0MzNDNi44OTA2MiA2My40NDIyIDYuNjM2NzIgNjMuNDkxNyA2LjM0NzY2IDYzLjQ5MTdDNi4wNDAzNiA2My40OTE3IDUuNzcyMTQgNjMuNDI5MiA1LjU0Mjk3IDYzLjMwNDJDNS4zMTM4IDYzLjE3NjYgNS4xMjM3IDYzLjAwNzMgNC45NzI2NiA2Mi43OTY0QzQuODIxNjEgNjIuNTg1NCA0LjcwODMzIDYyLjM1MTEgNC42MzI4MSA2Mi4wOTMzQzQuNTU3MjkgNjEuODM1NCA0LjUxOTUzIDYxLjU3MzcgNC41MTk1MyA2MS4zMDgxVjYwLjk2ODNDNC41MTk1MyA2MC41NjcyIDQuNTU5OSA2MC4xNzQgNC42NDA2MiA1OS43ODg2QzQuNzIxMzUgNTkuNDAzMiA0Ljg2MDY4IDU5LjA1NDIgNS4wNTg1OSA1OC43NDE3QzUuMjU5MTEgNTguNDI5MiA1LjUzNjQ2IDU4LjE4MDUgNS44OTA2MiA1Ny45OTU2QzYuMjQ0NzkgNTcuODEwNyA2LjY5NjYxIDU3LjcxODMgNy4yNDYwOSA1Ny43MTgzWk0xMi42NzUyIDYwLjExNjdWNjAuOTgzOUMxMi42NzUyIDYxLjQ1IDEyLjYzMzUgNjEuODQzMyAxMi41NTAyIDYyLjE2MzZDMTIuNDY2OCA2Mi40ODM5IDEyLjM0NyA2Mi43NDE3IDEyLjE5MDggNjIuOTM3QzEyLjAzNDUgNjMuMTMyMyAxMS44NDU3IDYzLjI3NDMgMTEuNjI0NCA2My4zNjI4QzExLjQwNTYgNjMuNDQ4NyAxMS4xNTgyIDYzLjQ5MTcgMTAuODgyMiA2My40OTE3QzEwLjY2MzUgNjMuNDkxNyAxMC40NjE2IDYzLjQ2NDQgMTAuMjc2NyA2My40MDk3QzEwLjA5MTggNjMuMzU1IDkuOTI1MTcgNjMuMjY3NyA5Ljc3NjczIDYzLjE0NzlDOS42MzA5IDYzLjAyNTYgOS41MDU5IDYyLjg2NjcgOS40MDE3MyA2Mi42NzE0QzkuMjk3NTcgNjIuNDc2MSA5LjIxODE0IDYyLjIzOTEgOS4xNjM0NSA2MS45NjA0QzkuMTA4NzcgNjEuNjgxOCA5LjA4MTQyIDYxLjM1NjMgOS4wODE0MiA2MC45ODM5VjYwLjExNjdDOS4wODE0MiA1OS42NTA2IDkuMTIzMDkgNTkuMjU5OSA5LjIwNjQyIDU4Ljk0NDhDOS4yOTIzNiA1OC42Mjk3IDkuNDEzNDUgNTguMzc3MSA5LjU2OTcgNTguMTg3QzkuNzI1OTUgNTcuOTk0MyA5LjkxMzQ1IDU3Ljg1NjMgMTAuMTMyMiA1Ny43NzI5QzEwLjM1MzYgNTcuNjg5NiAxMC42MDEgNTcuNjQ3OSAxMC44NzQ0IDU3LjY0NzlDMTEuMDk1NyA1Ny42NDc5IDExLjI5ODkgNTcuNjc1MyAxMS40ODM4IDU3LjczQzExLjY3MTMgNTcuNzgyMSAxMS44Mzc5IDU3Ljg2NjcgMTEuOTgzOCA1Ny45ODM5QzEyLjEyOTYgNTguMDk4NSAxMi4yNTMzIDU4LjI1MjEgMTIuMzU0OSA1OC40NDQ4QzEyLjQ1OSA1OC42MzQ5IDEyLjUzODUgNTguODY4IDEyLjU5MzEgNTkuMTQ0QzEyLjY0NzggNTkuNDIwMSAxMi42NzUyIDU5Ljc0NDMgMTIuNjc1MiA2MC4xMTY3Wk0xMS45NDg2IDYxLjEwMTFWNTkuOTk1NkMxMS45NDg2IDU5Ljc0MDQgMTEuOTMzIDU5LjUxNjQgMTEuOTAxNyA1OS4zMjM3QzExLjg3MzEgNTkuMTI4NCAxMS44MzAxIDU4Ljk2MTggMTEuNzcyOCA1OC44MjM3QzExLjcxNTUgNTguNjg1NyAxMS42NDI2IDU4LjU3MzcgMTEuNTU0MSA1OC40ODc4QzExLjQ2ODEgNTguNDAxOSAxMS4zNjc5IDU4LjMzOTQgMTEuMjUzMyA1OC4zMDAzQzExLjE0MTMgNTguMjU4NiAxMS4wMTUgNTguMjM3OCAxMC44NzQ0IDU4LjIzNzhDMTAuNzAyNSA1OC4yMzc4IDEwLjU1MDIgNTguMjcwMyAxMC40MTc0IDU4LjMzNTRDMTAuMjg0NSA1OC4zOTc5IDEwLjE3MjYgNTguNDk4MiAxMC4wODE0IDU4LjYzNjJDOS45OTI4OCA1OC43NzQzIDkuOTI1MTcgNTguOTU1MiA5Ljg3ODMgNTkuMTc5MkM5LjgzMTQyIDU5LjQwMzIgOS44MDc5OCA1OS42NzUzIDkuODA3OTggNTkuOTk1NlY2MS4xMDExQzkuODA3OTggNjEuMzU2MyA5LjgyMjMxIDYxLjU4MTUgOS44NTA5NSA2MS43NzY5QzkuODgyMiA2MS45NzIyIDkuOTI3NzggNjIuMTQxNCA5Ljk4NzY3IDYyLjI4NDdDMTAuMDQ3NiA2Mi40MjUzIDEwLjEyMDUgNjIuNTQxMiAxMC4yMDY0IDYyLjYzMjNDMTAuMjkyNCA2Mi43MjM1IDEwLjM5MTMgNjIuNzkxMiAxMC41MDMzIDYyLjgzNTRDMTAuNjE3OSA2Mi44NzcxIDEwLjc0NDIgNjIuODk3OSAxMC44ODIyIDYyLjg5NzlDMTEuMDU5MyA2Mi44OTc5IDExLjIxNDIgNjIuODY0MSAxMS4zNDcgNjIuNzk2NEMxMS40Nzk5IDYyLjcyODcgMTEuNTkwNSA2Mi42MjMyIDExLjY3OTEgNjIuNDhDMTEuNzcwMiA2Mi4zMzQxIDExLjgzNzkgNjIuMTQ3OSAxMS44ODIyIDYxLjkyMTRDMTEuOTI2NSA2MS42OTIyIDExLjk0ODYgNjEuNDE4OCAxMS45NDg2IDYxLjEwMTFaTTEzLjY3NDYgNTkuMTIwNlY1OC44MTk4QzEzLjY3NDYgNTguNjAzNyAxMy43MjE0IDU4LjQwNzEgMTMuODE1MiA1OC4yM0MxMy45MDg5IDU4LjA1MjkgMTQuMDQzMSA1Ny45MTEgMTQuMjE3NSA1Ny44MDQyQzE0LjM5MiA1Ny42OTc0IDE0LjU5OSA1Ny42NDQgMTQuODM4NiA1Ny42NDRDMTUuMDgzNCA1Ny42NDQgMTUuMjkxOCA1Ny42OTc0IDE1LjQ2MzYgNTcuODA0MkMxNS42MzgxIDU3LjkxMSAxNS43NzIyIDU4LjA1MjkgMTUuODY2IDU4LjIzQzE1Ljk1OTcgNTguNDA3MSAxNi4wMDY2IDU4LjYwMzcgMTYuMDA2NiA1OC44MTk4VjU5LjEyMDZDMTYuMDA2NiA1OS4zMzE1IDE1Ljk1OTcgNTkuNTI1NiAxNS44NjYgNTkuNzAyNkMxNS43NzQ4IDU5Ljg3OTcgMTUuNjQyIDYwLjAyMTYgMTUuNDY3NSA2MC4xMjg0QzE1LjI5NTcgNjAuMjM1MiAxNS4wODg2IDYwLjI4ODYgMTQuODQ2NCA2MC4yODg2QzE0LjYwNDMgNjAuMjg4NiAxNC4zOTQ2IDYwLjIzNTIgMTQuMjE3NSA2MC4xMjg0QzE0LjA0MzEgNjAuMDIxNiAxMy45MDg5IDU5Ljg3OTcgMTMuODE1MiA1OS43MDI2QzEzLjcyMTQgNTkuNTI1NiAxMy42NzQ2IDU5LjMzMTUgMTMuNjc0NiA1OS4xMjA2Wk0xNC4yMTc1IDU4LjgxOThWNTkuMTIwNkMxNC4yMTc1IDU5LjI0MDQgMTQuMjM5NyA1OS4zNTM3IDE0LjI4MzkgNTkuNDYwNEMxNC4zMzA4IDU5LjU2NzIgMTQuNDAxMSA1OS42NTQ1IDE0LjQ5NDkgNTkuNzIyMkMxNC41ODg2IDU5Ljc4NzMgMTQuNzA1OCA1OS44MTk4IDE0Ljg0NjQgNTkuODE5OEMxNC45ODcxIDU5LjgxOTggMTUuMTAyOSA1OS43ODczIDE1LjE5NDEgNTkuNzIyMkMxNS4yODUyIDU5LjY1NDUgMTUuMzUyOSA1OS41NjcyIDE1LjM5NzIgNTkuNDYwNEMxNS40NDE1IDU5LjM1MzcgMTUuNDYzNiA1OS4yNDA0IDE1LjQ2MzYgNTkuMTIwNlY1OC44MTk4QzE1LjQ2MzYgNTguNjk3NCAxNS40NDAyIDU4LjU4MjggMTUuMzkzMyA1OC40NzYxQzE1LjM0OSA1OC4zNjY3IDE1LjI4IDU4LjI3OTUgMTUuMTg2MyA1OC4yMTQ0QzE1LjA5NTEgNTguMTQ2NiAxNC45NzkzIDU4LjExMjggMTQuODM4NiA1OC4xMTI4QzE0LjcwMDYgNTguMTEyOCAxNC41ODQ3IDU4LjE0NjYgMTQuNDkxIDU4LjIxNDRDMTQuMzk5OCA1OC4yNzk1IDE0LjMzMDggNTguMzY2NyAxNC4yODM5IDU4LjQ3NjFDMTQuMjM5NyA1OC41ODI4IDE0LjIxNzUgNTguNjk3NCAxNC4yMTc1IDU4LjgxOThaTTE2LjQ0NDEgNjIuMzIzN1Y2Mi4wMTlDMTYuNDQ0MSA2MS44MDU1IDE2LjQ5MSA2MS42MTAyIDE2LjU4NDcgNjEuNDMzMUMxNi42Nzg1IDYxLjI1NiAxNi44MTI2IDYxLjExNDEgMTYuOTg3MSA2MS4wMDczQzE3LjE2MTUgNjAuOTAwNiAxNy4zNjg2IDYwLjg0NzIgMTcuNjA4MiA2MC44NDcyQzE3Ljg1MjkgNjAuODQ3MiAxOC4wNjEzIDYwLjkwMDYgMTguMjMzMiA2MS4wMDczQzE4LjQwNzYgNjEuMTE0MSAxOC41NDE4IDYxLjI1NiAxOC42MzU1IDYxLjQzMzFDMTguNzI5MyA2MS42MTAyIDE4Ljc3NjEgNjEuODA1NSAxOC43NzYxIDYyLjAxOVY2Mi4zMjM3QzE4Ljc3NjEgNjIuNTM3MyAxOC43MjkzIDYyLjczMjYgMTguNjM1NSA2Mi45MDk3QzE4LjU0NDQgNjMuMDg2OCAxOC40MTE1IDYzLjIyODcgMTguMjM3MSA2My4zMzU0QzE4LjA2NTIgNjMuNDQyMiAxNy44NTgyIDYzLjQ5NTYgMTcuNjE2IDYzLjQ5NTZDMTcuMzczOCA2My40OTU2IDE3LjE2NTQgNjMuNDQyMiAxNi45OTEgNjMuMzM1NEMxNi44MTY1IDYzLjIyODcgMTYuNjgxMSA2My4wODY4IDE2LjU4NDcgNjIuOTA5N0MxNi40OTEgNjIuNzMyNiAxNi40NDQxIDYyLjUzNzMgMTYuNDQ0MSA2Mi4zMjM3Wk0xNi45ODcxIDYyLjAxOVY2Mi4zMjM3QzE2Ljk4NzEgNjIuNDQzNSAxNy4wMDkyIDYyLjU1ODEgMTcuMDUzNSA2Mi42Njc1QzE3LjEwMDMgNjIuNzc0MyAxNy4xNzA3IDYyLjg2MTUgMTcuMjY0NCA2Mi45MjkyQzE3LjM1ODIgNjIuOTk0MyAxNy40NzUzIDYzLjAyNjkgMTcuNjE2IDYzLjAyNjlDMTcuNzU2NiA2My4wMjY5IDE3Ljg3MjUgNjIuOTk0MyAxNy45NjM2IDYyLjkyOTJDMTguMDU3NCA2Mi44NjE1IDE4LjEyNjQgNjIuNzc0MyAxOC4xNzA3IDYyLjY2NzVDMTguMjE0OSA2Mi41NjA3IDE4LjIzNzEgNjIuNDQ2MSAxOC4yMzcxIDYyLjMyMzdWNjIuMDE5QzE4LjIzNzEgNjEuODk2NiAxOC4yMTM2IDYxLjc4MjEgMTguMTY2OCA2MS42NzUzQzE4LjEyMjUgNjEuNTY4NSAxOC4wNTM1IDYxLjQ4MjYgMTcuOTU5NyA2MS40MTc1QzE3Ljg2ODYgNjEuMzQ5OCAxNy43NTE0IDYxLjMxNTkgMTcuNjA4MiA2MS4zMTU5QzE3LjQ3MDEgNjEuMzE1OSAxNy4zNTQzIDYxLjM0OTggMTcuMjYwNSA2MS40MTc1QzE3LjE2OTQgNjEuNDgyNiAxNy4xMDAzIDYxLjU2ODUgMTcuMDUzNSA2MS42NzUzQzE3LjAwOTIgNjEuNzgyMSAxNi45ODcxIDYxLjg5NjYgMTYuOTg3MSA2Mi4wMTlaTTE3Ljc4NzggNTguNTM0N0wxNS4wMTA1IDYyLjk4TDE0LjYwNDMgNjIuNzIyMkwxNy4zODE2IDU4LjI3NjlMMTcuNzg3OCA1OC41MzQ3WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNOC4zMTY0MSA4OS43MDYzVjkwLjNINC4yMDcwM1Y4OS44NzQzTDYuNzUzOTEgODUuOTMyOUg3LjM0Mzc1TDYuNzEwOTQgODcuMDczNUw1LjAyNzM0IDg5LjcwNjNIOC4zMTY0MVpNNy41MjM0NCA4NS45MzI5VjkxLjYyMDRINi44MDA3OFY4NS45MzI5SDcuNTIzNDRaTTEyLjY3NTIgODguMzIzNVY4OS4xOTA3QzEyLjY3NTIgODkuNjU2OCAxMi42MzM1IDkwLjA1IDEyLjU1MDIgOTAuMzcwNEMxMi40NjY4IDkwLjY5MDcgMTIuMzQ3IDkwLjk0ODUgMTIuMTkwOCA5MS4xNDM4QzEyLjAzNDUgOTEuMzM5MSAxMS44NDU3IDkxLjQ4MSAxMS42MjQ0IDkxLjU2OTZDMTEuNDA1NiA5MS42NTU1IDExLjE1ODIgOTEuNjk4NSAxMC44ODIyIDkxLjY5ODVDMTAuNjYzNSA5MS42OTg1IDEwLjQ2MTYgOTEuNjcxMSAxMC4yNzY3IDkxLjYxNjVDMTAuMDkxOCA5MS41NjE4IDkuOTI1MTcgOTEuNDc0NSA5Ljc3NjczIDkxLjM1NDdDOS42MzA5IDkxLjIzMjMgOS41MDU5IDkxLjA3MzUgOS40MDE3MyA5MC44NzgyQzkuMjk3NTcgOTAuNjgyOSA5LjIxODE0IDkwLjQ0NTkgOS4xNjM0NSA5MC4xNjcyQzkuMTA4NzcgODkuODg4NiA5LjA4MTQyIDg5LjU2MzEgOS4wODE0MiA4OS4xOTA3Vjg4LjMyMzVDOS4wODE0MiA4Ny44NTczIDkuMTIzMDkgODcuNDY2NyA5LjIwNjQyIDg3LjE1MTZDOS4yOTIzNiA4Ni44MzY1IDkuNDEzNDUgODYuNTgzOSA5LjU2OTcgODYuMzkzOEM5LjcyNTk1IDg2LjIwMTEgOS45MTM0NSA4Ni4wNjMxIDEwLjEzMjIgODUuOTc5N0MxMC4zNTM2IDg1Ljg5NjQgMTAuNjAxIDg1Ljg1NDcgMTAuODc0NCA4NS44NTQ3QzExLjA5NTcgODUuODU0NyAxMS4yOTg5IDg1Ljg4MjEgMTEuNDgzOCA4NS45MzY4QzExLjY3MTMgODUuOTg4OSAxMS44Mzc5IDg2LjA3MzUgMTEuOTgzOCA4Ni4xOTA3QzEyLjEyOTYgODYuMzA1MyAxMi4yNTMzIDg2LjQ1ODkgMTIuMzU0OSA4Ni42NTE2QzEyLjQ1OSA4Ni44NDE3IDEyLjUzODUgODcuMDc0OCAxMi41OTMxIDg3LjM1MDhDMTIuNjQ3OCA4Ny42MjY5IDEyLjY3NTIgODcuOTUxMSAxMi42NzUyIDg4LjMyMzVaTTExLjk0ODYgODkuMzA3OVY4OC4yMDI0QzExLjk0ODYgODcuOTQ3MiAxMS45MzMgODcuNzIzMiAxMS45MDE3IDg3LjUzMDVDMTEuODczMSA4Ny4zMzUyIDExLjgzMDEgODcuMTY4NSAxMS43NzI4IDg3LjAzMDVDMTEuNzE1NSA4Ni44OTI1IDExLjY0MjYgODYuNzgwNSAxMS41NTQxIDg2LjY5NDZDMTEuNDY4MSA4Ni42MDg2IDExLjM2NzkgODYuNTQ2MSAxMS4yNTMzIDg2LjUwNzFDMTEuMTQxMyA4Ni40NjU0IDExLjAxNSA4Ni40NDQ2IDEwLjg3NDQgODYuNDQ0NkMxMC43MDI1IDg2LjQ0NDYgMTAuNTUwMiA4Ni40NzcxIDEwLjQxNzQgODYuNTQyMkMxMC4yODQ1IDg2LjYwNDcgMTAuMTcyNiA4Ni43MDUgMTAuMDgxNCA4Ni44NDNDOS45OTI4OCA4Ni45ODEgOS45MjUxNyA4Ny4xNjIgOS44NzgzIDg3LjM4NkM5LjgzMTQyIDg3LjYwOTkgOS44MDc5OCA4Ny44ODIxIDkuODA3OTggODguMjAyNFY4OS4zMDc5QzkuODA3OTggODkuNTYzMSA5LjgyMjMxIDg5Ljc4ODMgOS44NTA5NSA4OS45ODM2QzkuODgyMiA5MC4xNzkgOS45Mjc3OCA5MC4zNDgyIDkuOTg3NjcgOTAuNDkxNUMxMC4wNDc2IDkwLjYzMjEgMTAuMTIwNSA5MC43NDggMTAuMjA2NCA5MC44MzkxQzEwLjI5MjQgOTAuOTMwMyAxMC4zOTEzIDkwLjk5OCAxMC41MDMzIDkxLjA0MjJDMTAuNjE3OSA5MS4wODM5IDEwLjc0NDIgOTEuMTA0NyAxMC44ODIyIDkxLjEwNDdDMTEuMDU5MyA5MS4xMDQ3IDExLjIxNDIgOTEuMDcwOSAxMS4zNDcgOTEuMDAzMkMxMS40Nzk5IDkwLjkzNTUgMTEuNTkwNSA5MC44MyAxMS42NzkxIDkwLjY4NjhDMTEuNzcwMiA5MC41NDA5IDExLjgzNzkgOTAuMzU0NyAxMS44ODIyIDkwLjEyODJDMTEuOTI2NSA4OS44OTkgMTEuOTQ4NiA4OS42MjU2IDExLjk0ODYgODkuMzA3OVpNMTMuNjc0NiA4Ny4zMjc0Vjg3LjAyNjZDMTMuNjc0NiA4Ni44MTA1IDEzLjcyMTQgODYuNjEzOSAxMy44MTUyIDg2LjQzNjhDMTMuOTA4OSA4Ni4yNTk3IDE0LjA0MzEgODYuMTE3OCAxNC4yMTc1IDg2LjAxMUMxNC4zOTIgODUuOTA0MiAxNC41OTkgODUuODUwOCAxNC44Mzg2IDg1Ljg1MDhDMTUuMDgzNCA4NS44NTA4IDE1LjI5MTggODUuOTA0MiAxNS40NjM2IDg2LjAxMUMxNS42MzgxIDg2LjExNzggMTUuNzcyMiA4Ni4yNTk3IDE1Ljg2NiA4Ni40MzY4QzE1Ljk1OTcgODYuNjEzOSAxNi4wMDY2IDg2LjgxMDUgMTYuMDA2NiA4Ny4wMjY2Vjg3LjMyNzRDMTYuMDA2NiA4Ny41MzgzIDE1Ljk1OTcgODcuNzMyMyAxNS44NjYgODcuOTA5NEMxNS43NzQ4IDg4LjA4NjUgMTUuNjQyIDg4LjIyODQgMTUuNDY3NSA4OC4zMzUyQzE1LjI5NTcgODguNDQyIDE1LjA4ODYgODguNDk1NCAxNC44NDY0IDg4LjQ5NTRDMTQuNjA0MyA4OC40OTU0IDE0LjM5NDYgODguNDQyIDE0LjIxNzUgODguMzM1MkMxNC4wNDMxIDg4LjIyODQgMTMuOTA4OSA4OC4wODY1IDEzLjgxNTIgODcuOTA5NEMxMy43MjE0IDg3LjczMjMgMTMuNjc0NiA4Ny41MzgzIDEzLjY3NDYgODcuMzI3NFpNMTQuMjE3NSA4Ny4wMjY2Vjg3LjMyNzRDMTQuMjE3NSA4Ny40NDcyIDE0LjIzOTcgODcuNTYwNSAxNC4yODM5IDg3LjY2NzJDMTQuMzMwOCA4Ny43NzQgMTQuNDAxMSA4Ny44NjEyIDE0LjQ5NDkgODcuOTI5QzE0LjU4ODYgODcuOTk0MSAxNC43MDU4IDg4LjAyNjYgMTQuODQ2NCA4OC4wMjY2QzE0Ljk4NzEgODguMDI2NiAxNS4xMDI5IDg3Ljk5NDEgMTUuMTk0MSA4Ny45MjlDMTUuMjg1MiA4Ny44NjEyIDE1LjM1MjkgODcuNzc0IDE1LjM5NzIgODcuNjY3MkMxNS40NDE1IDg3LjU2MDUgMTUuNDYzNiA4Ny40NDcyIDE1LjQ2MzYgODcuMzI3NFY4Ny4wMjY2QzE1LjQ2MzYgODYuOTA0MiAxNS40NDAyIDg2Ljc4OTYgMTUuMzkzMyA4Ni42ODI5QzE1LjM0OSA4Ni41NzM1IDE1LjI4IDg2LjQ4NjIgMTUuMTg2MyA4Ni40MjExQzE1LjA5NTEgODYuMzUzNCAxNC45NzkzIDg2LjMxOTYgMTQuODM4NiA4Ni4zMTk2QzE0LjcwMDYgODYuMzE5NiAxNC41ODQ3IDg2LjM1MzQgMTQuNDkxIDg2LjQyMTFDMTQuMzk5OCA4Ni40ODYyIDE0LjMzMDggODYuNTczNSAxNC4yODM5IDg2LjY4MjlDMTQuMjM5NyA4Ni43ODk2IDE0LjIxNzUgODYuOTA0MiAxNC4yMTc1IDg3LjAyNjZaTTE2LjQ0NDEgOTAuNTMwNVY5MC4yMjU4QzE2LjQ0NDEgOTAuMDEyMyAxNi40OTEgODkuODE3IDE2LjU4NDcgODkuNjM5OUMxNi42Nzg1IDg5LjQ2MjggMTYuODEyNiA4OS4zMjA5IDE2Ljk4NzEgODkuMjE0MUMxNy4xNjE1IDg5LjEwNzMgMTcuMzY4NiA4OS4wNTQgMTcuNjA4MiA4OS4wNTRDMTcuODUyOSA4OS4wNTQgMTguMDYxMyA4OS4xMDczIDE4LjIzMzIgODkuMjE0MUMxOC40MDc2IDg5LjMyMDkgMTguNTQxOCA4OS40NjI4IDE4LjYzNTUgODkuNjM5OUMxOC43MjkzIDg5LjgxNyAxOC43NzYxIDkwLjAxMjMgMTguNzc2MSA5MC4yMjU4VjkwLjUzMDVDMTguNzc2MSA5MC43NDQxIDE4LjcyOTMgOTAuOTM5NCAxOC42MzU1IDkxLjExNjVDMTguNTQ0NCA5MS4yOTM1IDE4LjQxMTUgOTEuNDM1NSAxOC4yMzcxIDkxLjU0MjJDMTguMDY1MiA5MS42NDkgMTcuODU4MiA5MS43MDI0IDE3LjYxNiA5MS43MDI0QzE3LjM3MzggOTEuNzAyNCAxNy4xNjU0IDkxLjY0OSAxNi45OTEgOTEuNTQyMkMxNi44MTY1IDkxLjQzNTUgMTYuNjgxMSA5MS4yOTM1IDE2LjU4NDcgOTEuMTE2NUMxNi40OTEgOTAuOTM5NCAxNi40NDQxIDkwLjc0NDEgMTYuNDQ0MSA5MC41MzA1Wk0xNi45ODcxIDkwLjIyNThWOTAuNTMwNUMxNi45ODcxIDkwLjY1MDMgMTcuMDA5MiA5MC43NjQ5IDE3LjA1MzUgOTAuODc0M0MxNy4xMDAzIDkwLjk4MSAxNy4xNzA3IDkxLjA2ODMgMTcuMjY0NCA5MS4xMzZDMTcuMzU4MiA5MS4yMDExIDE3LjQ3NTMgOTEuMjMzNiAxNy42MTYgOTEuMjMzNkMxNy43NTY2IDkxLjIzMzYgMTcuODcyNSA5MS4yMDExIDE3Ljk2MzYgOTEuMTM2QzE4LjA1NzQgOTEuMDY4MyAxOC4xMjY0IDkwLjk4MSAxOC4xNzA3IDkwLjg3NDNDMTguMjE0OSA5MC43Njc1IDE4LjIzNzEgOTAuNjUyOSAxOC4yMzcxIDkwLjUzMDVWOTAuMjI1OEMxOC4yMzcxIDkwLjEwMzQgMTguMjEzNiA4OS45ODg5IDE4LjE2NjggODkuODgyMUMxOC4xMjI1IDg5Ljc3NTMgMTguMDUzNSA4OS42ODk0IDE3Ljk1OTcgODkuNjI0M0MxNy44Njg2IDg5LjU1NjYgMTcuNzUxNCA4OS41MjI3IDE3LjYwODIgODkuNTIyN0MxNy40NzAxIDg5LjUyMjcgMTcuMzU0MyA4OS41NTY2IDE3LjI2MDUgODkuNjI0M0MxNy4xNjk0IDg5LjY4OTQgMTcuMTAwMyA4OS43NzUzIDE3LjA1MzUgODkuODgyMUMxNy4wMDkyIDg5Ljk4ODkgMTYuOTg3MSA5MC4xMDM0IDE2Ljk4NzEgOTAuMjI1OFpNMTcuNzg3OCA4Ni43NDE1TDE1LjAxMDUgOTEuMTg2OEwxNC42MDQzIDkwLjkyOUwxNy4zODE2IDg2LjQ4MzZMMTcuNzg3OCA4Ni43NDE1WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNOC4xOTkyMiAxMTkuMjMzVjExOS44MjdINC40NzY1NlYxMTkuMzA4TDYuMzM5ODQgMTE3LjIzM0M2LjU2OTAxIDExNi45NzggNi43NDYwOSAxMTYuNzYyIDYuODcxMDkgMTE2LjU4NUM2Ljk5ODcgMTE2LjQwNSA3LjA4NzI0IDExNi4yNDUgNy4xMzY3MiAxMTYuMTA0QzcuMTg4OCAxMTUuOTYxIDcuMjE0ODQgMTE1LjgxNSA3LjIxNDg0IDExNS42NjdDNy4yMTQ4NCAxMTUuNDc5IDcuMTc1NzggMTE1LjMxIDcuMDk3NjYgMTE1LjE1OUM3LjAyMjE0IDExNS4wMDYgNi45MTAxNiAxMTQuODgzIDYuNzYxNzIgMTE0Ljc5MkM2LjYxMzI4IDExNC43MDEgNi40MzM1OSAxMTQuNjU1IDYuMjIyNjYgMTE0LjY1NUM1Ljk3MDA1IDExNC42NTUgNS43NTkxMSAxMTQuNzA1IDUuNTg5ODQgMTE0LjgwNEM1LjQyMzE4IDExNC45IDUuMjk4MTggMTE1LjAzNSA1LjIxNDg0IDExNS4yMUM1LjEzMTUxIDExNS4zODQgNS4wODk4NCAxMTUuNTg1IDUuMDg5ODQgMTE1LjgxMkg0LjM2NzE5QzQuMzY3MTkgMTE1LjQ5MSA0LjQzNzUgMTE1LjE5OCA0LjU3ODEyIDExNC45MzNDNC43MTg3NSAxMTQuNjY3IDQuOTI3MDggMTE0LjQ1NiA1LjIwMzEyIDExNC4zQzUuNDc5MTcgMTE0LjE0MSA1LjgxOTAxIDExNC4wNjIgNi4yMjI2NiAxMTQuMDYyQzYuNTgyMDMgMTE0LjA2MiA2Ljg4OTMyIDExNC4xMjUgNy4xNDQ1MyAxMTQuMjUzQzcuMzk5NzQgMTE0LjM3OCA3LjU5NTA1IDExNC41NTUgNy43MzA0NyAxMTQuNzg0QzcuODY4NDkgMTE1LjAxMSA3LjkzNzUgMTE1LjI3NiA3LjkzNzUgMTE1LjU4MUM3LjkzNzUgMTE1Ljc0OCA3LjkwODg1IDExNS45MTcgNy44NTE1NiAxMTYuMDg5QzcuNzk2ODggMTE2LjI1OCA3LjcyMDA1IDExNi40MjcgNy42MjEwOSAxMTYuNTk3QzcuNTI0NzQgMTE2Ljc2NiA3LjQxMTQ2IDExNi45MzMgNy4yODEyNSAxMTcuMDk3QzcuMTUzNjUgMTE3LjI2MSA3LjAxNjkzIDExNy40MjIgNi44NzEwOSAxMTcuNTgxTDUuMzQ3NjYgMTE5LjIzM0g4LjE5OTIyWk0xMi42NzUyIDExNi41M1YxMTcuMzk3QzEyLjY3NTIgMTE3Ljg2NCAxMi42MzM1IDExOC4yNTcgMTIuNTUwMiAxMTguNTc3QzEyLjQ2NjggMTE4Ljg5NyAxMi4zNDcgMTE5LjE1NSAxMi4xOTA4IDExOS4zNTFDMTIuMDM0NSAxMTkuNTQ2IDExLjg0NTcgMTE5LjY4OCAxMS42MjQ0IDExOS43NzZDMTEuNDA1NiAxMTkuODYyIDExLjE1ODIgMTE5LjkwNSAxMC44ODIyIDExOS45MDVDMTAuNjYzNSAxMTkuOTA1IDEwLjQ2MTYgMTE5Ljg3OCAxMC4yNzY3IDExOS44MjNDMTAuMDkxOCAxMTkuNzY5IDkuOTI1MTcgMTE5LjY4MSA5Ljc3NjczIDExOS41NjJDOS42MzA5IDExOS40MzkgOS41MDU5IDExOS4yOCA5LjQwMTczIDExOS4wODVDOS4yOTc1NyAxMTguODkgOS4yMTgxNCAxMTguNjUzIDkuMTYzNDUgMTE4LjM3NEM5LjEwODc3IDExOC4wOTUgOS4wODE0MiAxMTcuNzcgOS4wODE0MiAxMTcuMzk3VjExNi41M0M5LjA4MTQyIDExNi4wNjQgOS4xMjMwOSAxMTUuNjc0IDkuMjA2NDIgMTE1LjM1OEM5LjI5MjM2IDExNS4wNDMgOS40MTM0NSAxMTQuNzkxIDkuNTY5NyAxMTQuNjAxQzkuNzI1OTUgMTE0LjQwOCA5LjkxMzQ1IDExNC4yNyAxMC4xMzIyIDExNC4xODdDMTAuMzUzNiAxMTQuMTAzIDEwLjYwMSAxMTQuMDYyIDEwLjg3NDQgMTE0LjA2MkMxMS4wOTU3IDExNC4wNjIgMTEuMjk4OSAxMTQuMDg5IDExLjQ4MzggMTE0LjE0NEMxMS42NzEzIDExNC4xOTYgMTEuODM3OSAxMTQuMjggMTEuOTgzOCAxMTQuMzk3QzEyLjEyOTYgMTE0LjUxMiAxMi4yNTMzIDExNC42NjYgMTIuMzU0OSAxMTQuODU4QzEyLjQ1OSAxMTUuMDQ5IDEyLjUzODUgMTE1LjI4MiAxMi41OTMxIDExNS41NThDMTIuNjQ3OCAxMTUuODM0IDEyLjY3NTIgMTE2LjE1OCAxMi42NzUyIDExNi41M1pNMTEuOTQ4NiAxMTcuNTE1VjExNi40MDlDMTEuOTQ4NiAxMTYuMTU0IDExLjkzMyAxMTUuOTMgMTEuOTAxNyAxMTUuNzM3QzExLjg3MzEgMTE1LjU0MiAxMS44MzAxIDExNS4zNzUgMTEuNzcyOCAxMTUuMjM3QzExLjcxNTUgMTE1LjA5OSAxMS42NDI2IDExNC45ODcgMTEuNTU0MSAxMTQuOTAxQzExLjQ2ODEgMTE0LjgxNSAxMS4zNjc5IDExNC43NTMgMTEuMjUzMyAxMTQuNzE0QzExLjE0MTMgMTE0LjY3MiAxMS4wMTUgMTE0LjY1MSAxMC44NzQ0IDExNC42NTFDMTAuNzAyNSAxMTQuNjUxIDEwLjU1MDIgMTE0LjY4NCAxMC40MTc0IDExNC43NDlDMTAuMjg0NSAxMTQuODEyIDEwLjE3MjYgMTE0LjkxMiAxMC4wODE0IDExNS4wNUM5Ljk5Mjg4IDExNS4xODggOS45MjUxNyAxMTUuMzY5IDkuODc4MyAxMTUuNTkzQzkuODMxNDIgMTE1LjgxNyA5LjgwNzk4IDExNi4wODkgOS44MDc5OCAxMTYuNDA5VjExNy41MTVDOS44MDc5OCAxMTcuNzcgOS44MjIzMSAxMTcuOTk1IDkuODUwOTUgMTE4LjE5QzkuODgyMiAxMTguMzg2IDkuOTI3NzggMTE4LjU1NSA5Ljk4NzY3IDExOC42OThDMTAuMDQ3NiAxMTguODM5IDEwLjEyMDUgMTE4Ljk1NSAxMC4yMDY0IDExOS4wNDZDMTAuMjkyNCAxMTkuMTM3IDEwLjM5MTMgMTE5LjIwNSAxMC41MDMzIDExOS4yNDlDMTAuNjE3OSAxMTkuMjkxIDEwLjc0NDIgMTE5LjMxMiAxMC44ODIyIDExOS4zMTJDMTEuMDU5MyAxMTkuMzEyIDExLjIxNDIgMTE5LjI3OCAxMS4zNDcgMTE5LjIxQzExLjQ3OTkgMTE5LjE0MiAxMS41OTA1IDExOS4wMzcgMTEuNjc5MSAxMTguODk0QzExLjc3MDIgMTE4Ljc0OCAxMS44Mzc5IDExOC41NjIgMTEuODgyMiAxMTguMzM1QzExLjkyNjUgMTE4LjEwNiAxMS45NDg2IDExNy44MzIgMTEuOTQ4NiAxMTcuNTE1Wk0xMy42NzQ2IDExNS41MzRWMTE1LjIzM0MxMy42NzQ2IDExNS4wMTcgMTMuNzIxNCAxMTQuODIxIDEzLjgxNTIgMTE0LjY0NEMxMy45MDg5IDExNC40NjYgMTQuMDQzMSAxMTQuMzI1IDE0LjIxNzUgMTE0LjIxOEMxNC4zOTIgMTE0LjExMSAxNC41OTkgMTE0LjA1OCAxNC44Mzg2IDExNC4wNThDMTUuMDgzNCAxMTQuMDU4IDE1LjI5MTggMTE0LjExMSAxNS40NjM2IDExNC4yMThDMTUuNjM4MSAxMTQuMzI1IDE1Ljc3MjIgMTE0LjQ2NiAxNS44NjYgMTE0LjY0NEMxNS45NTk3IDExNC44MjEgMTYuMDA2NiAxMTUuMDE3IDE2LjAwNjYgMTE1LjIzM1YxMTUuNTM0QzE2LjAwNjYgMTE1Ljc0NSAxNS45NTk3IDExNS45MzkgMTUuODY2IDExNi4xMTZDMTUuNzc0OCAxMTYuMjkzIDE1LjY0MiAxMTYuNDM1IDE1LjQ2NzUgMTE2LjU0MkMxNS4yOTU3IDExNi42NDkgMTUuMDg4NiAxMTYuNzAyIDE0Ljg0NjQgMTE2LjcwMkMxNC42MDQzIDExNi43MDIgMTQuMzk0NiAxMTYuNjQ5IDE0LjIxNzUgMTE2LjU0MkMxNC4wNDMxIDExNi40MzUgMTMuOTA4OSAxMTYuMjkzIDEzLjgxNTIgMTE2LjExNkMxMy43MjE0IDExNS45MzkgMTMuNjc0NiAxMTUuNzQ1IDEzLjY3NDYgMTE1LjUzNFpNMTQuMjE3NSAxMTUuMjMzVjExNS41MzRDMTQuMjE3NSAxMTUuNjU0IDE0LjIzOTcgMTE1Ljc2NyAxNC4yODM5IDExNS44NzRDMTQuMzMwOCAxMTUuOTgxIDE0LjQwMTEgMTE2LjA2OCAxNC40OTQ5IDExNi4xMzZDMTQuNTg4NiAxMTYuMjAxIDE0LjcwNTggMTE2LjIzMyAxNC44NDY0IDExNi4yMzNDMTQuOTg3MSAxMTYuMjMzIDE1LjEwMjkgMTE2LjIwMSAxNS4xOTQxIDExNi4xMzZDMTUuMjg1MiAxMTYuMDY4IDE1LjM1MjkgMTE1Ljk4MSAxNS4zOTcyIDExNS44NzRDMTUuNDQxNSAxMTUuNzY3IDE1LjQ2MzYgMTE1LjY1NCAxNS40NjM2IDExNS41MzRWMTE1LjIzM0MxNS40NjM2IDExNS4xMTEgMTUuNDQwMiAxMTQuOTk2IDE1LjM5MzMgMTE0Ljg5QzE1LjM0OSAxMTQuNzggMTUuMjggMTE0LjY5MyAxNS4xODYzIDExNC42MjhDMTUuMDk1MSAxMTQuNTYgMTQuOTc5MyAxMTQuNTI2IDE0LjgzODYgMTE0LjUyNkMxNC43MDA2IDExNC41MjYgMTQuNTg0NyAxMTQuNTYgMTQuNDkxIDExNC42MjhDMTQuMzk5OCAxMTQuNjkzIDE0LjMzMDggMTE0Ljc4IDE0LjI4MzkgMTE0Ljg5QzE0LjIzOTcgMTE0Ljk5NiAxNC4yMTc1IDExNS4xMTEgMTQuMjE3NSAxMTUuMjMzWk0xNi40NDQxIDExOC43MzdWMTE4LjQzM0MxNi40NDQxIDExOC4yMTkgMTYuNDkxIDExOC4wMjQgMTYuNTg0NyAxMTcuODQ3QzE2LjY3ODUgMTE3LjY3IDE2LjgxMjYgMTE3LjUyOCAxNi45ODcxIDExNy40MjFDMTcuMTYxNSAxMTcuMzE0IDE3LjM2ODYgMTE3LjI2MSAxNy42MDgyIDExNy4yNjFDMTcuODUyOSAxMTcuMjYxIDE4LjA2MTMgMTE3LjMxNCAxOC4yMzMyIDExNy40MjFDMTguNDA3NiAxMTcuNTI4IDE4LjU0MTggMTE3LjY3IDE4LjYzNTUgMTE3Ljg0N0MxOC43MjkzIDExOC4wMjQgMTguNzc2MSAxMTguMjE5IDE4Ljc3NjEgMTE4LjQzM1YxMTguNzM3QzE4Ljc3NjEgMTE4Ljk1MSAxOC43MjkzIDExOS4xNDYgMTguNjM1NSAxMTkuMzIzQzE4LjU0NDQgMTE5LjUgMTguNDExNSAxMTkuNjQyIDE4LjIzNzEgMTE5Ljc0OUMxOC4wNjUyIDExOS44NTYgMTcuODU4MiAxMTkuOTA5IDE3LjYxNiAxMTkuOTA5QzE3LjM3MzggMTE5LjkwOSAxNy4xNjU0IDExOS44NTYgMTYuOTkxIDExOS43NDlDMTYuODE2NSAxMTkuNjQyIDE2LjY4MTEgMTE5LjUgMTYuNTg0NyAxMTkuMzIzQzE2LjQ5MSAxMTkuMTQ2IDE2LjQ0NDEgMTE4Ljk1MSAxNi40NDQxIDExOC43MzdaTTE2Ljk4NzEgMTE4LjQzM1YxMTguNzM3QzE2Ljk4NzEgMTE4Ljg1NyAxNy4wMDkyIDExOC45NzIgMTcuMDUzNSAxMTkuMDgxQzE3LjEwMDMgMTE5LjE4OCAxNy4xNzA3IDExOS4yNzUgMTcuMjY0NCAxMTkuMzQzQzE3LjM1ODIgMTE5LjQwOCAxNy40NzUzIDExOS40NCAxNy42MTYgMTE5LjQ0QzE3Ljc1NjYgMTE5LjQ0IDE3Ljg3MjUgMTE5LjQwOCAxNy45NjM2IDExOS4zNDNDMTguMDU3NCAxMTkuMjc1IDE4LjEyNjQgMTE5LjE4OCAxOC4xNzA3IDExOS4wODFDMTguMjE0OSAxMTguOTc0IDE4LjIzNzEgMTE4Ljg2IDE4LjIzNzEgMTE4LjczN1YxMTguNDMzQzE4LjIzNzEgMTE4LjMxIDE4LjIxMzYgMTE4LjE5NiAxOC4xNjY4IDExOC4wODlDMTguMTIyNSAxMTcuOTgyIDE4LjA1MzUgMTE3Ljg5NiAxNy45NTk3IDExNy44MzFDMTcuODY4NiAxMTcuNzYzIDE3Ljc1MTQgMTE3LjcyOSAxNy42MDgyIDExNy43MjlDMTcuNDcwMSAxMTcuNzI5IDE3LjM1NDMgMTE3Ljc2MyAxNy4yNjA1IDExNy44MzFDMTcuMTY5NCAxMTcuODk2IDE3LjEwMDMgMTE3Ljk4MiAxNy4wNTM1IDExOC4wODlDMTcuMDA5MiAxMTguMTk2IDE2Ljk4NzEgMTE4LjMxIDE2Ljk4NzEgMTE4LjQzM1pNMTcuNzg3OCAxMTQuOTQ4TDE1LjAxMDUgMTE5LjM5NEwxNC42MDQzIDExOS4xMzZMMTcuMzgxNiAxMTQuNjlMMTcuNzg3OCAxMTQuOTQ4WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNMTMuMDQzIDE0NC43MzdWMTQ1LjYwNEMxMy4wNDMgMTQ2LjA3IDEzLjAwMTMgMTQ2LjQ2NCAxMi45MTggMTQ2Ljc4NEMxMi44MzQ2IDE0Ny4xMDQgMTIuNzE0OCAxNDcuMzYyIDEyLjU1ODYgMTQ3LjU1N0MxMi40MDIzIDE0Ny43NTMgMTIuMjEzNSAxNDcuODk1IDExLjk5MjIgMTQ3Ljk4M0MxMS43NzM0IDE0OC4wNjkgMTEuNTI2IDE0OC4xMTIgMTEuMjUgMTQ4LjExMkMxMS4wMzEyIDE0OC4xMTIgMTAuODI5NCAxNDguMDg1IDEwLjY0NDUgMTQ4LjAzQzEwLjQ1OTYgMTQ3Ljk3NSAxMC4yOTMgMTQ3Ljg4OCAxMC4xNDQ1IDE0Ny43NjhDOS45OTg3IDE0Ny42NDYgOS44NzM3IDE0Ny40ODcgOS43Njk1MyAxNDcuMjkyQzkuNjY1MzYgMTQ3LjA5NiA5LjU4NTk0IDE0Ni44NTkgOS41MzEyNSAxNDYuNTgxQzkuNDc2NTYgMTQ2LjMwMiA5LjQ0OTIyIDE0NS45NzcgOS40NDkyMiAxNDUuNjA0VjE0NC43MzdDOS40NDkyMiAxNDQuMjcxIDkuNDkwODkgMTQzLjg4IDkuNTc0MjIgMTQzLjU2NUM5LjY2MDE2IDE0My4yNSA5Ljc4MTI1IDE0Mi45OTcgOS45Mzc1IDE0Mi44MDdDMTAuMDkzOCAxNDIuNjE1IDEwLjI4MTIgMTQyLjQ3NyAxMC41IDE0Mi4zOTNDMTAuNzIxNCAxNDIuMzEgMTAuOTY4OCAxNDIuMjY4IDExLjI0MjIgMTQyLjI2OEMxMS40NjM1IDE0Mi4yNjggMTEuNjY2NyAxNDIuMjk2IDExLjg1MTYgMTQyLjM1QzEyLjAzOTEgMTQyLjQwMiAxMi4yMDU3IDE0Mi40ODcgMTIuMzUxNiAxNDIuNjA0QzEyLjQ5NzQgMTQyLjcxOSAxMi42MjExIDE0Mi44NzIgMTIuNzIyNyAxNDMuMDY1QzEyLjgyNjggMTQzLjI1NSAxMi45MDYyIDE0My40ODggMTIuOTYwOSAxNDMuNzY0QzEzLjAxNTYgMTQ0LjA0IDEzLjA0MyAxNDQuMzY1IDEzLjA0MyAxNDQuNzM3Wk0xMi4zMTY0IDE0NS43MjFWMTQ0LjYxNkMxMi4zMTY0IDE0NC4zNjEgMTIuMzAwOCAxNDQuMTM3IDEyLjI2OTUgMTQzLjk0NEMxMi4yNDA5IDE0My43NDkgMTIuMTk3OSAxNDMuNTgyIDEyLjE0MDYgMTQzLjQ0NEMxMi4wODMzIDE0My4zMDYgMTIuMDEwNCAxNDMuMTk0IDExLjkyMTkgMTQzLjEwOEMxMS44MzU5IDE0My4wMjIgMTEuNzM1NyAxNDIuOTYgMTEuNjIxMSAxNDIuOTIxQzExLjUwOTEgMTQyLjg3OSAxMS4zODI4IDE0Mi44NTggMTEuMjQyMiAxNDIuODU4QzExLjA3MDMgMTQyLjg1OCAxMC45MTggMTQyLjg5MSAxMC43ODUyIDE0Mi45NTZDMTAuNjUyMyAxNDMuMDE4IDEwLjU0MDQgMTQzLjExOSAxMC40NDkyIDE0My4yNTdDMTAuMzYwNyAxNDMuMzk1IDEwLjI5MyAxNDMuNTc2IDEwLjI0NjEgMTQzLjhDMTAuMTk5MiAxNDQuMDI0IDEwLjE3NTggMTQ0LjI5NiAxMC4xNzU4IDE0NC42MTZWMTQ1LjcyMUMxMC4xNzU4IDE0NS45NzcgMTAuMTkwMSAxNDYuMjAyIDEwLjIxODggMTQ2LjM5N0MxMC4yNSAxNDYuNTkzIDEwLjI5NTYgMTQ2Ljc2MiAxMC4zNTU1IDE0Ni45MDVDMTAuNDE1NCAxNDcuMDQ2IDEwLjQ4ODMgMTQ3LjE2MiAxMC41NzQyIDE0Ny4yNTNDMTAuNjYwMiAxNDcuMzQ0IDEwLjc1OTEgMTQ3LjQxMiAxMC44NzExIDE0Ny40NTZDMTAuOTg1NyAxNDcuNDk3IDExLjExMiAxNDcuNTE4IDExLjI1IDE0Ny41MThDMTEuNDI3MSAxNDcuNTE4IDExLjU4MiAxNDcuNDg0IDExLjcxNDggMTQ3LjQxN0MxMS44NDc3IDE0Ny4zNDkgMTEuOTU4MyAxNDcuMjQ0IDEyLjA0NjkgMTQ3LjFDMTIuMTM4IDE0Ni45NTUgMTIuMjA1NyAxNDYuNzY4IDEyLjI1IDE0Ni41NDJDMTIuMjk0MyAxNDYuMzEzIDEyLjMxNjQgMTQ2LjAzOSAxMi4zMTY0IDE0NS43MjFaTTE0LjA0MjQgMTQzLjc0MVYxNDMuNDRDMTQuMDQyNCAxNDMuMjI0IDE0LjA4OTIgMTQzLjAyNyAxNC4xODMgMTQyLjg1QzE0LjI3NjcgMTQyLjY3MyAxNC40MTA4IDE0Mi41MzEgMTQuNTg1MyAxNDIuNDI1QzE0Ljc1OTggMTQyLjMxOCAxNC45NjY4IDE0Mi4yNjQgMTUuMjA2NCAxNDIuMjY0QzE1LjQ1MTIgMTQyLjI2NCAxNS42NTk1IDE0Mi4zMTggMTUuODMxNCAxNDIuNDI1QzE2LjAwNTkgMTQyLjUzMSAxNi4xNCAxNDIuNjczIDE2LjIzMzggMTQyLjg1QzE2LjMyNzUgMTQzLjAyNyAxNi4zNzQ0IDE0My4yMjQgMTYuMzc0NCAxNDMuNDRWMTQzLjc0MUMxNi4zNzQ0IDE0My45NTIgMTYuMzI3NSAxNDQuMTQ2IDE2LjIzMzggMTQ0LjMyM0MxNi4xNDI2IDE0NC41IDE2LjAwOTggMTQ0LjY0MiAxNS44MzUzIDE0NC43NDlDMTUuNjYzNSAxNDQuODU2IDE1LjQ1NjQgMTQ0LjkwOSAxNS4yMTQyIDE0NC45MDlDMTQuOTcyIDE0NC45MDkgMTQuNzYyNCAxNDQuODU2IDE0LjU4NTMgMTQ0Ljc0OUMxNC40MTA4IDE0NC42NDIgMTQuMjc2NyAxNDQuNSAxNC4xODMgMTQ0LjMyM0MxNC4wODkyIDE0NC4xNDYgMTQuMDQyNCAxNDMuOTUyIDE0LjA0MjQgMTQzLjc0MVpNMTQuNTg1MyAxNDMuNDRWMTQzLjc0MUMxNC41ODUzIDE0My44NjEgMTQuNjA3NSAxNDMuOTc0IDE0LjY1MTcgMTQ0LjA4MUMxNC42OTg2IDE0NC4xODggMTQuNzY4OSAxNDQuMjc1IDE0Ljg2MjcgMTQ0LjM0M0MxNC45NTY0IDE0NC40MDggMTUuMDczNiAxNDQuNDQgMTUuMjE0MiAxNDQuNDRDMTUuMzU0OSAxNDQuNDQgMTUuNDcwNyAxNDQuNDA4IDE1LjU2MTkgMTQ0LjM0M0MxNS42NTMgMTQ0LjI3NSAxNS43MjA3IDE0NC4xODggMTUuNzY1IDE0NC4wODFDMTUuODA5MyAxNDMuOTc0IDE1LjgzMTQgMTQzLjg2MSAxNS44MzE0IDE0My43NDFWMTQzLjQ0QzE1LjgzMTQgMTQzLjMxOCAxNS44MDggMTQzLjIwMyAxNS43NjExIDE0My4wOTZDMTUuNzE2OCAxNDIuOTg3IDE1LjY0NzggMTQyLjkgMTUuNTU0MSAxNDIuODM1QzE1LjQ2MjkgMTQyLjc2NyAxNS4zNDcgMTQyLjczMyAxNS4yMDY0IDE0Mi43MzNDMTUuMDY4NCAxNDIuNzMzIDE0Ljk1MjUgMTQyLjc2NyAxNC44NTg4IDE0Mi44MzVDMTQuNzY3NiAxNDIuOSAxNC42OTg2IDE0Mi45ODcgMTQuNjUxNyAxNDMuMDk2QzE0LjYwNzUgMTQzLjIwMyAxNC41ODUzIDE0My4zMTggMTQuNTg1MyAxNDMuNDRaTTE2LjgxMTkgMTQ2Ljk0NFYxNDYuNjM5QzE2LjgxMTkgMTQ2LjQyNiAxNi44NTg4IDE0Ni4yMzEgMTYuOTUyNSAxNDYuMDUzQzE3LjA0NjMgMTQ1Ljg3NiAxNy4xODA0IDE0NS43MzQgMTcuMzU0OSAxNDUuNjI4QzE3LjUyOTMgMTQ1LjUyMSAxNy43MzY0IDE0NS40NjggMTcuOTc2IDE0NS40NjhDMTguMjIwNyAxNDUuNDY4IDE4LjQyOTEgMTQ1LjUyMSAxOC42MDEgMTQ1LjYyOEMxOC43NzU0IDE0NS43MzQgMTguOTA5NSAxNDUuODc2IDE5LjAwMzMgMTQ2LjA1M0MxOS4wOTcgMTQ2LjIzMSAxOS4xNDM5IDE0Ni40MjYgMTkuMTQzOSAxNDYuNjM5VjE0Ni45NDRDMTkuMTQzOSAxNDcuMTU4IDE5LjA5NyAxNDcuMzUzIDE5LjAwMzMgMTQ3LjUzQzE4LjkxMjIgMTQ3LjcwNyAxOC43NzkzIDE0Ny44NDkgMTguNjA0OSAxNDcuOTU2QzE4LjQzMyAxNDguMDYzIDE4LjIyNiAxNDguMTE2IDE3Ljk4MzggMTQ4LjExNkMxNy43NDE2IDE0OC4xMTYgMTcuNTMzMiAxNDguMDYzIDE3LjM1ODggMTQ3Ljk1NkMxNy4xODQzIDE0Ny44NDkgMTcuMDQ4OSAxNDcuNzA3IDE2Ljk1MjUgMTQ3LjUzQzE2Ljg1ODggMTQ3LjM1MyAxNi44MTE5IDE0Ny4xNTggMTYuODExOSAxNDYuOTQ0Wk0xNy4zNTQ5IDE0Ni42MzlWMTQ2Ljk0NEMxNy4zNTQ5IDE0Ny4wNjQgMTcuMzc3IDE0Ny4xNzggMTcuNDIxMyAxNDcuMjg4QzE3LjQ2ODEgMTQ3LjM5NSAxNy41Mzg1IDE0Ny40ODIgMTcuNjMyMiAxNDcuNTVDMTcuNzI2IDE0Ny42MTUgMTcuODQzMSAxNDcuNjQ3IDE3Ljk4MzggMTQ3LjY0N0MxOC4xMjQ0IDE0Ny42NDcgMTguMjQwMyAxNDcuNjE1IDE4LjMzMTQgMTQ3LjU1QzE4LjQyNTIgMTQ3LjQ4MiAxOC40OTQyIDE0Ny4zOTUgMTguNTM4NSAxNDcuMjg4QzE4LjU4MjcgMTQ3LjE4MSAxOC42MDQ5IDE0Ny4wNjYgMTguNjA0OSAxNDYuOTQ0VjE0Ni42MzlDMTguNjA0OSAxNDYuNTE3IDE4LjU4MTQgMTQ2LjQwMiAxOC41MzQ1IDE0Ni4yOTZDMTguNDkwMyAxNDYuMTg5IDE4LjQyMTMgMTQ2LjEwMyAxOC4zMjc1IDE0Ni4wMzhDMTguMjM2NCAxNDUuOTcgMTguMTE5MiAxNDUuOTM2IDE3Ljk3NiAxNDUuOTM2QzE3LjgzNzkgMTQ1LjkzNiAxNy43MjIgMTQ1Ljk3IDE3LjYyODMgMTQ2LjAzOEMxNy41MzcyIDE0Ni4xMDMgMTcuNDY4MSAxNDYuMTg5IDE3LjQyMTMgMTQ2LjI5NkMxNy4zNzcgMTQ2LjQwMiAxNy4zNTQ5IDE0Ni41MTcgMTcuMzU0OSAxNDYuNjM5Wk0xOC4xNTU2IDE0My4xNTVMMTUuMzc4MyAxNDcuNkwxNC45NzIgMTQ3LjM0M0wxNy43NDk0IDE0Mi44OTdMMTguMTU1NiAxNDMuMTU1WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNMjUgNC4xNjExM0wyMDAgNC4xNjExNiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiLz4KPHBhdGggZD0iTTI1IDMzLjE2MTFMMjAwIDMzLjE2MTIiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1vcGFjaXR5PSIwLjEyIi8+CjxwYXRoIGQ9Ik0yNSA2MS4xNjExTDIwMCA2MS4xNjEyIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC4xMiIvPgo8cGF0aCBkPSJNMjUgODkuMTYxMUwyMDAgODkuMTYxMiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiLz4KPHBhdGggZD0iTTI1IDExOC4xNjFMMjAwIDExOC4xNjEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1vcGFjaXR5PSIwLjEyIi8+CjxsaW5lIHgxPSIyMy4yIiB5MT0iMTQ1Ljk2MSIgeDI9IjIwMi44IiB5Mj0iMTQ1Ljk2MSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuNyIgc3Ryb2tlLXdpZHRoPSIwLjQiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz4KPGxpbmUgeDE9IjQwLjQ1IiB5MT0iMTQ4LjA3MiIgeDI9IjQwLjQ1IiB5Mj0iMTQ3LjI1IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC41IiBzdHJva2Utd2lkdGg9IjAuNSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8cGF0aCBkPSJNMzIuNTA5MSAxNTIuMDI1VjE1Mi44OTNDMzIuNTA5MSAxNTMuMzU5IDMyLjQ2NzQgMTUzLjc1MiAzMi4zODQxIDE1NC4wNzJDMzIuMzAwNyAxNTQuMzkzIDMyLjE4MDkgMTU0LjY1IDMyLjAyNDcgMTU0Ljg0NkMzMS44Njg0IDE1NS4wNDEgMzEuNjc5NiAxNTUuMTgzIDMxLjQ1ODMgMTU1LjI3MUMzMS4yMzk1IDE1NS4zNTcgMzAuOTkyMSAxNTUuNCAzMC43MTYxIDE1NS40QzMwLjQ5NzMgMTU1LjQgMzAuMjk1NSAxNTUuMzczIDMwLjExMDYgMTU1LjMxOEMyOS45MjU3IDE1NS4yNjQgMjkuNzU5MSAxNTUuMTc2IDI5LjYxMDYgMTU1LjA1N0MyOS40NjQ4IDE1NC45MzQgMjkuMzM5OCAxNTQuNzc1IDI5LjIzNTYgMTU0LjU4QzI5LjEzMTUgMTU0LjM4NSAyOS4wNTIgMTU0LjE0OCAyOC45OTczIDE1My44NjlDMjguOTQyNyAxNTMuNTkgMjguOTE1MyAxNTMuMjY1IDI4LjkxNTMgMTUyLjg5M1YxNTIuMDI1QzI4LjkxNTMgMTUxLjU1OSAyOC45NTcgMTUxLjE2OSAyOS4wNDAzIDE1MC44NTRDMjkuMTI2MiAxNTAuNTM4IDI5LjI0NzMgMTUwLjI4NiAyOS40MDM2IDE1MC4wOTZDMjkuNTU5OCAxNDkuOTAzIDI5Ljc0NzMgMTQ5Ljc2NSAyOS45NjYxIDE0OS42ODJDMzAuMTg3NCAxNDkuNTk4IDMwLjQzNDggMTQ5LjU1NyAzMC43MDgzIDE0OS41NTdDMzAuOTI5NiAxNDkuNTU3IDMxLjEzMjggMTQ5LjU4NCAzMS4zMTc3IDE0OS42MzlDMzEuNTA1MiAxNDkuNjkxIDMxLjY3MTggMTQ5Ljc3NSAzMS44MTc3IDE0OS44OTNDMzEuOTYzNSAxNTAuMDA3IDMyLjA4NzIgMTUwLjE2MSAzMi4xODg3IDE1MC4zNTRDMzIuMjkyOSAxNTAuNTQ0IDMyLjM3MjMgMTUwLjc3NyAzMi40MjcgMTUxLjA1M0MzMi40ODE3IDE1MS4zMjkgMzIuNTA5MSAxNTEuNjUzIDMyLjUwOTEgMTUyLjAyNVpNMzEuNzgyNSAxNTMuMDFWMTUxLjkwNEMzMS43ODI1IDE1MS42NDkgMzEuNzY2OSAxNTEuNDI1IDMxLjczNTYgMTUxLjIzMkMzMS43MDcgMTUxLjAzNyAzMS42NjQgMTUwLjg3IDMxLjYwNjcgMTUwLjczMkMzMS41NDk0IDE1MC41OTQgMzEuNDc2NSAxNTAuNDgyIDMxLjM4OCAxNTAuMzk2QzMxLjMwMiAxNTAuMzExIDMxLjIwMTggMTUwLjI0OCAzMS4wODcyIDE1MC4yMDlDMzAuOTc1MiAxNTAuMTY3IDMwLjg0ODkgMTUwLjE0NiAzMC43MDgzIDE1MC4xNDZDMzAuNTM2NCAxNTAuMTQ2IDMwLjM4NDEgMTUwLjE3OSAzMC4yNTEyIDE1MC4yNDRDMzAuMTE4NCAxNTAuMzA3IDMwLjAwNjUgMTUwLjQwNyAyOS45MTUzIDE1MC41NDVDMjkuODI2OCAxNTAuNjgzIDI5Ljc1OTEgMTUwLjg2NCAyOS43MTIyIDE1MS4wODhDMjkuNjY1MyAxNTEuMzEyIDI5LjY0MTkgMTUxLjU4NCAyOS42NDE5IDE1MS45MDRWMTUzLjAxQzI5LjY0MTkgMTUzLjI2NSAyOS42NTYyIDE1My40OSAyOS42ODQ4IDE1My42ODZDMjkuNzE2MSAxNTMuODgxIDI5Ljc2MTcgMTU0LjA1IDI5LjgyMTYgMTU0LjE5M0MyOS44ODE1IDE1NC4zMzQgMjkuOTU0NCAxNTQuNDUgMzAuMDQwMyAxNTQuNTQxQzMwLjEyNjIgMTU0LjYzMiAzMC4yMjUyIDE1NC43IDMwLjMzNzIgMTU0Ljc0NEMzMC40NTE4IDE1NC43ODYgMzAuNTc4MSAxNTQuODA3IDMwLjcxNjEgMTU0LjgwN0MzMC44OTMyIDE1NC44MDcgMzEuMDQ4MSAxNTQuNzczIDMxLjE4MDkgMTU0LjcwNUMzMS4zMTM3IDE1NC42MzcgMzEuNDI0NCAxNTQuNTMyIDMxLjUxMyAxNTQuMzg5QzMxLjYwNDEgMTU0LjI0MyAzMS42NzE4IDE1NC4wNTcgMzEuNzE2MSAxNTMuODNDMzEuNzYwNCAxNTMuNjAxIDMxLjc4MjUgMTUzLjMyNyAzMS43ODI1IDE1My4wMVpNMzUuODk2NCAxNDkuNjA0VjE1NS4zMjJIMzUuMTczN1YxNTAuNTA2TDMzLjcxNjcgMTUxLjAzN1YxNTAuMzg1TDM1Ljc4MzEgMTQ5LjYwNEgzNS44OTY0Wk00MS4xMTI0IDE0OS42MzVWMTU1LjMyMkg0MC4zNTg1VjE0OS42MzVINDEuMTEyNFpNNDMuNDk1MiAxNTIuMTkzVjE1Mi44MTFINDAuOTQ4M1YxNTIuMTkzSDQzLjQ5NTJaTTQzLjg4MTkgMTQ5LjYzNVYxNTAuMjUySDQwLjk0ODNWMTQ5LjYzNUg0My44ODE5Wk00Ni40MjE2IDE1NS40QzQ2LjEyNzMgMTU1LjQgNDUuODYwNCAxNTUuMzUxIDQ1LjYyMDggMTU1LjI1MkM0NS4zODM4IDE1NS4xNSA0NS4xNzk0IDE1NS4wMDggNDUuMDA3NSAxNTQuODI2QzQ0LjgzODMgMTU0LjY0NCA0NC43MDgxIDE1NC40MjggNDQuNjE2OSAxNTQuMTc4QzQ0LjUyNTggMTUzLjkyOCA0NC40ODAyIDE1My42NTQgNDQuNDgwMiAxNTMuMzU3VjE1My4xOTNDNDQuNDgwMiAxNTIuODUgNDQuNTMxIDE1Mi41NDQgNDQuNjMyNSAxNTIuMjc1QzQ0LjczNDEgMTUyLjAwNSA0NC44NzIxIDE1MS43NzUgNDUuMDQ2NiAxNTEuNTg4QzQ1LjIyMTEgMTUxLjQgNDUuNDE5IDE1MS4yNTggNDUuNjQwMyAxNTEuMTYyQzQ1Ljg2MTcgMTUxLjA2NiA0Ni4wOTA5IDE1MS4wMTggNDYuMzI3OCAxNTEuMDE4QzQ2LjYyOTkgMTUxLjAxOCA0Ni44OTAzIDE1MS4wNyA0Ny4xMDkxIDE1MS4xNzRDNDcuMzMwNSAxNTEuMjc4IDQ3LjUxMTQgMTUxLjQyNCA0Ny42NTIxIDE1MS42MTFDNDcuNzkyNyAxNTEuNzk2IDQ3Ljg5NjkgMTUyLjAxNSA0Ny45NjQ2IDE1Mi4yNjhDNDguMDMyMyAxNTIuNTE4IDQ4LjA2NjEgMTUyLjc5MSA0OC4wNjYxIDE1My4wODhWMTUzLjQxMkg0NC45MDk5VjE1Mi44MjJINDcuMzQzNVYxNTIuNzY4QzQ3LjMzMzEgMTUyLjU4IDQ3LjI5NCAxNTIuMzk4IDQ3LjIyNjMgMTUyLjIyMUM0Ny4xNjEyIDE1Mi4wNDQgNDcuMDU3IDE1MS44OTggNDYuOTEzOCAxNTEuNzgzQzQ2Ljc3MDYgMTUxLjY2OSA0Ni41NzUyIDE1MS42MTEgNDYuMzI3OCAxNTEuNjExQzQ2LjE2MzggMTUxLjYxMSA0Ni4wMTI3IDE1MS42NDYgNDUuODc0NyAxNTEuNzE3QzQ1LjczNjcgMTUxLjc4NSA0NS42MTgyIDE1MS44ODYgNDUuNTE5MyAxNTIuMDIxQzQ1LjQyMDMgMTUyLjE1NyA0NS4zNDM1IDE1Mi4zMjIgNDUuMjg4OCAxNTIuNTE4QzQ1LjIzNDEgMTUyLjcxMyA0NS4yMDY4IDE1Mi45MzggNDUuMjA2OCAxNTMuMTkzVjE1My4zNTdDNDUuMjA2OCAxNTMuNTU4IDQ1LjIzNDEgMTUzLjc0NyA0NS4yODg4IDE1My45MjRDNDUuMzQ2MSAxNTQuMDk4IDQ1LjQyODEgMTU0LjI1MiA0NS41MzQ5IDE1NC4zODVDNDUuNjQ0MyAxNTQuNTE4IDQ1Ljc3NTggMTU0LjYyMiA0NS45Mjk0IDE1NC42OTdDNDYuMDg1NyAxNTQuNzczIDQ2LjI2MjcgMTU0LjgxMSA0Ni40NjA3IDE1NC44MTFDNDYuNzE1OSAxNTQuODExIDQ2LjkzMiAxNTQuNzU4IDQ3LjEwOTEgMTU0LjY1NEM0Ny4yODYyIDE1NC41NSA0Ny40NDExIDE1NC40MTEgNDcuNTczOSAxNTQuMjM2TDQ4LjAxMTQgMTU0LjU4NEM0Ny45MjAzIDE1NC43MjIgNDcuODA0NCAxNTQuODU0IDQ3LjY2MzggMTU0Ljk3OUM0Ny41MjMyIDE1NS4xMDQgNDcuMzUgMTU1LjIwNSA0Ny4xNDQzIDE1NS4yODNDNDYuOTQxMSAxNTUuMzYxIDQ2LjcwMDIgMTU1LjQgNDYuNDIxNiAxNTUuNFpNNDguOTg4NiAxNDkuMzIySDQ5LjcxNTJWMTU0LjUwMkw0OS42NTI3IDE1NS4zMjJINDguOTg4NlYxNDkuMzIyWk01Mi41NzA2IDE1My4xNzRWMTUzLjI1NkM1Mi41NzA2IDE1My41NjMgNTIuNTM0MiAxNTMuODQ4IDUyLjQ2MTMgMTU0LjExMUM1Mi4zODgzIDE1NC4zNzIgNTIuMjgxNiAxNTQuNTk4IDUyLjE0MDkgMTU0Ljc5MUM1Mi4wMDAzIDE1NC45ODQgNTEuODI4NCAxNTUuMTMzIDUxLjYyNTMgMTU1LjI0QzUxLjQyMjIgMTU1LjM0NyA1MS4xODkxIDE1NS40IDUwLjkyNjEgMTU1LjRDNTAuNjU3OSAxNTUuNCA1MC40MjIyIDE1NS4zNTUgNTAuMjE5MSAxNTUuMjY0QzUwLjAxODUgMTU1LjE3IDQ5Ljg0OTMgMTU1LjAzNiA0OS43MTEzIDE1NC44NjFDNDkuNTczMiAxNTQuNjg3IDQ5LjQ2MjYgMTU0LjQ3NiA0OS4zNzkyIDE1NC4yMjlDNDkuMjk4NSAxNTMuOTgxIDQ5LjI0MjUgMTUzLjcwMiA0OS4yMTEzIDE1My4zOTNWMTUzLjAzM0M0OS4yNDI1IDE1Mi43MjEgNDkuMjk4NSAxNTIuNDQxIDQ5LjM3OTIgMTUyLjE5M0M0OS40NjI2IDE1MS45NDYgNDkuNTczMiAxNTEuNzM1IDQ5LjcxMTMgMTUxLjU2MUM0OS44NDkzIDE1MS4zODMgNTAuMDE4NSAxNTEuMjQ5IDUwLjIxOTEgMTUxLjE1OEM1MC40MTk2IDE1MS4wNjQgNTAuNjUyNyAxNTEuMDE4IDUwLjkxODMgMTUxLjAxOEM1MS4xODM5IDE1MS4wMTggNTEuNDE5NiAxNTEuMDcgNTEuNjI1MyAxNTEuMTc0QzUxLjgzMSAxNTEuMjc1IDUyLjAwMjkgMTUxLjQyMSA1Mi4xNDA5IDE1MS42MTFDNTIuMjgxNiAxNTEuODAxIDUyLjM4ODMgMTUyLjAyOSA1Mi40NjEzIDE1Mi4yOTVDNTIuNTM0MiAxNTIuNTU4IDUyLjU3MDYgMTUyLjg1MSA1Mi41NzA2IDE1My4xNzRaTTUxLjg0NDEgMTUzLjI1NlYxNTMuMTc0QzUxLjg0NDEgMTUyLjk2MyA1MS44MjQ1IDE1Mi43NjUgNTEuNzg1NSAxNTIuNThDNTEuNzQ2NCAxNTIuMzkzIDUxLjY4MzkgMTUyLjIyOSA1MS41OTggMTUyLjA4OEM1MS41MTIgMTUxLjk0NSA1MS4zOTg4IDE1MS44MzMgNTEuMjU4MSAxNTEuNzUyQzUxLjExNzUgMTUxLjY2OSA1MC45NDQzIDE1MS42MjcgNTAuNzM4NiAxNTEuNjI3QzUwLjU1NjMgMTUxLjYyNyA1MC4zOTc1IDE1MS42NTggNTAuMjYyIDE1MS43MjFDNTAuMTI5MiAxNTEuNzgzIDUwLjAxNTkgMTUxLjg2OCA0OS45MjIyIDE1MS45NzVDNDkuODI4NCAxNTIuMDc5IDQ5Ljc1MTYgMTUyLjE5OSA0OS42OTE3IDE1Mi4zMzRDNDkuNjM0NCAxNTIuNDY3IDQ5LjU5MTUgMTUyLjYwNSA0OS41NjI4IDE1Mi43NDhWMTUzLjY4OUM0OS42MDQ1IDE1My44NzIgNDkuNjcyMiAxNTQuMDQ4IDQ5Ljc2NTkgMTU0LjIxN0M0OS44NjIzIDE1NC4zODMgNDkuOTg5OSAxNTQuNTIgNTAuMTQ4OCAxNTQuNjI3QzUwLjMxMDIgMTU0LjczNCA1MC41MDk0IDE1NC43ODcgNTAuNzQ2NCAxNTQuNzg3QzUwLjk0MTcgMTU0Ljc4NyA1MS4xMDg0IDE1NC43NDggNTEuMjQ2NCAxNTQuNjdDNTEuMzg3IDE1NC41ODkgNTEuNTAwMyAxNTQuNDc5IDUxLjU4NjMgMTU0LjMzOEM1MS42NzQ4IDE1NC4xOTcgNTEuNzM5OSAxNTQuMDM1IDUxLjc4MTYgMTUzLjg1QzUxLjgyMzIgMTUzLjY2NSA1MS44NDQxIDE1My40NjcgNTEuODQ0MSAxNTMuMjU2WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDFfNDE4NF85NDUyNykiPgo8bGluZSB4MT0iNzUuODQ5OSIgeTE9IjE0Ny4wNzIiIHgyPSI3NS44NDk5IiB5Mj0iMTQ2LjI1IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC41IiBzdHJva2Utd2lkdGg9IjAuNSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8cGF0aCBkPSJNNjcuOTA5IDE1Mi4wMjVWMTUyLjg5MkM2Ny45MDkgMTUzLjM1OCA2Ny44NjczIDE1My43NTIgNjcuNzg0IDE1NC4wNzJDNjcuNzAwNiAxNTQuMzkyIDY3LjU4MDggMTU0LjY1IDY3LjQyNDYgMTU0Ljg0NUM2Ny4yNjgzIDE1NS4wNDEgNjcuMDc5NSAxNTUuMTgzIDY2Ljg1ODIgMTU1LjI3MUM2Ni42Mzk0IDE1NS4zNTcgNjYuMzkyIDE1NS40IDY2LjExNiAxNTUuNEM2NS44OTcyIDE1NS40IDY1LjY5NTQgMTU1LjM3MyA2NS41MTA1IDE1NS4zMThDNjUuMzI1NiAxNTUuMjYzIDY1LjE1OSAxNTUuMTc2IDY1LjAxMDUgMTU1LjA1NkM2NC44NjQ3IDE1NC45MzQgNjQuNzM5NyAxNTQuNzc1IDY0LjYzNTUgMTU0LjU4QzY0LjUzMTQgMTU0LjM4NSA2NC40NTE5IDE1NC4xNDggNjQuMzk3MiAxNTMuODY5QzY0LjM0MjYgMTUzLjU5IDY0LjMxNTIgMTUzLjI2NSA2NC4zMTUyIDE1Mi44OTJWMTUyLjAyNUM2NC4zMTUyIDE1MS41NTkgNjQuMzU2OSAxNTEuMTY4IDY0LjQ0MDIgMTUwLjg1M0M2NC41MjYxIDE1MC41MzggNjQuNjQ3MiAxNTAuMjg2IDY0LjgwMzUgMTUwLjA5NUM2NC45NTk3IDE0OS45MDMgNjUuMTQ3MiAxNDkuNzY1IDY1LjM2NiAxNDkuNjgxQzY1LjU4NzMgMTQ5LjU5OCA2NS44MzQ3IDE0OS41NTYgNjYuMTA4MiAxNDkuNTU2QzY2LjMyOTUgMTQ5LjU1NiA2Ni41MzI3IDE0OS41ODQgNjYuNzE3NiAxNDkuNjM4QzY2LjkwNTEgMTQ5LjY5MSA2Ny4wNzE3IDE0OS43NzUgNjcuMjE3NiAxNDkuODkyQzY3LjM2MzQgMTUwLjAwNyA2Ny40ODcxIDE1MC4xNjEgNjcuNTg4NiAxNTAuMzUzQzY3LjY5MjggMTUwLjU0MyA2Ny43NzIyIDE1MC43NzYgNjcuODI2OSAxNTEuMDUyQzY3Ljg4MTYgMTUxLjMyOSA2Ny45MDkgMTUxLjY1MyA2Ny45MDkgMTUyLjAyNVpNNjcuMTgyNCAxNTMuMDFWMTUxLjkwNEM2Ny4xODI0IDE1MS42NDkgNjcuMTY2OCAxNTEuNDI1IDY3LjEzNTUgMTUxLjIzMkM2Ny4xMDY5IDE1MS4wMzcgNjcuMDYzOSAxNTAuODcgNjcuMDA2NiAxNTAuNzMyQzY2Ljk0OTMgMTUwLjU5NCA2Ni44NzY0IDE1MC40ODIgNjYuNzg3OSAxNTAuMzk2QzY2LjcwMTkgMTUwLjMxIDY2LjYwMTcgMTUwLjI0OCA2Ni40ODcxIDE1MC4yMDlDNjYuMzc1MSAxNTAuMTY3IDY2LjI0ODggMTUwLjE0NiA2Ni4xMDgyIDE1MC4xNDZDNjUuOTM2MyAxNTAuMTQ2IDY1Ljc4NCAxNTAuMTc5IDY1LjY1MTEgMTUwLjI0NEM2NS41MTgzIDE1MC4zMDYgNjUuNDA2NCAxNTAuNDA3IDY1LjMxNTIgMTUwLjU0NUM2NS4yMjY3IDE1MC42ODMgNjUuMTU5IDE1MC44NjQgNjUuMTEyMSAxNTEuMDg4QzY1LjA2NTIgMTUxLjMxMiA2NS4wNDE4IDE1MS41ODQgNjUuMDQxOCAxNTEuOTA0VjE1My4wMUM2NS4wNDE4IDE1My4yNjUgNjUuMDU2MSAxNTMuNDkgNjUuMDg0NyAxNTMuNjg1QzY1LjExNiAxNTMuODgxIDY1LjE2MTYgMTU0LjA1IDY1LjIyMTUgMTU0LjE5M0M2NS4yODE0IDE1NC4zMzQgNjUuMzU0MyAxNTQuNDUgNjUuNDQwMiAxNTQuNTQxQzY1LjUyNjEgMTU0LjYzMiA2NS42MjUxIDE1NC43IDY1LjczNzEgMTU0Ljc0NEM2NS44NTE3IDE1NC43ODYgNjUuOTc4IDE1NC44MDYgNjYuMTE2IDE1NC44MDZDNjYuMjkzMSAxNTQuODA2IDY2LjQ0OCAxNTQuNzczIDY2LjU4MDggMTU0LjcwNUM2Ni43MTM2IDE1NC42MzcgNjYuODI0MyAxNTQuNTMyIDY2LjkxMjkgMTU0LjM4OEM2Ny4wMDQgMTU0LjI0MyA2Ny4wNzE3IDE1NC4wNTYgNjcuMTE2IDE1My44M0M2Ny4xNjAzIDE1My42MDEgNjcuMTgyNCAxNTMuMzI3IDY3LjE4MjQgMTUzLjAxWk03Mi42NDc4IDE1NC43MjhWMTU1LjMyMkg2OC45MjUyVjE1NC44MDJMNzAuNzg4NSAxNTIuNzI4QzcxLjAxNzYgMTUyLjQ3MyA3MS4xOTQ3IDE1Mi4yNTcgNzEuMzE5NyAxNTIuMDhDNzEuNDQ3MyAxNTEuOSA3MS41MzU5IDE1MS43NCA3MS41ODUzIDE1MS41OTlDNzEuNjM3NCAxNTEuNDU2IDcxLjY2MzUgMTUxLjMxIDcxLjY2MzUgMTUxLjE2MkM3MS42NjM1IDE1MC45NzQgNzEuNjI0NCAxNTAuODA1IDcxLjU0NjMgMTUwLjY1NEM3MS40NzA4IDE1MC41IDcxLjM1ODggMTUwLjM3OCA3MS4yMTAzIDE1MC4yODdDNzEuMDYxOSAxNTAuMTk2IDcwLjg4MjIgMTUwLjE1IDcwLjY3MTMgMTUwLjE1QzcwLjQxODcgMTUwLjE1IDcwLjIwNzcgMTUwLjIgNzAuMDM4NSAxNTAuMjk5QzY5Ljg3MTggMTUwLjM5NSA2OS43NDY4IDE1MC41MyA2OS42NjM1IDE1MC43MDVDNjkuNTgwMSAxNTAuODc5IDY5LjUzODUgMTUxLjA4IDY5LjUzODUgMTUxLjMwNkg2OC44MTU4QzY4LjgxNTggMTUwLjk4NiA2OC44ODYxIDE1MC42OTMgNjkuMDI2NyAxNTAuNDI3QzY5LjE2NzQgMTUwLjE2MiA2OS4zNzU3IDE0OS45NTEgNjkuNjUxNyAxNDkuNzk1QzY5LjkyNzggMTQ5LjYzNiA3MC4yNjc2IDE0OS41NTYgNzAuNjcxMyAxNDkuNTU2QzcxLjAzMDcgMTQ5LjU1NiA3MS4zMzc5IDE0OS42MiA3MS41OTMyIDE0OS43NDhDNzEuODQ4NCAxNDkuODczIDcyLjA0MzcgMTUwLjA1IDcyLjE3OTEgMTUwLjI3OUM3Mi4zMTcxIDE1MC41MDYgNzIuMzg2MSAxNTAuNzcxIDcyLjM4NjEgMTUxLjA3NkM3Mi4zODYxIDE1MS4yNDMgNzIuMzU3NSAxNTEuNDEyIDcyLjMwMDIgMTUxLjU4NEM3Mi4yNDU1IDE1MS43NTMgNzIuMTY4NyAxNTEuOTIyIDcyLjA2OTcgMTUyLjA5MkM3MS45NzM0IDE1Mi4yNjEgNzEuODYwMSAxNTIuNDI3IDcxLjcyOTkgMTUyLjU5MkM3MS42MDIzIDE1Mi43NTYgNzEuNDY1NSAxNTIuOTE3IDcxLjMxOTcgMTUzLjA3Nkw2OS43OTYzIDE1NC43MjhINzIuNjQ3OFpNNzYuNTEyMyAxNDkuNjM1VjE1NS4zMjJINzUuNzU4NFYxNDkuNjM1SDc2LjUxMjNaTTc4Ljg5NTEgMTUyLjE5M1YxNTIuODFINzYuMzQ4MlYxNTIuMTkzSDc4Ljg5NTFaTTc5LjI4MTggMTQ5LjYzNVYxNTAuMjUySDc2LjM0ODJWMTQ5LjYzNUg3OS4yODE4Wk04MS44MjE1IDE1NS40QzgxLjUyNzIgMTU1LjQgODEuMjYwMyAxNTUuMzUxIDgxLjAyMDcgMTU1LjI1MkM4MC43ODM3IDE1NS4xNSA4MC41NzkzIDE1NS4wMDggODAuNDA3NCAxNTQuODI2QzgwLjIzODIgMTU0LjY0NCA4MC4xMDggMTU0LjQyNyA4MC4wMTY4IDE1NC4xNzdDNzkuOTI1NyAxNTMuOTI3IDc5Ljg4MDEgMTUzLjY1NCA3OS44ODAxIDE1My4zNTdWMTUzLjE5M0M3OS44ODAxIDE1Mi44NDkgNzkuOTMwOSAxNTIuNTQzIDgwLjAzMjQgMTUyLjI3NUM4MC4xMzQgMTUyLjAwNCA4MC4yNzIgMTUxLjc3NSA4MC40NDY1IDE1MS41ODhDODAuNjIxIDE1MS40IDgwLjgxODkgMTUxLjI1OCA4MS4wNDAyIDE1MS4xNjJDODEuMjYxNiAxNTEuMDY2IDgxLjQ5MDggMTUxLjAxNyA4MS43Mjc3IDE1MS4wMTdDODIuMDI5OCAxNTEuMDE3IDgyLjI5MDIgMTUxLjA2OSA4Mi41MDkgMTUxLjE3NEM4Mi43MzA0IDE1MS4yNzggODIuOTExMyAxNTEuNDI0IDgzLjA1MiAxNTEuNjExQzgzLjE5MjYgMTUxLjc5NiA4My4yOTY4IDE1Mi4wMTUgODMuMzY0NSAxNTIuMjY3QzgzLjQzMjIgMTUyLjUxNyA4My40NjYgMTUyLjc5MSA4My40NjYgMTUzLjA4OFYxNTMuNDEySDgwLjMwOThWMTUyLjgyMkg4Mi43NDM0VjE1Mi43NjdDODIuNzMzIDE1Mi41OCA4Mi42OTM5IDE1Mi4zOTggODIuNjI2MiAxNTIuMjJDODIuNTYxMSAxNTIuMDQzIDgyLjQ1NjkgMTUxLjg5OCA4Mi4zMTM3IDE1MS43ODNDODIuMTcwNSAxNTEuNjY4IDgxLjk3NTEgMTUxLjYxMSA4MS43Mjc3IDE1MS42MTFDODEuNTYzNyAxNTEuNjExIDgxLjQxMjYgMTUxLjY0NiA4MS4yNzQ2IDE1MS43MTdDODEuMTM2NiAxNTEuNzg0IDgxLjAxODEgMTUxLjg4NiA4MC45MTkyIDE1Mi4wMjFDODAuODIwMiAxNTIuMTU3IDgwLjc0MzQgMTUyLjMyMiA4MC42ODg3IDE1Mi41MTdDODAuNjM0IDE1Mi43MTMgODAuNjA2NyAxNTIuOTM4IDgwLjYwNjcgMTUzLjE5M1YxNTMuMzU3QzgwLjYwNjcgMTUzLjU1OCA4MC42MzQgMTUzLjc0NyA4MC42ODg3IDE1My45MjRDODAuNzQ2IDE1NC4wOTggODAuODI4IDE1NC4yNTIgODAuOTM0OCAxNTQuMzg1QzgxLjA0NDIgMTU0LjUxNyA4MS4xNzU3IDE1NC42MjIgODEuMzI5MyAxNTQuNjk3QzgxLjQ4NTYgMTU0Ljc3MyA4MS42NjI2IDE1NC44MSA4MS44NjA2IDE1NC44MUM4Mi4xMTU4IDE1NC44MSA4Mi4zMzE5IDE1NC43NTggODIuNTA5IDE1NC42NTRDODIuNjg2MSAxNTQuNTUgODIuODQxIDE1NC40MTEgODIuOTczOCAxNTQuMjM2TDgzLjQxMTMgMTU0LjU4NEM4My4zMjAyIDE1NC43MjIgODMuMjA0MyAxNTQuODUzIDgzLjA2MzcgMTU0Ljk3OEM4Mi45MjMxIDE1NS4xMDMgODIuNzQ5OSAxNTUuMjA1IDgyLjU0NDIgMTU1LjI4M0M4Mi4zNDEgMTU1LjM2MSA4Mi4xMDAxIDE1NS40IDgxLjgyMTUgMTU1LjRaTTg0LjM4ODUgMTQ5LjMyMkg4NS4xMTUxVjE1NC41MDJMODUuMDUyNiAxNTUuMzIySDg0LjM4ODVWMTQ5LjMyMlpNODcuOTcwNSAxNTMuMTc0VjE1My4yNTZDODcuOTcwNSAxNTMuNTYzIDg3LjkzNDEgMTUzLjg0OCA4Ny44NjEyIDE1NC4xMTFDODcuNzg4MiAxNTQuMzcyIDg3LjY4MTUgMTU0LjU5OCA4Ny41NDA4IDE1NC43OTFDODcuNDAwMiAxNTQuOTgzIDg3LjIyODMgMTU1LjEzMyA4Ny4wMjUyIDE1NS4yNEM4Ni44MjIxIDE1NS4zNDcgODYuNTg5IDE1NS40IDg2LjMyNiAxNTUuNEM4Ni4wNTc4IDE1NS40IDg1LjgyMjEgMTU1LjM1NSA4NS42MTkgMTU1LjI2M0M4NS40MTg1IDE1NS4xNyA4NS4yNDkyIDE1NS4wMzYgODUuMTExMiAxNTQuODYxQzg0Ljk3MzEgMTU0LjY4NyA4NC44NjI1IDE1NC40NzYgODQuNzc5MSAxNTQuMjI4Qzg0LjY5ODQgMTUzLjk4MSA4NC42NDI0IDE1My43MDIgODQuNjExMiAxNTMuMzkyVjE1My4wMzNDODQuNjQyNCAxNTIuNzIgODQuNjk4NCAxNTIuNDQxIDg0Ljc3OTEgMTUyLjE5M0M4NC44NjI1IDE1MS45NDYgODQuOTczMSAxNTEuNzM1IDg1LjExMTIgMTUxLjU2Qzg1LjI0OTIgMTUxLjM4MyA4NS40MTg1IDE1MS4yNDkgODUuNjE5IDE1MS4xNThDODUuODE5NSAxNTEuMDY0IDg2LjA1MjYgMTUxLjAxNyA4Ni4zMTgyIDE1MS4wMTdDODYuNTgzOCAxNTEuMDE3IDg2LjgxOTUgMTUxLjA2OSA4Ny4wMjUyIDE1MS4xNzRDODcuMjMxIDE1MS4yNzUgODcuNDAyOCAxNTEuNDIxIDg3LjU0MDggMTUxLjYxMUM4Ny42ODE1IDE1MS44MDEgODcuNzg4MiAxNTIuMDI5IDg3Ljg2MTIgMTUyLjI5NUM4Ny45MzQxIDE1Mi41NTggODcuOTcwNSAxNTIuODUxIDg3Ljk3MDUgMTUzLjE3NFpNODcuMjQ0IDE1My4yNTZWMTUzLjE3NEM4Ny4yNDQgMTUyLjk2MyA4Ny4yMjQ0IDE1Mi43NjUgODcuMTg1NCAxNTIuNThDODcuMTQ2MyAxNTIuMzkyIDg3LjA4MzggMTUyLjIyOCA4Ni45OTc5IDE1Mi4wODhDODYuOTExOSAxNTEuOTQ0IDg2Ljc5ODcgMTUxLjgzMiA4Ni42NTggMTUxLjc1MkM4Ni41MTc0IDE1MS42NjggODYuMzQ0MiAxNTEuNjI3IDg2LjEzODUgMTUxLjYyN0M4NS45NTYyIDE1MS42MjcgODUuNzk3NCAxNTEuNjU4IDg1LjY2MTkgMTUxLjcyQzg1LjUyOTEgMTUxLjc4MyA4NS40MTU4IDE1MS44NjggODUuMzIyMSAxNTEuOTc0Qzg1LjIyODMgMTUyLjA3OSA4NS4xNTE1IDE1Mi4xOTggODUuMDkxNiAxNTIuMzM0Qzg1LjAzNDMgMTUyLjQ2NyA4NC45OTE0IDE1Mi42MDUgODQuOTYyNyAxNTIuNzQ4VjE1My42ODlDODUuMDA0NCAxNTMuODcyIDg1LjA3MjEgMTU0LjA0NyA4NS4xNjU4IDE1NC4yMTdDODUuMjYyMiAxNTQuMzgzIDg1LjM4OTggMTU0LjUyIDg1LjU0ODcgMTU0LjYyN0M4NS43MTAxIDE1NC43MzMgODUuOTA5MyAxNTQuNzg3IDg2LjE0NjMgMTU0Ljc4N0M4Ni4zNDE2IDE1NC43ODcgODYuNTA4MyAxNTQuNzQ4IDg2LjY0NjMgMTU0LjY3Qzg2Ljc4NjkgMTU0LjU4OSA4Ni45MDAyIDE1NC40NzggODYuOTg2MiAxNTQuMzM4Qzg3LjA3NDcgMTU0LjE5NyA4Ny4xMzk4IDE1NC4wMzQgODcuMTgxNSAxNTMuODQ5Qzg3LjIyMzEgMTUzLjY2NCA4Ny4yNDQgMTUzLjQ2NyA4Ny4yNDQgMTUzLjI1NloiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuNTQiLz4KPC9nPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDJfNDE4NF85NDUyNykiPgo8bGluZSB4MT0iMTExLjI1IiB5MT0iMTQ3LjA3MiIgeDI9IjExMS4yNSIgeTI9IjE0Ni4yNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuNSIgc3Ryb2tlLXdpZHRoPSIwLjUiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz4KPHBhdGggZD0iTTEwMy4zMDkgMTUyLjAyNVYxNTIuODkyQzEwMy4zMDkgMTUzLjM1OCAxMDMuMjY3IDE1My43NTIgMTAzLjE4NCAxNTQuMDcyQzEwMy4xMDEgMTU0LjM5MiAxMDIuOTgxIDE1NC42NSAxMDIuODI1IDE1NC44NDVDMTAyLjY2OCAxNTUuMDQxIDEwMi40OCAxNTUuMTgzIDEwMi4yNTggMTU1LjI3MUMxMDIuMDQgMTU1LjM1NyAxMDEuNzkyIDE1NS40IDEwMS41MTYgMTU1LjRDMTAxLjI5NyAxNTUuNCAxMDEuMDk2IDE1NS4zNzMgMTAwLjkxMSAxNTUuMzE4QzEwMC43MjYgMTU1LjI2MyAxMDAuNTU5IDE1NS4xNzYgMTAwLjQxMSAxNTUuMDU2QzEwMC4yNjUgMTU0LjkzNCAxMDAuMTQgMTU0Ljc3NSAxMDAuMDM2IDE1NC41OEM5OS45MzE1IDE1NC4zODUgOTkuODUyMSAxNTQuMTQ4IDk5Ljc5NzQgMTUzLjg2OUM5OS43NDI3IDE1My41OSA5OS43MTU0IDE1My4yNjUgOTkuNzE1NCAxNTIuODkyVjE1Mi4wMjVDOTkuNzE1NCAxNTEuNTU5IDk5Ljc1NyAxNTEuMTY4IDk5Ljg0MDQgMTUwLjg1M0M5OS45MjYzIDE1MC41MzggMTAwLjA0NyAxNTAuMjg2IDEwMC4yMDQgMTUwLjA5NUMxMDAuMzYgMTQ5LjkwMyAxMDAuNTQ3IDE0OS43NjUgMTAwLjc2NiAxNDkuNjgxQzEwMC45ODcgMTQ5LjU5OCAxMDEuMjM1IDE0OS41NTYgMTAxLjUwOCAxNDkuNTU2QzEwMS43MyAxNDkuNTU2IDEwMS45MzMgMTQ5LjU4NCAxMDIuMTE4IDE0OS42MzhDMTAyLjMwNSAxNDkuNjkxIDEwMi40NzIgMTQ5Ljc3NSAxMDIuNjE4IDE0OS44OTJDMTAyLjc2NCAxNTAuMDA3IDEwMi44ODcgMTUwLjE2MSAxMDIuOTg5IDE1MC4zNTNDMTAzLjA5MyAxNTAuNTQzIDEwMy4xNzIgMTUwLjc3NiAxMDMuMjI3IDE1MS4wNTJDMTAzLjI4MiAxNTEuMzI5IDEwMy4zMDkgMTUxLjY1MyAxMDMuMzA5IDE1Mi4wMjVaTTEwMi41ODMgMTUzLjAxVjE1MS45MDRDMTAyLjU4MyAxNTEuNjQ5IDEwMi41NjcgMTUxLjQyNSAxMDIuNTM2IDE1MS4yMzJDMTAyLjUwNyAxNTEuMDM3IDEwMi40NjQgMTUwLjg3IDEwMi40MDcgMTUwLjczMkMxMDIuMzQ5IDE1MC41OTQgMTAyLjI3NyAxNTAuNDgyIDEwMi4xODggMTUwLjM5NkMxMDIuMTAyIDE1MC4zMSAxMDIuMDAyIDE1MC4yNDggMTAxLjg4NyAxNTAuMjA5QzEwMS43NzUgMTUwLjE2NyAxMDEuNjQ5IDE1MC4xNDYgMTAxLjUwOCAxNTAuMTQ2QzEwMS4zMzYgMTUwLjE0NiAxMDEuMTg0IDE1MC4xNzkgMTAxLjA1MSAxNTAuMjQ0QzEwMC45MTggMTUwLjMwNiAxMDAuODA3IDE1MC40MDcgMTAwLjcxNSAxNTAuNTQ1QzEwMC42MjcgMTUwLjY4MyAxMDAuNTU5IDE1MC44NjQgMTAwLjUxMiAxNTEuMDg4QzEwMC40NjUgMTUxLjMxMiAxMDAuNDQyIDE1MS41ODQgMTAwLjQ0MiAxNTEuOTA0VjE1My4wMUMxMDAuNDQyIDE1My4yNjUgMTAwLjQ1NiAxNTMuNDkgMTAwLjQ4NSAxNTMuNjg1QzEwMC41MTYgMTUzLjg4MSAxMDAuNTYyIDE1NC4wNSAxMDAuNjIyIDE1NC4xOTNDMTAwLjY4MiAxNTQuMzM0IDEwMC43NTQgMTU0LjQ1IDEwMC44NCAxNTQuNTQxQzEwMC45MjYgMTU0LjYzMiAxMDEuMDI1IDE1NC43IDEwMS4xMzcgMTU0Ljc0NEMxMDEuMjUyIDE1NC43ODYgMTAxLjM3OCAxNTQuODA2IDEwMS41MTYgMTU0LjgwNkMxMDEuNjkzIDE1NC44MDYgMTAxLjg0OCAxNTQuNzczIDEwMS45ODEgMTU0LjcwNUMxMDIuMTE0IDE1NC42MzcgMTAyLjIyNCAxNTQuNTMyIDEwMi4zMTMgMTU0LjM4OEMxMDIuNDA0IDE1NC4yNDMgMTAyLjQ3MiAxNTQuMDU2IDEwMi41MTYgMTUzLjgzQzEwMi41NiAxNTMuNjAxIDEwMi41ODMgMTUzLjMyNyAxMDIuNTgzIDE1My4wMVpNMTA1LjM3NiAxNTIuMTIzSDEwNS44OTJDMTA2LjE0NCAxNTIuMTIzIDEwNi4zNTMgMTUyLjA4MSAxMDYuNTE3IDE1MS45OThDMTA2LjY4MyAxNTEuOTEyIDEwNi44MDcgMTUxLjc5NiAxMDYuODg4IDE1MS42NUMxMDYuOTcxIDE1MS41MDIgMTA3LjAxMyAxNTEuMzM1IDEwNy4wMTMgMTUxLjE1QzEwNy4wMTMgMTUwLjkzMSAxMDYuOTc2IDE1MC43NDggMTA2LjkwMyAxNTAuNTk5QzEwNi44MzEgMTUwLjQ1MSAxMDYuNzIxIDE1MC4zMzkgMTA2LjU3NSAxNTAuMjYzQzEwNi40MjkgMTUwLjE4OCAxMDYuMjQ1IDE1MC4xNSAxMDYuMDIxIDE1MC4xNUMxMDUuODE4IDE1MC4xNSAxMDUuNjM4IDE1MC4xOTEgMTA1LjQ4MiAxNTAuMjcxQzEwNS4zMjggMTUwLjM0OSAxMDUuMjA3IDE1MC40NjEgMTA1LjExOCAxNTAuNjA3QzEwNS4wMzIgMTUwLjc1MyAxMDQuOTg5IDE1MC45MjUgMTA0Ljk4OSAxNTEuMTIzSDEwNC4yNjdDMTA0LjI2NyAxNTAuODM0IDEwNC4zNCAxNTAuNTcxIDEwNC40ODUgMTUwLjMzNEMxMDQuNjMxIDE1MC4wOTcgMTA0LjgzNiAxNDkuOTA4IDEwNS4wOTkgMTQ5Ljc2N0MxMDUuMzY0IDE0OS42MjcgMTA1LjY3MiAxNDkuNTU2IDEwNi4wMjEgMTQ5LjU1NkMxMDYuMzY0IDE0OS41NTYgMTA2LjY2NSAxNDkuNjE4IDEwNi45MjMgMTQ5Ljc0QzEwNy4xODEgMTQ5Ljg2IDEwNy4zODEgMTUwLjAzOSAxMDcuNTI1IDE1MC4yNzlDMTA3LjY2OCAxNTAuNTE2IDEwNy43MzkgMTUwLjgxMiAxMDcuNzM5IDE1MS4xNjZDMTA3LjczOSAxNTEuMzA5IDEwNy43MDYgMTUxLjQ2MyAxMDcuNjM4IDE1MS42MjdDMTA3LjU3MyAxNTEuNzg4IDEwNy40NyAxNTEuOTM5IDEwNy4zMjkgMTUyLjA4QzEwNy4xOTEgMTUyLjIyIDEwNy4wMTIgMTUyLjMzNiAxMDYuNzkgMTUyLjQyN0MxMDYuNTY5IDE1Mi41MTYgMTA2LjMwMyAxNTIuNTYgMTA1Ljk5MyAxNTIuNTZIMTA1LjM3NlYxNTIuMTIzWk0xMDUuMzc2IDE1Mi43MTdWMTUyLjI4M0gxMDUuOTkzQzEwNi4zNTUgMTUyLjI4MyAxMDYuNjU1IDE1Mi4zMjYgMTA2Ljg5MiAxNTIuNDEyQzEwNy4xMjkgMTUyLjQ5OCAxMDcuMzE1IDE1Mi42MTIgMTA3LjQ1IDE1Mi43NTZDMTA3LjU4OCAxNTIuODk5IDEwNy42ODUgMTUzLjA1NiAxMDcuNzM5IDE1My4yMjhDMTA3Ljc5NyAxNTMuMzk4IDEwNy44MjUgMTUzLjU2NyAxMDcuODI1IDE1My43MzZDMTA3LjgyNSAxNTQuMDAyIDEwNy43OCAxNTQuMjM3IDEwNy42ODkgMTU0LjQ0M0MxMDcuNiAxNTQuNjQ5IDEwNy40NzQgMTU0LjgyMyAxMDcuMzEgMTU0Ljk2N0MxMDcuMTQ4IDE1NS4xMSAxMDYuOTU4IDE1NS4yMTggMTA2LjczOSAxNTUuMjkxQzEwNi41MjEgMTU1LjM2NCAxMDYuMjgyIDE1NS40IDEwNi4wMjUgMTU1LjRDMTA1Ljc3NyAxNTUuNCAxMDUuNTQ0IDE1NS4zNjUgMTA1LjMyNSAxNTUuMjk1QzEwNS4xMDkgMTU1LjIyNCAxMDQuOTE4IDE1NS4xMjMgMTA0Ljc1MSAxNTQuOTlDMTA0LjU4NCAxNTQuODU1IDEwNC40NTQgMTU0LjY4OSAxMDQuMzYgMTU0LjQ5NEMxMDQuMjY3IDE1NC4yOTYgMTA0LjIyIDE1NC4wNzEgMTA0LjIyIDE1My44MThIMTA0Ljk0M0MxMDQuOTQzIDE1NC4wMTYgMTA0Ljk4NSAxNTQuMTg5IDEwNS4wNzEgMTU0LjMzOEMxMDUuMTYgMTU0LjQ4NiAxMDUuMjg1IDE1NC42MDIgMTA1LjQ0NiAxNTQuNjg1QzEwNS42MSAxNTQuNzY2IDEwNS44MDMgMTU0LjgwNiAxMDYuMDI1IDE1NC44MDZDMTA2LjI0NiAxNTQuODA2IDEwNi40MzYgMTU0Ljc2OSAxMDYuNTk1IDE1NC42OTNDMTA2Ljc1NiAxNTQuNjE1IDEwNi44OCAxNTQuNDk4IDEwNi45NjYgMTU0LjM0MkMxMDcuMDU0IDE1NC4xODUgMTA3LjA5OSAxNTMuOTg5IDEwNy4wOTkgMTUzLjc1MkMxMDcuMDk5IDE1My41MTUgMTA3LjA0OSAxNTMuMzIxIDEwNi45NSAxNTMuMTdDMTA2Ljg1MSAxNTMuMDE2IDEwNi43MTEgMTUyLjkwMyAxMDYuNTI4IDE1Mi44M0MxMDYuMzQ5IDE1Mi43NTQgMTA2LjEzNyAxNTIuNzE3IDEwNS44OTIgMTUyLjcxN0gxMDUuMzc2Wk0xMTEuOTEyIDE0OS42MzVWMTU1LjMyMkgxMTEuMTU5VjE0OS42MzVIMTExLjkxMlpNMTE0LjI5NSAxNTIuMTkzVjE1Mi44MUgxMTEuNzQ4VjE1Mi4xOTNIMTE0LjI5NVpNMTE0LjY4MiAxNDkuNjM1VjE1MC4yNTJIMTExLjc0OFYxNDkuNjM1SDExNC42ODJaTTExNy4yMjIgMTU1LjRDMTE2LjkyNyAxNTUuNCAxMTYuNjYgMTU1LjM1MSAxMTYuNDIxIDE1NS4yNTJDMTE2LjE4NCAxNTUuMTUgMTE1Ljk3OSAxNTUuMDA4IDExNS44MDggMTU0LjgyNkMxMTUuNjM4IDE1NC42NDQgMTE1LjUwOCAxNTQuNDI3IDExNS40MTcgMTU0LjE3N0MxMTUuMzI2IDE1My45MjcgMTE1LjI4IDE1My42NTQgMTE1LjI4IDE1My4zNTdWMTUzLjE5M0MxMTUuMjggMTUyLjg0OSAxMTUuMzMxIDE1Mi41NDMgMTE1LjQzMyAxNTIuMjc1QzExNS41MzQgMTUyLjAwNCAxMTUuNjcyIDE1MS43NzUgMTE1Ljg0NyAxNTEuNTg4QzExNi4wMjEgMTUxLjQgMTE2LjIxOSAxNTEuMjU4IDExNi40NCAxNTEuMTYyQzExNi42NjIgMTUxLjA2NiAxMTYuODkxIDE1MS4wMTcgMTE3LjEyOCAxNTEuMDE3QzExNy40MyAxNTEuMDE3IDExNy42OSAxNTEuMDY5IDExNy45MDkgMTUxLjE3NEMxMTguMTMgMTUxLjI3OCAxMTguMzExIDE1MS40MjQgMTE4LjQ1MiAxNTEuNjExQzExOC41OTMgMTUxLjc5NiAxMTguNjk3IDE1Mi4wMTUgMTE4Ljc2NSAxNTIuMjY3QzExOC44MzIgMTUyLjUxNyAxMTguODY2IDE1Mi43OTEgMTE4Ljg2NiAxNTMuMDg4VjE1My40MTJIMTE1LjcxVjE1Mi44MjJIMTE4LjE0NFYxNTIuNzY3QzExOC4xMzMgMTUyLjU4IDExOC4wOTQgMTUyLjM5OCAxMTguMDI2IDE1Mi4yMkMxMTcuOTYxIDE1Mi4wNDMgMTE3Ljg1NyAxNTEuODk4IDExNy43MTQgMTUxLjc4M0MxMTcuNTcxIDE1MS42NjggMTE3LjM3NSAxNTEuNjExIDExNy4xMjggMTUxLjYxMUMxMTYuOTY0IDE1MS42MTEgMTE2LjgxMyAxNTEuNjQ2IDExNi42NzUgMTUxLjcxN0MxMTYuNTM3IDE1MS43ODQgMTE2LjQxOCAxNTEuODg2IDExNi4zMTkgMTUyLjAyMUMxMTYuMjIgMTUyLjE1NyAxMTYuMTQ0IDE1Mi4zMjIgMTE2LjA4OSAxNTIuNTE3QzExNi4wMzQgMTUyLjcxMyAxMTYuMDA3IDE1Mi45MzggMTE2LjAwNyAxNTMuMTkzVjE1My4zNTdDMTE2LjAwNyAxNTMuNTU4IDExNi4wMzQgMTUzLjc0NyAxMTYuMDg5IDE1My45MjRDMTE2LjE0NiAxNTQuMDk4IDExNi4yMjggMTU0LjI1MiAxMTYuMzM1IDE1NC4zODVDMTE2LjQ0NCAxNTQuNTE3IDExNi41NzYgMTU0LjYyMiAxMTYuNzI5IDE1NC42OTdDMTE2Ljg4NiAxNTQuNzczIDExNy4wNjMgMTU0LjgxIDExNy4yNjEgMTU0LjgxQzExNy41MTYgMTU0LjgxIDExNy43MzIgMTU0Ljc1OCAxMTcuOTA5IDE1NC42NTRDMTE4LjA4NiAxNTQuNTUgMTE4LjI0MSAxNTQuNDExIDExOC4zNzQgMTU0LjIzNkwxMTguODExIDE1NC41ODRDMTE4LjcyIDE1NC43MjIgMTE4LjYwNCAxNTQuODUzIDExOC40NjQgMTU0Ljk3OEMxMTguMzIzIDE1NS4xMDMgMTE4LjE1IDE1NS4yMDUgMTE3Ljk0NCAxNTUuMjgzQzExNy43NDEgMTU1LjM2MSAxMTcuNSAxNTUuNCAxMTcuMjIyIDE1NS40Wk0xMTkuNzg5IDE0OS4zMjJIMTIwLjUxNVYxNTQuNTAyTDEyMC40NTMgMTU1LjMyMkgxMTkuNzg5VjE0OS4zMjJaTTEyMy4zNzEgMTUzLjE3NFYxNTMuMjU2QzEyMy4zNzEgMTUzLjU2MyAxMjMuMzM0IDE1My44NDggMTIzLjI2MSAxNTQuMTExQzEyMy4xODggMTU0LjM3MiAxMjMuMDgyIDE1NC41OTggMTIyLjk0MSAxNTQuNzkxQzEyMi44IDE1NC45ODMgMTIyLjYyOCAxNTUuMTMzIDEyMi40MjUgMTU1LjI0QzEyMi4yMjIgMTU1LjM0NyAxMjEuOTg5IDE1NS40IDEyMS43MjYgMTU1LjRDMTIxLjQ1OCAxNTUuNCAxMjEuMjIyIDE1NS4zNTUgMTIxLjAxOSAxNTUuMjYzQzEyMC44MTkgMTU1LjE3IDEyMC42NDkgMTU1LjAzNiAxMjAuNTExIDE1NC44NjFDMTIwLjM3MyAxNTQuNjg3IDEyMC4yNjMgMTU0LjQ3NiAxMjAuMTc5IDE1NC4yMjhDMTIwLjA5OSAxNTMuOTgxIDEyMC4wNDMgMTUzLjcwMiAxMjAuMDExIDE1My4zOTJWMTUzLjAzM0MxMjAuMDQzIDE1Mi43MiAxMjAuMDk5IDE1Mi40NDEgMTIwLjE3OSAxNTIuMTkzQzEyMC4yNjMgMTUxLjk0NiAxMjAuMzczIDE1MS43MzUgMTIwLjUxMSAxNTEuNTZDMTIwLjY0OSAxNTEuMzgzIDEyMC44MTkgMTUxLjI0OSAxMjEuMDE5IDE1MS4xNThDMTIxLjIyIDE1MS4wNjQgMTIxLjQ1MyAxNTEuMDE3IDEyMS43MTggMTUxLjAxN0MxMjEuOTg0IDE1MS4wMTcgMTIyLjIyIDE1MS4wNjkgMTIyLjQyNSAxNTEuMTc0QzEyMi42MzEgMTUxLjI3NSAxMjIuODAzIDE1MS40MjEgMTIyLjk0MSAxNTEuNjExQzEyMy4wODIgMTUxLjgwMSAxMjMuMTg4IDE1Mi4wMjkgMTIzLjI2MSAxNTIuMjk1QzEyMy4zMzQgMTUyLjU1OCAxMjMuMzcxIDE1Mi44NTEgMTIzLjM3MSAxNTMuMTc0Wk0xMjIuNjQ0IDE1My4yNTZWMTUzLjE3NEMxMjIuNjQ0IDE1Mi45NjMgMTIyLjYyNSAxNTIuNzY1IDEyMi41ODYgMTUyLjU4QzEyMi41NDYgMTUyLjM5MiAxMjIuNDg0IDE1Mi4yMjggMTIyLjM5OCAxNTIuMDg4QzEyMi4zMTIgMTUxLjk0NCAxMjIuMTk5IDE1MS44MzIgMTIyLjA1OCAxNTEuNzUyQzEyMS45MTggMTUxLjY2OCAxMjEuNzQ0IDE1MS42MjcgMTIxLjUzOSAxNTEuNjI3QzEyMS4zNTYgMTUxLjYyNyAxMjEuMTk4IDE1MS42NTggMTIxLjA2MiAxNTEuNzJDMTIwLjkyOSAxNTEuNzgzIDEyMC44MTYgMTUxLjg2OCAxMjAuNzIyIDE1MS45NzRDMTIwLjYyOCAxNTIuMDc5IDEyMC41NTIgMTUyLjE5OCAxMjAuNDkyIDE1Mi4zMzRDMTIwLjQzNCAxNTIuNDY3IDEyMC4zOTIgMTUyLjYwNSAxMjAuMzYzIDE1Mi43NDhWMTUzLjY4OUMxMjAuNDA1IDE1My44NzIgMTIwLjQ3MiAxNTQuMDQ3IDEyMC41NjYgMTU0LjIxN0MxMjAuNjYyIDE1NC4zODMgMTIwLjc5IDE1NC41MiAxMjAuOTQ5IDE1NC42MjdDMTIxLjExIDE1NC43MzMgMTIxLjMwOSAxNTQuNzg3IDEyMS41NDYgMTU0Ljc4N0MxMjEuNzQyIDE1NC43ODcgMTIxLjkwOCAxNTQuNzQ4IDEyMi4wNDYgMTU0LjY3QzEyMi4xODcgMTU0LjU4OSAxMjIuMyAxNTQuNDc4IDEyMi4zODYgMTU0LjMzOEMxMjIuNDc1IDE1NC4xOTcgMTIyLjU0IDE1NC4wMzQgMTIyLjU4MiAxNTMuODQ5QzEyMi42MjMgMTUzLjY2NCAxMjIuNjQ0IDE1My40NjcgMTIyLjY0NCAxNTMuMjU2WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8L2c+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwM180MTg0Xzk0NTI3KSI+CjxsaW5lIHgxPSIxNDYuNjUiIHkxPSIxNDcuMDcyIiB4Mj0iMTQ2LjY1IiB5Mj0iMTQ2LjI1IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC41IiBzdHJva2Utd2lkdGg9IjAuNSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8cGF0aCBkPSJNMTM4LjcwOSAxNTIuMDI1VjE1Mi44OTJDMTM4LjcwOSAxNTMuMzU4IDEzOC42NjcgMTUzLjc1MiAxMzguNTg0IDE1NC4wNzJDMTM4LjUwMSAxNTQuMzkyIDEzOC4zODEgMTU0LjY1IDEzOC4yMjUgMTU0Ljg0NUMxMzguMDY4IDE1NS4wNDEgMTM3Ljg4IDE1NS4xODMgMTM3LjY1OCAxNTUuMjcxQzEzNy40MzkgMTU1LjM1NyAxMzcuMTkyIDE1NS40IDEzNi45MTYgMTU1LjRDMTM2LjY5NyAxNTUuNCAxMzYuNDk1IDE1NS4zNzMgMTM2LjMxMSAxNTUuMzE4QzEzNi4xMjYgMTU1LjI2MyAxMzUuOTU5IDE1NS4xNzYgMTM1LjgxMSAxNTUuMDU2QzEzNS42NjUgMTU0LjkzNCAxMzUuNTQgMTU0Ljc3NSAxMzUuNDM2IDE1NC41OEMxMzUuMzMxIDE1NC4zODUgMTM1LjI1MiAxNTQuMTQ4IDEzNS4xOTcgMTUzLjg2OUMxMzUuMTQzIDE1My41OSAxMzUuMTE1IDE1My4yNjUgMTM1LjExNSAxNTIuODkyVjE1Mi4wMjVDMTM1LjExNSAxNTEuNTU5IDEzNS4xNTcgMTUxLjE2OCAxMzUuMjQgMTUwLjg1M0MxMzUuMzI2IDE1MC41MzggMTM1LjQ0NyAxNTAuMjg2IDEzNS42MDQgMTUwLjA5NUMxMzUuNzYgMTQ5LjkwMyAxMzUuOTQ3IDE0OS43NjUgMTM2LjE2NiAxNDkuNjgxQzEzNi4zODcgMTQ5LjU5OCAxMzYuNjM1IDE0OS41NTYgMTM2LjkwOCAxNDkuNTU2QzEzNy4xMyAxNDkuNTU2IDEzNy4zMzMgMTQ5LjU4NCAxMzcuNTE4IDE0OS42MzhDMTM3LjcwNSAxNDkuNjkxIDEzNy44NzIgMTQ5Ljc3NSAxMzguMDE4IDE0OS44OTJDMTM4LjE2MyAxNTAuMDA3IDEzOC4yODcgMTUwLjE2MSAxMzguMzg5IDE1MC4zNTNDMTM4LjQ5MyAxNTAuNTQzIDEzOC41NzIgMTUwLjc3NiAxMzguNjI3IDE1MS4wNTJDMTM4LjY4MiAxNTEuMzI5IDEzOC43MDkgMTUxLjY1MyAxMzguNzA5IDE1Mi4wMjVaTTEzNy45ODIgMTUzLjAxVjE1MS45MDRDMTM3Ljk4MiAxNTEuNjQ5IDEzNy45NjcgMTUxLjQyNSAxMzcuOTM2IDE1MS4yMzJDMTM3LjkwNyAxNTEuMDM3IDEzNy44NjQgMTUwLjg3IDEzNy44MDcgMTUwLjczMkMxMzcuNzQ5IDE1MC41OTQgMTM3LjY3NiAxNTAuNDgyIDEzNy41ODggMTUwLjM5NkMxMzcuNTAyIDE1MC4zMSAxMzcuNDAyIDE1MC4yNDggMTM3LjI4NyAxNTAuMjA5QzEzNy4xNzUgMTUwLjE2NyAxMzcuMDQ5IDE1MC4xNDYgMTM2LjkwOCAxNTAuMTQ2QzEzNi43MzYgMTUwLjE0NiAxMzYuNTg0IDE1MC4xNzkgMTM2LjQ1MSAxNTAuMjQ0QzEzNi4zMTggMTUwLjMwNiAxMzYuMjA2IDE1MC40MDcgMTM2LjExNSAxNTAuNTQ1QzEzNi4wMjcgMTUwLjY4MyAxMzUuOTU5IDE1MC44NjQgMTM1LjkxMiAxNTEuMDg4QzEzNS44NjUgMTUxLjMxMiAxMzUuODQyIDE1MS41ODQgMTM1Ljg0MiAxNTEuOTA0VjE1My4wMUMxMzUuODQyIDE1My4yNjUgMTM1Ljg1NiAxNTMuNDkgMTM1Ljg4NSAxNTMuNjg1QzEzNS45MTYgMTUzLjg4MSAxMzUuOTYyIDE1NC4wNSAxMzYuMDIyIDE1NC4xOTNDMTM2LjA4MSAxNTQuMzM0IDEzNi4xNTQgMTU0LjQ1IDEzNi4yNCAxNTQuNTQxQzEzNi4zMjYgMTU0LjYzMiAxMzYuNDI1IDE1NC43IDEzNi41MzcgMTU0Ljc0NEMxMzYuNjUyIDE1NC43ODYgMTM2Ljc3OCAxNTQuODA2IDEzNi45MTYgMTU0LjgwNkMxMzcuMDkzIDE1NC44MDYgMTM3LjI0OCAxNTQuNzczIDEzNy4zODEgMTU0LjcwNUMxMzcuNTE0IDE1NC42MzcgMTM3LjYyNCAxNTQuNTMyIDEzNy43MTMgMTU0LjM4OEMxMzcuODA0IDE1NC4yNDMgMTM3Ljg3MiAxNTQuMDU2IDEzNy45MTYgMTUzLjgzQzEzNy45NiAxNTMuNjAxIDEzNy45ODIgMTUzLjMyNyAxMzcuOTgyIDE1My4wMVpNMTQzLjU2NSAxNTMuNDA4VjE1NC4wMDJIMTM5LjQ1NlYxNTMuNTc2TDE0Mi4wMDMgMTQ5LjYzNUgxNDIuNTkyTDE0MS45NiAxNTAuNzc1TDE0MC4yNzYgMTUzLjQwOEgxNDMuNTY1Wk0xNDIuNzcyIDE0OS42MzVWMTU1LjMyMkgxNDIuMDQ5VjE0OS42MzVIMTQyLjc3MlpNMTQ3LjMxMiAxNDkuNjM1VjE1NS4zMjJIMTQ2LjU1OFYxNDkuNjM1SDE0Ny4zMTJaTTE0OS42OTUgMTUyLjE5M1YxNTIuODFIMTQ3LjE0OFYxNTIuMTkzSDE0OS42OTVaTTE1MC4wODIgMTQ5LjYzNVYxNTAuMjUySDE0Ny4xNDhWMTQ5LjYzNUgxNTAuMDgyWk0xNTIuNjIyIDE1NS40QzE1Mi4zMjcgMTU1LjQgMTUyLjA2IDE1NS4zNTEgMTUxLjgyMSAxNTUuMjUyQzE1MS41ODQgMTU1LjE1IDE1MS4zNzkgMTU1LjAwOCAxNTEuMjA3IDE1NC44MjZDMTUxLjAzOCAxNTQuNjQ0IDE1MC45MDggMTU0LjQyNyAxNTAuODE3IDE1NC4xNzdDMTUwLjcyNiAxNTMuOTI3IDE1MC42OCAxNTMuNjU0IDE1MC42OCAxNTMuMzU3VjE1My4xOTNDMTUwLjY4IDE1Mi44NDkgMTUwLjczMSAxNTIuNTQzIDE1MC44MzIgMTUyLjI3NUMxNTAuOTM0IDE1Mi4wMDQgMTUxLjA3MiAxNTEuNzc1IDE1MS4yNDcgMTUxLjU4OEMxNTEuNDIxIDE1MS40IDE1MS42MTkgMTUxLjI1OCAxNTEuODQgMTUxLjE2MkMxNTIuMDYyIDE1MS4wNjYgMTUyLjI5MSAxNTEuMDE3IDE1Mi41MjggMTUxLjAxN0MxNTIuODMgMTUxLjAxNyAxNTMuMDkgMTUxLjA2OSAxNTMuMzA5IDE1MS4xNzRDMTUzLjUzIDE1MS4yNzggMTUzLjcxMSAxNTEuNDI0IDE1My44NTIgMTUxLjYxMUMxNTMuOTkzIDE1MS43OTYgMTU0LjA5NyAxNTIuMDE1IDE1NC4xNjUgMTUyLjI2N0MxNTQuMjMyIDE1Mi41MTcgMTU0LjI2NiAxNTIuNzkxIDE1NC4yNjYgMTUzLjA4OFYxNTMuNDEySDE1MS4xMVYxNTIuODIySDE1My41NDNWMTUyLjc2N0MxNTMuNTMzIDE1Mi41OCAxNTMuNDk0IDE1Mi4zOTggMTUzLjQyNiAxNTIuMjJDMTUzLjM2MSAxNTIuMDQzIDE1My4yNTcgMTUxLjg5OCAxNTMuMTE0IDE1MS43ODNDMTUyLjk3MSAxNTEuNjY4IDE1Mi43NzUgMTUxLjYxMSAxNTIuNTI4IDE1MS42MTFDMTUyLjM2NCAxNTEuNjExIDE1Mi4yMTMgMTUxLjY0NiAxNTIuMDc1IDE1MS43MTdDMTUxLjkzNyAxNTEuNzg0IDE1MS44MTggMTUxLjg4NiAxNTEuNzE5IDE1Mi4wMjFDMTUxLjYyIDE1Mi4xNTcgMTUxLjU0MyAxNTIuMzIyIDE1MS40ODkgMTUyLjUxN0MxNTEuNDM0IDE1Mi43MTMgMTUxLjQwNyAxNTIuOTM4IDE1MS40MDcgMTUzLjE5M1YxNTMuMzU3QzE1MS40MDcgMTUzLjU1OCAxNTEuNDM0IDE1My43NDcgMTUxLjQ4OSAxNTMuOTI0QzE1MS41NDYgMTU0LjA5OCAxNTEuNjI4IDE1NC4yNTIgMTUxLjczNSAxNTQuMzg1QzE1MS44NDQgMTU0LjUxNyAxNTEuOTc2IDE1NC42MjIgMTUyLjEyOSAxNTQuNjk3QzE1Mi4yODYgMTU0Ljc3MyAxNTIuNDYzIDE1NC44MSAxNTIuNjYxIDE1NC44MUMxNTIuOTE2IDE1NC44MSAxNTMuMTMyIDE1NC43NTggMTUzLjMwOSAxNTQuNjU0QzE1My40ODYgMTU0LjU1IDE1My42NDEgMTU0LjQxMSAxNTMuNzc0IDE1NC4yMzZMMTU0LjIxMSAxNTQuNTg0QzE1NC4xMiAxNTQuNzIyIDE1NC4wMDQgMTU0Ljg1MyAxNTMuODY0IDE1NC45NzhDMTUzLjcyMyAxNTUuMTAzIDE1My41NSAxNTUuMjA1IDE1My4zNDQgMTU1LjI4M0MxNTMuMTQxIDE1NS4zNjEgMTUyLjkgMTU1LjQgMTUyLjYyMiAxNTUuNFpNMTU1LjE4OSAxNDkuMzIySDE1NS45MTVWMTU0LjUwMkwxNTUuODUzIDE1NS4zMjJIMTU1LjE4OVYxNDkuMzIyWk0xNTguNzcxIDE1My4xNzRWMTUzLjI1NkMxNTguNzcxIDE1My41NjMgMTU4LjczNCAxNTMuODQ4IDE1OC42NjEgMTU0LjExMUMxNTguNTg4IDE1NC4zNzIgMTU4LjQ4MiAxNTQuNTk4IDE1OC4zNDEgMTU0Ljc5MUMxNTguMiAxNTQuOTgzIDE1OC4wMjggMTU1LjEzMyAxNTcuODI1IDE1NS4yNEMxNTcuNjIyIDE1NS4zNDcgMTU3LjM4OSAxNTUuNCAxNTcuMTI2IDE1NS40QzE1Ni44NTggMTU1LjQgMTU2LjYyMiAxNTUuMzU1IDE1Ni40MTkgMTU1LjI2M0MxNTYuMjE4IDE1NS4xNyAxNTYuMDQ5IDE1NS4wMzYgMTU1LjkxMSAxNTQuODYxQzE1NS43NzMgMTU0LjY4NyAxNTUuNjYzIDE1NC40NzYgMTU1LjU3OSAxNTQuMjI4QzE1NS40OTggMTUzLjk4MSAxNTUuNDQyIDE1My43MDIgMTU1LjQxMSAxNTMuMzkyVjE1My4wMzNDMTU1LjQ0MiAxNTIuNzIgMTU1LjQ5OCAxNTIuNDQxIDE1NS41NzkgMTUyLjE5M0MxNTUuNjYzIDE1MS45NDYgMTU1Ljc3MyAxNTEuNzM1IDE1NS45MTEgMTUxLjU2QzE1Ni4wNDkgMTUxLjM4MyAxNTYuMjE4IDE1MS4yNDkgMTU2LjQxOSAxNTEuMTU4QzE1Ni42MiAxNTEuMDY0IDE1Ni44NTMgMTUxLjAxNyAxNTcuMTE4IDE1MS4wMTdDMTU3LjM4NCAxNTEuMDE3IDE1Ny42MiAxNTEuMDY5IDE1Ny44MjUgMTUxLjE3NEMxNTguMDMxIDE1MS4yNzUgMTU4LjIwMyAxNTEuNDIxIDE1OC4zNDEgMTUxLjYxMUMxNTguNDgyIDE1MS44MDEgMTU4LjU4OCAxNTIuMDI5IDE1OC42NjEgMTUyLjI5NUMxNTguNzM0IDE1Mi41NTggMTU4Ljc3MSAxNTIuODUxIDE1OC43NzEgMTUzLjE3NFpNMTU4LjA0NCAxNTMuMjU2VjE1My4xNzRDMTU4LjA0NCAxNTIuOTYzIDE1OC4wMjQgMTUyLjc2NSAxNTcuOTg1IDE1Mi41OEMxNTcuOTQ2IDE1Mi4zOTIgMTU3Ljg4NCAxNTIuMjI4IDE1Ny43OTggMTUyLjA4OEMxNTcuNzEyIDE1MS45NDQgMTU3LjU5OSAxNTEuODMyIDE1Ny40NTggMTUxLjc1MkMxNTcuMzE3IDE1MS42NjggMTU3LjE0NCAxNTEuNjI3IDE1Ni45MzkgMTUxLjYyN0MxNTYuNzU2IDE1MS42MjcgMTU2LjU5NyAxNTEuNjU4IDE1Ni40NjIgMTUxLjcyQzE1Ni4zMjkgMTUxLjc4MyAxNTYuMjE2IDE1MS44NjggMTU2LjEyMiAxNTEuOTc0QzE1Ni4wMjggMTUyLjA3OSAxNTUuOTUyIDE1Mi4xOTggMTU1Ljg5MiAxNTIuMzM0QzE1NS44MzQgMTUyLjQ2NyAxNTUuNzkxIDE1Mi42MDUgMTU1Ljc2MyAxNTIuNzQ4VjE1My42ODlDMTU1LjgwNCAxNTMuODcyIDE1NS44NzIgMTU0LjA0NyAxNTUuOTY2IDE1NC4yMTdDMTU2LjA2MiAxNTQuMzgzIDE1Ni4xOSAxNTQuNTIgMTU2LjM0OSAxNTQuNjI3QzE1Ni41MSAxNTQuNzMzIDE1Ni43MDkgMTU0Ljc4NyAxNTYuOTQ2IDE1NC43ODdDMTU3LjE0MiAxNTQuNzg3IDE1Ny4zMDggMTU0Ljc0OCAxNTcuNDQ2IDE1NC42N0MxNTcuNTg3IDE1NC41ODkgMTU3LjcgMTU0LjQ3OCAxNTcuNzg2IDE1NC4zMzhDMTU3Ljg3NSAxNTQuMTk3IDE1Ny45NCAxNTQuMDM0IDE1Ny45ODIgMTUzLjg0OUMxNTguMDIzIDE1My42NjQgMTU4LjA0NCAxNTMuNDY3IDE1OC4wNDQgMTUzLjI1NloiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuNTQiLz4KPC9nPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDRfNDE4NF85NDUyNykiPgo8bGluZSB4MT0iMTgyLjA1IiB5MT0iMTQ3LjA3MiIgeDI9IjE4Mi4wNSIgeTI9IjE0Ni4yNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuNSIgc3Ryb2tlLXdpZHRoPSIwLjUiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz4KPHBhdGggZD0iTTE3NC4xMDkgMTUyLjAyNVYxNTIuODkyQzE3NC4xMDkgMTUzLjM1OCAxNzQuMDY3IDE1My43NTIgMTczLjk4NCAxNTQuMDcyQzE3My45MDEgMTU0LjM5MiAxNzMuNzgxIDE1NC42NSAxNzMuNjI1IDE1NC44NDVDMTczLjQ2OSAxNTUuMDQxIDE3My4yOCAxNTUuMTgzIDE3My4wNTggMTU1LjI3MUMxNzIuODQgMTU1LjM1NyAxNzIuNTkyIDE1NS40IDE3Mi4zMTYgMTU1LjRDMTcyLjA5NyAxNTUuNCAxNzEuODk2IDE1NS4zNzMgMTcxLjcxMSAxNTUuMzE4QzE3MS41MjYgMTU1LjI2MyAxNzEuMzU5IDE1NS4xNzYgMTcxLjIxMSAxNTUuMDU2QzE3MS4wNjUgMTU0LjkzNCAxNzAuOTQgMTU0Ljc3NSAxNzAuODM2IDE1NC41OEMxNzAuNzMyIDE1NC4zODUgMTcwLjY1MiAxNTQuMTQ4IDE3MC41OTcgMTUzLjg2OUMxNzAuNTQzIDE1My41OSAxNzAuNTE1IDE1My4yNjUgMTcwLjUxNSAxNTIuODkyVjE1Mi4wMjVDMTcwLjUxNSAxNTEuNTU5IDE3MC41NTcgMTUxLjE2OCAxNzAuNjQgMTUwLjg1M0MxNzAuNzI2IDE1MC41MzggMTcwLjg0NyAxNTAuMjg2IDE3MS4wMDQgMTUwLjA5NUMxNzEuMTYgMTQ5LjkwMyAxNzEuMzQ3IDE0OS43NjUgMTcxLjU2NiAxNDkuNjgxQzE3MS43ODggMTQ5LjU5OCAxNzIuMDM1IDE0OS41NTYgMTcyLjMwOCAxNDkuNTU2QzE3Mi41MyAxNDkuNTU2IDE3Mi43MzMgMTQ5LjU4NCAxNzIuOTE4IDE0OS42MzhDMTczLjEwNSAxNDkuNjkxIDE3My4yNzIgMTQ5Ljc3NSAxNzMuNDE4IDE0OS44OTJDMTczLjU2NCAxNTAuMDA3IDE3My42ODcgMTUwLjE2MSAxNzMuNzg5IDE1MC4zNTNDMTczLjg5MyAxNTAuNTQzIDE3My45NzIgMTUwLjc3NiAxNzQuMDI3IDE1MS4wNTJDMTc0LjA4MiAxNTEuMzI5IDE3NC4xMDkgMTUxLjY1MyAxNzQuMTA5IDE1Mi4wMjVaTTE3My4zODMgMTUzLjAxVjE1MS45MDRDMTczLjM4MyAxNTEuNjQ5IDE3My4zNjcgMTUxLjQyNSAxNzMuMzM2IDE1MS4yMzJDMTczLjMwNyAxNTEuMDM3IDE3My4yNjQgMTUwLjg3IDE3My4yMDcgMTUwLjczMkMxNzMuMTUgMTUwLjU5NCAxNzMuMDc3IDE1MC40ODIgMTcyLjk4OCAxNTAuMzk2QzE3Mi45MDIgMTUwLjMxIDE3Mi44MDIgMTUwLjI0OCAxNzIuNjg3IDE1MC4yMDlDMTcyLjU3NSAxNTAuMTY3IDE3Mi40NDkgMTUwLjE0NiAxNzIuMzA4IDE1MC4xNDZDMTcyLjEzNiAxNTAuMTQ2IDE3MS45ODQgMTUwLjE3OSAxNzEuODUxIDE1MC4yNDRDMTcxLjcxOSAxNTAuMzA2IDE3MS42MDcgMTUwLjQwNyAxNzEuNTE1IDE1MC41NDVDMTcxLjQyNyAxNTAuNjgzIDE3MS4zNTkgMTUwLjg2NCAxNzEuMzEyIDE1MS4wODhDMTcxLjI2NSAxNTEuMzEyIDE3MS4yNDIgMTUxLjU4NCAxNzEuMjQyIDE1MS45MDRWMTUzLjAxQzE3MS4yNDIgMTUzLjI2NSAxNzEuMjU2IDE1My40OSAxNzEuMjg1IDE1My42ODVDMTcxLjMxNiAxNTMuODgxIDE3MS4zNjIgMTU0LjA1IDE3MS40MjIgMTU0LjE5M0MxNzEuNDgyIDE1NC4zMzQgMTcxLjU1NCAxNTQuNDUgMTcxLjY0IDE1NC41NDFDMTcxLjcyNiAxNTQuNjMyIDE3MS44MjUgMTU0LjcgMTcxLjkzNyAxNTQuNzQ0QzE3Mi4wNTIgMTU0Ljc4NiAxNzIuMTc4IDE1NC44MDYgMTcyLjMxNiAxNTQuODA2QzE3Mi40OTMgMTU0LjgwNiAxNzIuNjQ4IDE1NC43NzMgMTcyLjc4MSAxNTQuNzA1QzE3Mi45MTQgMTU0LjYzNyAxNzMuMDI1IDE1NC41MzIgMTczLjExMyAxNTQuMzg4QzE3My4yMDQgMTU0LjI0MyAxNzMuMjcyIDE1NC4wNTYgMTczLjMxNiAxNTMuODNDMTczLjM2IDE1My42MDEgMTczLjM4MyAxNTMuMzI3IDE3My4zODMgMTUzLjAxWk0xNzYuMDM2IDE1Mi42MTVMMTc1LjQ1NyAxNTIuNDY3TDE3NS43NDMgMTQ5LjYzNUgxNzguNjYxVjE1MC4zMDJIMTc2LjM1NkwxNzYuMTg0IDE1MS44NDlDMTc2LjI4OCAxNTEuNzg5IDE3Ni40MiAxNTEuNzMzIDE3Ni41NzkgMTUxLjY4MUMxNzYuNzQgMTUxLjYyOSAxNzYuOTI1IDE1MS42MDMgMTc3LjEzMyAxNTEuNjAzQzE3Ny4zOTYgMTUxLjYwMyAxNzcuNjMyIDE1MS42NDkgMTc3Ljg0IDE1MS43NEMxNzguMDQ5IDE1MS44MjkgMTc4LjIyNiAxNTEuOTU2IDE3OC4zNzEgMTUyLjEyM0MxNzguNTIgMTUyLjI4OSAxNzguNjMzIDE1Mi40OSAxNzguNzExIDE1Mi43MjRDMTc4Ljc4OSAxNTIuOTU5IDE3OC44MjkgMTUzLjIyIDE3OC44MjkgMTUzLjUxQzE3OC44MjkgMTUzLjc4MyAxNzguNzkxIDE1NC4wMzQgMTc4LjcxNSAxNTQuMjYzQzE3OC42NDIgMTU0LjQ5MyAxNzguNTMyIDE1NC42OTMgMTc4LjM4MyAxNTQuODY1QzE3OC4yMzUgMTU1LjAzNCAxNzguMDQ3IDE1NS4xNjYgMTc3LjgyMSAxNTUuMjZDMTc3LjU5NyAxNTUuMzUzIDE3Ny4zMzIgMTU1LjQgMTc3LjAyOCAxNTUuNEMxNzYuNzk5IDE1NS40IDE3Ni41ODEgMTU1LjM2OSAxNzYuMzc1IDE1NS4zMDZDMTc2LjE3MiAxNTUuMjQxIDE3NS45OSAxNTUuMTQ0IDE3NS44MjkgMTU1LjAxM0MxNzUuNjcgMTU0Ljg4MSAxNzUuNTM5IDE1NC43MTcgMTc1LjQzOCAxNTQuNTIxQzE3NS4zMzkgMTU0LjMyMyAxNzUuMjc2IDE1NC4wOTIgMTc1LjI1IDE1My44MjZIMTc1LjkzOEMxNzUuOTY5IDE1NC4wMzkgMTc2LjAzMiAxNTQuMjE5IDE3Ni4xMjUgMTU0LjM2NUMxNzYuMjE5IDE1NC41MTEgMTc2LjM0MiAxNTQuNjIyIDE3Ni40OTMgMTU0LjY5N0MxNzYuNjQ2IDE1NC43NyAxNzYuODI1IDE1NC44MDYgMTc3LjAyOCAxNTQuODA2QzE3Ny4yIDE1NC44MDYgMTc3LjM1MiAxNTQuNzc2IDE3Ny40ODUgMTU0LjcxN0MxNzcuNjE4IDE1NC42NTcgMTc3LjczIDE1NC41NzEgMTc3LjgyMSAxNTQuNDU5QzE3Ny45MTIgMTU0LjM0NyAxNzcuOTgxIDE1NC4yMTEgMTc4LjAyOCAxNTQuMDUyQzE3OC4wNzcgMTUzLjg5NCAxNzguMTAyIDE1My43MTUgMTc4LjEwMiAxNTMuNTE3QzE3OC4xMDIgMTUzLjMzOCAxNzguMDc3IDE1My4xNzEgMTc4LjAyOCAxNTMuMDE3QzE3Ny45NzggMTUyLjg2NCAxNzcuOTA0IDE1Mi43MyAxNzcuODA1IDE1Mi42MTVDMTc3LjcwOSAxNTIuNSAxNzcuNTkgMTUyLjQxMiAxNzcuNDUgMTUyLjM0OUMxNzcuMzA5IDE1Mi4yODQgMTc3LjE0OCAxNTIuMjUyIDE3Ni45NjUgMTUyLjI1MkMxNzYuNzIzIDE1Mi4yNTIgMTc2LjUzOSAxNTIuMjg0IDE3Ni40MTQgMTUyLjM0OUMxNzYuMjkyIDE1Mi40MTQgMTc2LjE2NiAxNTIuNTAzIDE3Ni4wMzYgMTUyLjYxNVpNMTgyLjcxMyAxNDkuNjM1VjE1NS4zMjJIMTgxLjk1OVYxNDkuNjM1SDE4Mi43MTNaTTE4NS4wOTUgMTUyLjE5M1YxNTIuODFIMTgyLjU0OFYxNTIuMTkzSDE4NS4wOTVaTTE4NS40ODIgMTQ5LjYzNVYxNTAuMjUySDE4Mi41NDhWMTQ5LjYzNUgxODUuNDgyWk0xODguMDIyIDE1NS40QzE4Ny43MjcgMTU1LjQgMTg3LjQ2IDE1NS4zNTEgMTg3LjIyMSAxNTUuMjUyQzE4Ni45ODQgMTU1LjE1IDE4Ni43OCAxNTUuMDA4IDE4Ni42MDggMTU0LjgyNkMxODYuNDM4IDE1NC42NDQgMTg2LjMwOCAxNTQuNDI3IDE4Ni4yMTcgMTU0LjE3N0MxODYuMTI2IDE1My45MjcgMTg2LjA4IDE1My42NTQgMTg2LjA4IDE1My4zNTdWMTUzLjE5M0MxODYuMDggMTUyLjg0OSAxODYuMTMxIDE1Mi41NDMgMTg2LjIzMyAxNTIuMjc1QzE4Ni4zMzQgMTUyLjAwNCAxODYuNDcyIDE1MS43NzUgMTg2LjY0NyAxNTEuNTg4QzE4Ni44MjEgMTUxLjQgMTg3LjAxOSAxNTEuMjU4IDE4Ny4yNCAxNTEuMTYyQzE4Ny40NjIgMTUxLjA2NiAxODcuNjkxIDE1MS4wMTcgMTg3LjkyOCAxNTEuMDE3QzE4OC4yMyAxNTEuMDE3IDE4OC40OSAxNTEuMDY5IDE4OC43MDkgMTUxLjE3NEMxODguOTMxIDE1MS4yNzggMTg5LjExMiAxNTEuNDI0IDE4OS4yNTIgMTUxLjYxMUMxODkuMzkzIDE1MS43OTYgMTg5LjQ5NyAxNTIuMDE1IDE4OS41NjUgMTUyLjI2N0MxODkuNjMyIDE1Mi41MTcgMTg5LjY2NiAxNTIuNzkxIDE4OS42NjYgMTUzLjA4OFYxNTMuNDEySDE4Ni41MVYxNTIuODIySDE4OC45NDRWMTUyLjc2N0MxODguOTMzIDE1Mi41OCAxODguODk0IDE1Mi4zOTggMTg4LjgyNiAxNTIuMjJDMTg4Ljc2MSAxNTIuMDQzIDE4OC42NTcgMTUxLjg5OCAxODguNTE0IDE1MS43ODNDMTg4LjM3MSAxNTEuNjY4IDE4OC4xNzUgMTUxLjYxMSAxODcuOTI4IDE1MS42MTFDMTg3Ljc2NCAxNTEuNjExIDE4Ny42MTMgMTUxLjY0NiAxODcuNDc1IDE1MS43MTdDMTg3LjMzNyAxNTEuNzg0IDE4Ny4yMTggMTUxLjg4NiAxODcuMTE5IDE1Mi4wMjFDMTg3LjAyIDE1Mi4xNTcgMTg2Ljk0NCAxNTIuMzIyIDE4Ni44ODkgMTUyLjUxN0MxODYuODM0IDE1Mi43MTMgMTg2LjgwNyAxNTIuOTM4IDE4Ni44MDcgMTUzLjE5M1YxNTMuMzU3QzE4Ni44MDcgMTUzLjU1OCAxODYuODM0IDE1My43NDcgMTg2Ljg4OSAxNTMuOTI0QzE4Ni45NDYgMTU0LjA5OCAxODcuMDI4IDE1NC4yNTIgMTg3LjEzNSAxNTQuMzg1QzE4Ny4yNDQgMTU0LjUxNyAxODcuMzc2IDE1NC42MjIgMTg3LjUzIDE1NC42OTdDMTg3LjY4NiAxNTQuNzczIDE4Ny44NjMgMTU0LjgxIDE4OC4wNjEgMTU0LjgxQzE4OC4zMTYgMTU0LjgxIDE4OC41MzIgMTU0Ljc1OCAxODguNzA5IDE1NC42NTRDMTg4Ljg4NiAxNTQuNTUgMTg5LjA0MSAxNTQuNDExIDE4OS4xNzQgMTU0LjIzNkwxODkuNjEyIDE1NC41ODRDMTg5LjUyIDE1NC43MjIgMTg5LjQwNSAxNTQuODUzIDE4OS4yNjQgMTU0Ljk3OEMxODkuMTIzIDE1NS4xMDMgMTg4Ljk1IDE1NS4yMDUgMTg4Ljc0NCAxNTUuMjgzQzE4OC41NDEgMTU1LjM2MSAxODguMyAxNTUuNCAxODguMDIyIDE1NS40Wk0xOTAuNTg5IDE0OS4zMjJIMTkxLjMxNVYxNTQuNTAyTDE5MS4yNTMgMTU1LjMyMkgxOTAuNTg5VjE0OS4zMjJaTTE5NC4xNzEgMTUzLjE3NFYxNTMuMjU2QzE5NC4xNzEgMTUzLjU2MyAxOTQuMTM0IDE1My44NDggMTk0LjA2MSAxNTQuMTExQzE5My45ODggMTU0LjM3MiAxOTMuODgyIDE1NC41OTggMTkzLjc0MSAxNTQuNzkxQzE5My42IDE1NC45ODMgMTkzLjQyOSAxNTUuMTMzIDE5My4yMjUgMTU1LjI0QzE5My4wMjIgMTU1LjM0NyAxOTIuNzg5IDE1NS40IDE5Mi41MjYgMTU1LjRDMTkyLjI1OCAxNTUuNCAxOTIuMDIyIDE1NS4zNTUgMTkxLjgxOSAxNTUuMjYzQzE5MS42MTkgMTU1LjE3IDE5MS40NDkgMTU1LjAzNiAxOTEuMzExIDE1NC44NjFDMTkxLjE3MyAxNTQuNjg3IDE5MS4wNjMgMTU0LjQ3NiAxOTAuOTc5IDE1NC4yMjhDMTkwLjg5OSAxNTMuOTgxIDE5MC44NDMgMTUzLjcwMiAxOTAuODExIDE1My4zOTJWMTUzLjAzM0MxOTAuODQzIDE1Mi43MiAxOTAuODk5IDE1Mi40NDEgMTkwLjk3OSAxNTIuMTkzQzE5MS4wNjMgMTUxLjk0NiAxOTEuMTczIDE1MS43MzUgMTkxLjMxMSAxNTEuNTZDMTkxLjQ0OSAxNTEuMzgzIDE5MS42MTkgMTUxLjI0OSAxOTEuODE5IDE1MS4xNThDMTkyLjAyIDE1MS4wNjQgMTkyLjI1MyAxNTEuMDE3IDE5Mi41MTggMTUxLjAxN0MxOTIuNzg0IDE1MS4wMTcgMTkzLjAyIDE1MS4wNjkgMTkzLjIyNSAxNTEuMTc0QzE5My40MzEgMTUxLjI3NSAxOTMuNjAzIDE1MS40MjEgMTkzLjc0MSAxNTEuNjExQzE5My44ODIgMTUxLjgwMSAxOTMuOTg4IDE1Mi4wMjkgMTk0LjA2MSAxNTIuMjk1QzE5NC4xMzQgMTUyLjU1OCAxOTQuMTcxIDE1Mi44NTEgMTk0LjE3MSAxNTMuMTc0Wk0xOTMuNDQ0IDE1My4yNTZWMTUzLjE3NEMxOTMuNDQ0IDE1Mi45NjMgMTkzLjQyNSAxNTIuNzY1IDE5My4zODYgMTUyLjU4QzE5My4zNDcgMTUyLjM5MiAxOTMuMjg0IDE1Mi4yMjggMTkzLjE5OCAxNTIuMDg4QzE5My4xMTIgMTUxLjk0NCAxOTIuOTk5IDE1MS44MzIgMTkyLjg1OCAxNTEuNzUyQzE5Mi43MTggMTUxLjY2OCAxOTIuNTQ0IDE1MS42MjcgMTkyLjMzOSAxNTEuNjI3QzE5Mi4xNTYgMTUxLjYyNyAxOTEuOTk4IDE1MS42NTggMTkxLjg2MiAxNTEuNzJDMTkxLjcyOSAxNTEuNzgzIDE5MS42MTYgMTUxLjg2OCAxOTEuNTIyIDE1MS45NzRDMTkxLjQyOSAxNTIuMDc5IDE5MS4zNTIgMTUyLjE5OCAxOTEuMjkyIDE1Mi4zMzRDMTkxLjIzNSAxNTIuNDY3IDE5MS4xOTIgMTUyLjYwNSAxOTEuMTYzIDE1Mi43NDhWMTUzLjY4OUMxOTEuMjA1IDE1My44NzIgMTkxLjI3MiAxNTQuMDQ3IDE5MS4zNjYgMTU0LjIxN0MxOTEuNDYyIDE1NC4zODMgMTkxLjU5IDE1NC41MiAxOTEuNzQ5IDE1NC42MjdDMTkxLjkxIDE1NC43MzMgMTkyLjExIDE1NC43ODcgMTkyLjM0NyAxNTQuNzg3QzE5Mi41NDIgMTU0Ljc4NyAxOTIuNzA4IDE1NC43NDggMTkyLjg0NyAxNTQuNjdDMTkyLjk4NyAxNTQuNTg5IDE5My4xIDE1NC40NzggMTkzLjE4NiAxNTQuMzM4QzE5My4yNzUgMTU0LjE5NyAxOTMuMzQgMTU0LjAzNCAxOTMuMzgyIDE1My44NDlDMTkzLjQyMyAxNTMuNjY0IDE5My40NDQgMTUzLjQ2NyAxOTMuNDQ0IDE1My4yNTZaIiBmaWxsPSJibGFjayIgZmlsbC1vcGFjaXR5PSIwLjU0Ii8+CjwvZz4KPHBhdGggZD0iTTI3IDEwNy40NDVMNDAgODguMDk2Mkw3NS45NDA3IDQ0Ljk4OTVDNzYuMjYxMSA0NC42MDUyIDc2LjgxNjEgNDQuNTE2OCA3Ny4yNCA0NC43ODI2TDExMC41NTYgNjUuNjcxNkMxMTAuODM0IDY1Ljg0NiAxMTEuMTggNjUuODcyOCAxMTEuNDgyIDY1Ljc0MzNMMTQ3IDUwLjQ5OUwxODQuMDMyIDM5LjgxODNDMTg0LjMyNyAzOS43MzMxIDE4NC41NjcgMzkuNTE2OCAxODQuNjgyIDM5LjIzMThMMTk4LjUgNSIgc3Ryb2tlPSIjRkZDMTA3IiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMjggMTI5LjE2MUw0MCAxMTIuMTRMNzYgNzkuMTYxNEwxMTEgODkuMjY3OEwxNDcgNzkuMTYxNEwxNzggMTIwLjY1MUwxOTkgODkuMjY3OCIgc3Ryb2tlPSIjNENBRjUwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMjcgMTE4TDQwIDcxLjc3OTJMNzYgNjQuNTYzNUwxMTAuNSAxNy42NjExTDE0Ni41IDQyLjkxNjJMMTgyIDcxLjc3OTJMMTk4LjUgMTA4IiBzdHJva2U9IiMyMTk2RjMiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfNDE4NF85NDUyNyI+CjxyZWN0IHdpZHRoPSIyMDAiIGhlaWdodD0iMTYwIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8Y2xpcFBhdGggaWQ9ImNsaXAxXzQxODRfOTQ1MjciPgo8cmVjdCB3aWR0aD0iMzUuNCIgaGVpZ2h0PSIxMC4zMjIiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1OC4zOTk5IDE0NikiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwMl80MTg0Xzk0NTI3Ij4KPHJlY3Qgd2lkdGg9IjM1LjQiIGhlaWdodD0iMTAuMzIyIiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTMuOCAxNDYpIi8+CjwvY2xpcFBhdGg+CjxjbGlwUGF0aCBpZD0iY2xpcDNfNDE4NF85NDUyNyI+CjxyZWN0IHdpZHRoPSIzNS40IiBoZWlnaHQ9IjEwLjMyMiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEyOS4yIDE0NikiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwNF80MTg0Xzk0NTI3Ij4KPHJlY3Qgd2lkdGg9IjM1LjQiIGhlaWdodD0iMTAuMzIyIiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTY0LjYgMTQ2KSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=", + "description": "Displays changes to time-series data over time—for example, temperature or humidity readings.", + "descriptor": { + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "resources": [], + "templateHtml": "\n", + "templateCss": "", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'line',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('line'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", + "settingsSchema": "{}", + "dataKeySettingsSchema": "{}", + "latestDataKeySettingsSchema": "{}", + "settingsDirective": "tb-time-series-chart-widget-settings", + "dataKeySettingsDirective": "tb-time-series-chart-key-settings", + "latestDataKeySettingsDirective": "", + "hasBasicMode": true, + "basicModeDirective": "tb-time-series-chart-basic-config", + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"opacity\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.3409583261715494,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"decimals\":null,\"aggregationType\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"dd MMM yyyy HH:mm:ss\",\"lastUpdateAgo\":false,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Line chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + }, + "tags": [ + "chart", + "time series", + "time-series", + "line", + "line chart" + ] +} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/point_chart.json b/application/src/main/data/json/system/widget_types/point_chart.json new file mode 100644 index 0000000000..f16d6823ee --- /dev/null +++ b/application/src/main/data/json/system/widget_types/point_chart.json @@ -0,0 +1,32 @@ +{ + "fqn": "point_chart", + "name": "Point chart", + "deprecated": false, + "image": "tb-image:Y2hhcnRfKDMpLnN2Zw==:IlBvaW50IGNoYXJ0IiBzeXN0ZW0gd2lkZ2V0IGltYWdl;data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE2MCIgdmlld0JveD0iMCAwIDIwMCAxNjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF80MTgyXzExMTkzKSI+CjxwYXRoIGQ9Ik0yLjg0NzY2IDEuMjgxMjVWN0gyLjEyNVYyLjE4MzU5TDAuNjY3OTY5IDIuNzE0ODRWMi4wNjI1TDIuNzM0MzggMS4yODEyNUgyLjg0NzY2Wk04LjY3NTE3IDMuNzAzMTJWNC41NzAzMUM4LjY3NTE3IDUuMDM2NDYgOC42MzM1MSA1LjQyOTY5IDguNTUwMTcgNS43NUM4LjQ2Njg0IDYuMDcwMzEgOC4zNDcwNSA2LjMyODEyIDguMTkwOCA2LjUyMzQ0QzguMDM0NTUgNi43MTg3NSA3Ljg0NTc1IDYuODYwNjggNy42MjQzOSA2Ljk0OTIyQzcuNDA1NjQgNy4wMzUxNiA3LjE1ODI1IDcuMDc4MTIgNi44ODIyIDcuMDc4MTJDNi42NjM0NSA3LjA3ODEyIDYuNDYxNjMgNy4wNTA3OCA2LjI3NjczIDYuOTk2MDlDNi4wOTE4NCA2Ljk0MTQxIDUuOTI1MTcgNi44NTQxNyA1Ljc3NjczIDYuNzM0MzhDNS42MzA5IDYuNjExOTggNS41MDU5IDYuNDUzMTIgNS40MDE3MyA2LjI1NzgxQzUuMjk3NTcgNi4wNjI1IDUuMjE4MTQgNS44MjU1MiA1LjE2MzQ1IDUuNTQ2ODhDNS4xMDg3NyA1LjI2ODIzIDUuMDgxNDIgNC45NDI3MSA1LjA4MTQyIDQuNTcwMzFWMy43MDMxMkM1LjA4MTQyIDMuMjM2OTggNS4xMjMwOSAyLjg0NjM1IDUuMjA2NDIgMi41MzEyNUM1LjI5MjM2IDIuMjE2MTUgNS40MTM0NSAxLjk2MzU0IDUuNTY5NyAxLjc3MzQ0QzUuNzI1OTUgMS41ODA3MyA1LjkxMzQ1IDEuNDQyNzEgNi4xMzIyIDEuMzU5MzhDNi4zNTM1NiAxLjI3NjA0IDYuNjAwOTUgMS4yMzQzOCA2Ljg3NDM5IDEuMjM0MzhDNy4wOTU3NSAxLjIzNDM4IDcuMjk4ODcgMS4yNjE3MiA3LjQ4Mzc3IDEuMzE2NDFDNy42NzEyNyAxLjM2ODQ5IDcuODM3OTMgMS40NTMxMiA3Ljk4Mzc3IDEuNTcwMzFDOC4xMjk2IDEuNjg0OSA4LjI1MzMgMS44Mzg1NCA4LjM1NDg2IDIuMDMxMjVDOC40NTkwMyAyLjIyMTM1IDguNTM4NDUgMi40NTQ0MyA4LjU5MzE0IDIuNzMwNDdDOC42NDc4MyAzLjAwNjUxIDguNjc1MTcgMy4zMzA3MyA4LjY3NTE3IDMuNzAzMTJaTTcuOTQ4NjEgNC42ODc1VjMuNTgyMDNDNy45NDg2MSAzLjMyNjgyIDcuOTMyOTggMy4xMDI4NiA3LjkwMTczIDIuOTEwMTZDNy44NzMwOSAyLjcxNDg0IDcuODMwMTIgMi41NDgxOCA3Ljc3MjgzIDIuNDEwMTZDNy43MTU1NCAyLjI3MjE0IDcuNjQyNjIgMi4xNjAxNiA3LjU1NDA4IDIuMDc0MjJDNy40NjgxNCAxLjk4ODI4IDcuMzY3ODggMS45MjU3OCA3LjI1MzMgMS44ODY3MkM3LjE0MTMyIDEuODQ1MDUgNy4wMTUwMiAxLjgyNDIyIDYuODc0MzkgMS44MjQyMkM2LjcwMjUyIDEuODI0MjIgNi41NTAxNyAxLjg1Njc3IDYuNDE3MzYgMS45MjE4OEM2LjI4NDU1IDEuOTg0MzggNi4xNzI1NyAyLjA4NDY0IDYuMDgxNDIgMi4yMjI2NkM1Ljk5Mjg4IDIuMzYwNjggNS45MjUxNyAyLjU0MTY3IDUuODc4MyAyLjc2NTYyQzUuODMxNDIgMi45ODk1OCA1LjgwNzk4IDMuMjYxNzIgNS44MDc5OCAzLjU4MjAzVjQuNjg3NUM1LjgwNzk4IDQuOTQyNzEgNS44MjIzMSA1LjE2Nzk3IDUuODUwOTUgNS4zNjMyOEM1Ljg4MjIgNS41NTg1OSA1LjkyNzc4IDUuNzI3ODYgNS45ODc2NyA1Ljg3MTA5QzYuMDQ3NTcgNi4wMTE3MiA2LjEyMDQ4IDYuMTI3NiA2LjIwNjQyIDYuMjE4NzVDNi4yOTIzNiA2LjMwOTkgNi4zOTEzMiA2LjM3NzYgNi41MDMzIDYuNDIxODhDNi42MTc4OCA2LjQ2MzU0IDYuNzQ0MTggNi40ODQzOCA2Ljg4MjIgNi40ODQzOEM3LjA1OTI5IDYuNDg0MzggNy4yMTQyMyA2LjQ1MDUyIDcuMzQ3MDUgNi4zODI4MUM3LjQ3OTg2IDYuMzE1MSA3LjU5MDU0IDYuMjA5NjQgNy42NzkwOCA2LjA2NjQxQzcuNzcwMjIgNS45MjA1NyA3LjgzNzkzIDUuNzM0MzggNy44ODIyIDUuNTA3ODFDNy45MjY0NyA1LjI3ODY1IDcuOTQ4NjEgNS4wMDUyMSA3Ljk0ODYxIDQuNjg3NVpNMTMuMzA3NCAzLjcwMzEyVjQuNTcwMzFDMTMuMzA3NCA1LjAzNjQ2IDEzLjI2NTcgNS40Mjk2OSAxMy4xODI0IDUuNzVDMTMuMDk5IDYuMDcwMzEgMTIuOTc5MyA2LjMyODEyIDEyLjgyMyA2LjUyMzQ0QzEyLjY2NjggNi43MTg3NSAxMi40Nzc5IDYuODYwNjggMTIuMjU2NiA2Ljk0OTIyQzEyLjAzNzggNy4wMzUxNiAxMS43OTA0IDcuMDc4MTIgMTEuNTE0NCA3LjA3ODEyQzExLjI5NTcgNy4wNzgxMiAxMS4wOTM4IDcuMDUwNzggMTAuOTA4OSA2Ljk5NjA5QzEwLjcyNCA2Ljk0MTQxIDEwLjU1NzQgNi44NTQxNyAxMC40MDg5IDYuNzM0MzhDMTAuMjYzMSA2LjYxMTk4IDEwLjEzODEgNi40NTMxMiAxMC4wMzM5IDYuMjU3ODFDOS45Mjk3NyA2LjA2MjUgOS44NTAzNCA1LjgyNTUyIDkuNzk1NjYgNS41NDY4OEM5Ljc0MDk3IDUuMjY4MjMgOS43MTM2MyA0Ljk0MjcxIDkuNzEzNjMgNC41NzAzMVYzLjcwMzEyQzkuNzEzNjMgMy4yMzY5OCA5Ljc1NTI5IDIuODQ2MzUgOS44Mzg2MyAyLjUzMTI1QzkuOTI0NTYgMi4yMTYxNSAxMC4wNDU3IDEuOTYzNTQgMTAuMjAxOSAxLjc3MzQ0QzEwLjM1ODIgMS41ODA3MyAxMC41NDU3IDEuNDQyNzEgMTAuNzY0NCAxLjM1OTM4QzEwLjk4NTggMS4yNzYwNCAxMS4yMzMyIDEuMjM0MzggMTEuNTA2NiAxLjIzNDM4QzExLjcyNzkgMS4yMzQzOCAxMS45MzExIDEuMjYxNzIgMTIuMTE2IDEuMzE2NDFDMTIuMzAzNSAxLjM2ODQ5IDEyLjQ3MDEgMS40NTMxMiAxMi42MTYgMS41NzAzMUMxMi43NjE4IDEuNjg0OSAxMi44ODU1IDEuODM4NTQgMTIuOTg3MSAyLjAzMTI1QzEzLjA5MTIgMi4yMjEzNSAxMy4xNzA3IDIuNDU0NDMgMTMuMjI1MyAyLjczMDQ3QzEzLjI4IDMuMDA2NTEgMTMuMzA3NCAzLjMzMDczIDEzLjMwNzQgMy43MDMxMlpNMTIuNTgwOCA0LjY4NzVWMy41ODIwM0MxMi41ODA4IDMuMzI2ODIgMTIuNTY1MiAzLjEwMjg2IDEyLjUzMzkgMi45MTAxNkMxMi41MDUzIDIuNzE0ODQgMTIuNDYyMyAyLjU0ODE4IDEyLjQwNSAyLjQxMDE2QzEyLjM0NzcgMi4yNzIxNCAxMi4yNzQ4IDIuMTYwMTYgMTIuMTg2MyAyLjA3NDIyQzEyLjEwMDMgMS45ODgyOCAxMi4wMDAxIDEuOTI1NzggMTEuODg1NSAxLjg4NjcyQzExLjc3MzUgMS44NDUwNSAxMS42NDcyIDEuODI0MjIgMTEuNTA2NiAxLjgyNDIyQzExLjMzNDcgMS44MjQyMiAxMS4xODI0IDEuODU2NzcgMTEuMDQ5NiAxLjkyMTg4QzEwLjkxNjggMS45ODQzOCAxMC44MDQ4IDIuMDg0NjQgMTAuNzEzNiAyLjIyMjY2QzEwLjYyNTEgMi4zNjA2OCAxMC41NTc0IDIuNTQxNjcgMTAuNTEwNSAyLjc2NTYyQzEwLjQ2MzYgMi45ODk1OCAxMC40NDAyIDMuMjYxNzIgMTAuNDQwMiAzLjU4MjAzVjQuNjg3NUMxMC40NDAyIDQuOTQyNzEgMTAuNDU0NSA1LjE2Nzk3IDEwLjQ4MzIgNS4zNjMyOEMxMC41MTQ0IDUuNTU4NTkgMTAuNTYgNS43Mjc4NiAxMC42MTk5IDUuODcxMDlDMTAuNjc5OCA2LjAxMTcyIDEwLjc1MjcgNi4xMjc2IDEwLjgzODYgNi4yMTg3NUMxMC45MjQ2IDYuMzA5OSAxMS4wMjM1IDYuMzc3NiAxMS4xMzU1IDYuNDIxODhDMTEuMjUwMSA2LjQ2MzU0IDExLjM3NjQgNi40ODQzOCAxMS41MTQ0IDYuNDg0MzhDMTEuNjkxNSA2LjQ4NDM4IDExLjg0NjQgNi40NTA1MiAxMS45NzkzIDYuMzgyODFDMTIuMTEyMSA2LjMxNTEgMTIuMjIyNyA2LjIwOTY0IDEyLjMxMTMgNi4wNjY0MUMxMi40MDI0IDUuOTIwNTcgMTIuNDcwMSA1LjczNDM4IDEyLjUxNDQgNS41MDc4MUMxMi41NTg3IDUuMjc4NjUgMTIuNTgwOCA1LjAwNTIxIDEyLjU4MDggNC42ODc1Wk0xNC4zMDY4IDIuNzA3MDNWMi40MDYyNUMxNC4zMDY4IDIuMTkwMSAxNC4zNTM2IDEuOTkzNDkgMTQuNDQ3NCAxLjgxNjQxQzE0LjU0MTEgMS42MzkzMiAxNC42NzUzIDEuNDk3NCAxNC44NDk3IDEuMzkwNjJDMTUuMDI0MiAxLjI4Mzg1IDE1LjIzMTIgMS4yMzA0NyAxNS40NzA4IDEuMjMwNDdDMTUuNzE1NiAxLjIzMDQ3IDE1LjkyNCAxLjI4Mzg1IDE2LjA5NTggMS4zOTA2MkMxNi4yNzAzIDEuNDk3NCAxNi40MDQ0IDEuNjM5MzIgMTYuNDk4MiAxLjgxNjQxQzE2LjU5MTkgMS45OTM0OSAxNi42Mzg4IDIuMTkwMSAxNi42Mzg4IDIuNDA2MjVWMi43MDcwM0MxNi42Mzg4IDIuOTE3OTcgMTYuNTkxOSAzLjExMTk4IDE2LjQ5ODIgMy4yODkwNkMxNi40MDcgMy40NjYxNSAxNi4yNzQyIDMuNjA4MDcgMTYuMDk5NyAzLjcxNDg0QzE1LjkyNzkgMy44MjE2MSAxNS43MjA4IDMuODc1IDE1LjQ3ODYgMy44NzVDMTUuMjM2NSAzLjg3NSAxNS4wMjY4IDMuODIxNjEgMTQuODQ5NyAzLjcxNDg0QzE0LjY3NTMgMy42MDgwNyAxNC41NDExIDMuNDY2MTUgMTQuNDQ3NCAzLjI4OTA2QzE0LjM1MzYgMy4xMTE5OCAxNC4zMDY4IDIuOTE3OTcgMTQuMzA2OCAyLjcwNzAzWk0xNC44NDk3IDIuNDA2MjVWMi43MDcwM0MxNC44NDk3IDIuODI2ODIgMTQuODcxOSAyLjk0MDEgMTQuOTE2MSAzLjA0Njg4QzE0Ljk2MyAzLjE1MzY1IDE1LjAzMzMgMy4yNDA4OSAxNS4xMjcxIDMuMzA4NTlDMTUuMjIwOCAzLjM3MzcgMTUuMzM4IDMuNDA2MjUgMTUuNDc4NiAzLjQwNjI1QzE1LjYxOTMgMy40MDYyNSAxNS43MzUyIDMuMzczNyAxNS44MjYzIDMuMzA4NTlDMTUuOTE3NCAzLjI0MDg5IDE1Ljk4NTIgMy4xNTM2NSAxNi4wMjk0IDMuMDQ2ODhDMTYuMDczNyAyLjk0MDEgMTYuMDk1OCAyLjgyNjgyIDE2LjA5NTggMi43MDcwM1YyLjQwNjI1QzE2LjA5NTggMi4yODM4NSAxNi4wNzI0IDIuMTY5MjcgMTYuMDI1NSAyLjA2MjVDMTUuOTgxMiAxLjk1MzEyIDE1LjkxMjIgMS44NjU4OSAxNS44MTg1IDEuODAwNzhDMTUuNzI3MyAxLjczMzA3IDE1LjYxMTUgMS42OTkyMiAxNS40NzA4IDEuNjk5MjJDMTUuMzMyOCAxLjY5OTIyIDE1LjIxNjkgMS43MzMwNyAxNS4xMjMyIDEuODAwNzhDMTUuMDMyIDEuODY1ODkgMTQuOTYzIDEuOTUzMTIgMTQuOTE2MSAyLjA2MjVDMTQuODcxOSAyLjE2OTI3IDE0Ljg0OTcgMi4yODM4NSAxNC44NDk3IDIuNDA2MjVaTTE3LjA3NjMgNS45MTAxNlY1LjYwNTQ3QzE3LjA3NjMgNS4zOTE5MyAxNy4xMjMyIDUuMTk2NjEgMTcuMjE2OSA1LjAxOTUzQzE3LjMxMDcgNC44NDI0NSAxNy40NDQ4IDQuNzAwNTIgMTcuNjE5MyA0LjU5Mzc1QzE3Ljc5MzcgNC40ODY5OCAxOC4wMDA4IDQuNDMzNTkgMTguMjQwNCA0LjQzMzU5QzE4LjQ4NTIgNC40MzM1OSAxOC42OTM1IDQuNDg2OTggMTguODY1NCA0LjU5Mzc1QzE5LjAzOTggNC43MDA1MiAxOS4xNzQgNC44NDI0NSAxOS4yNjc3IDUuMDE5NTNDMTkuMzYxNSA1LjE5NjYxIDE5LjQwODMgNS4zOTE5MyAxOS40MDgzIDUuNjA1NDdWNS45MTAxNkMxOS40MDgzIDYuMTIzNyAxOS4zNjE1IDYuMzE5MDEgMTkuMjY3NyA2LjQ5NjA5QzE5LjE3NjYgNi42NzMxOCAxOS4wNDM3IDYuODE1MSAxOC44NjkzIDYuOTIxODhDMTguNjk3NCA3LjAyODY1IDE4LjQ5MDQgNy4wODIwMyAxOC4yNDgyIDcuMDgyMDNDMTguMDA2IDcuMDgyMDMgMTcuNzk3NyA3LjAyODY1IDE3LjYyMzIgNi45MjE4OEMxNy40NDg3IDYuODE1MSAxNy4zMTMzIDYuNjczMTggMTcuMjE2OSA2LjQ5NjA5QzE3LjEyMzIgNi4zMTkwMSAxNy4wNzYzIDYuMTIzNyAxNy4wNzYzIDUuOTEwMTZaTTE3LjYxOTMgNS42MDU0N1Y1LjkxMDE2QzE3LjYxOTMgNi4wMjk5NSAxNy42NDE0IDYuMTQ0NTMgMTcuNjg1NyA2LjI1MzkxQzE3LjczMjUgNi4zNjA2OCAxNy44MDI5IDYuNDQ3OTIgMTcuODk2NiA2LjUxNTYyQzE3Ljk5MDQgNi41ODA3MyAxOC4xMDc1IDYuNjEzMjggMTguMjQ4MiA2LjYxMzI4QzE4LjM4ODggNi42MTMyOCAxOC41MDQ3IDYuNTgwNzMgMTguNTk1OCA2LjUxNTYyQzE4LjY4OTYgNi40NDc5MiAxOC43NTg2IDYuMzYwNjggMTguODAyOSA2LjI1MzkxQzE4Ljg0NzEgNi4xNDcxNCAxOC44NjkzIDYuMDMyNTUgMTguODY5MyA1LjkxMDE2VjUuNjA1NDdDMTguODY5MyA1LjQ4MzA3IDE4Ljg0NTggNS4zNjg0OSAxOC43OTkgNS4yNjE3MkMxOC43NTQ3IDUuMTU0OTUgMTguNjg1NyA1LjA2OTAxIDE4LjU5MTkgNS4wMDM5MUMxOC41MDA4IDQuOTM2MiAxOC4zODM2IDQuOTAyMzQgMTguMjQwNCA0LjkwMjM0QzE4LjEwMjMgNC45MDIzNCAxNy45ODY1IDQuOTM2MiAxNy44OTI3IDUuMDAzOTFDMTcuODAxNiA1LjA2OTAxIDE3LjczMjUgNS4xNTQ5NSAxNy42ODU3IDUuMjYxNzJDMTcuNjQxNCA1LjM2ODQ5IDE3LjYxOTMgNS40ODMwNyAxNy42MTkzIDUuNjA1NDdaTTE4LjQyIDIuMTIxMDlMMTUuNjQyNyA2LjU2NjQxTDE1LjIzNjUgNi4zMDg1OUwxOC4wMTM4IDEuODYzMjhMMTguNDIgMi4xMjEwOVoiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuNTQiLz4KPHBhdGggZD0iTTguMDU4NTkgMzMuNjY3N0M4LjA1ODU5IDM0LjAxNDEgNy45Nzc4NiAzNC4zMDgzIDcuODE2NDEgMzQuNTUwNUM3LjY1NzU1IDM0Ljc5MDEgNy40NDE0MSAzNC45NzI0IDcuMTY3OTcgMzUuMDk3NEM2Ljg5NzE0IDM1LjIyMjQgNi41OTExNSAzNS4yODQ5IDYuMjUgMzUuMjg0OUM1LjkwODg1IDM1LjI4NDkgNS42MDE1NiAzNS4yMjI0IDUuMzI4MTIgMzUuMDk3NEM1LjA1NDY5IDM0Ljk3MjQgNC44Mzg1NCAzNC43OTAxIDQuNjc5NjkgMzQuNTUwNUM0LjUyMDgzIDM0LjMwODMgNC40NDE0MSAzNC4wMTQxIDQuNDQxNDEgMzMuNjY3N0M0LjQ0MTQxIDMzLjQ0MTIgNC40ODQzOCAzMy4yMzQxIDQuNTcwMzEgMzMuMDQ2NkM0LjY1ODg1IDMyLjg1NjUgNC43ODI1NSAzMi42OTEyIDQuOTQxNDEgMzIuNTUwNUM1LjEwMjg2IDMyLjQwOTkgNS4yOTI5NyAzMi4zMDE4IDUuNTExNzIgMzIuMjI2M0M1LjczMzA3IDMyLjE0ODIgNS45NzY1NiAzMi4xMDkxIDYuMjQyMTkgMzIuMTA5MUM2LjU5MTE1IDMyLjEwOTEgNi45MDIzNCAzMi4xNzY4IDcuMTc1NzggMzIuMzEyM0M3LjQ0OTIyIDMyLjQ0NTEgNy42NjQwNiAzMi42Mjg3IDcuODIwMzEgMzIuODYzQzcuOTc5MTcgMzMuMDk3NCA4LjA1ODU5IDMzLjM2NTYgOC4wNTg1OSAzMy42Njc3Wk03LjMzMjAzIDMzLjY1MjFDNy4zMzIwMyAzMy40NDEyIDcuMjg2NDYgMzMuMjU1IDcuMTk1MzEgMzMuMDkzNUM3LjEwNDE3IDMyLjkyOTQgNi45NzY1NiAzMi44MDE4IDYuODEyNSAzMi43MTA3QzYuNjQ4NDQgMzIuNjE5NSA2LjQ1ODMzIDMyLjU3NCA2LjI0MjE5IDMyLjU3NEM2LjAyMDgzIDMyLjU3NCA1LjgyOTQzIDMyLjYxOTUgNS42Njc5NyAzMi43MTA3QzUuNTA5MTEgMzIuODAxOCA1LjM4NTQyIDMyLjkyOTQgNS4yOTY4OCAzMy4wOTM1QzUuMjA4MzMgMzMuMjU1IDUuMTY0MDYgMzMuNDQxMiA1LjE2NDA2IDMzLjY1MjFDNS4xNjQwNiAzMy44NzA4IDUuMjA3MDMgMzQuMDU4MyA1LjI5Mjk3IDM0LjIxNDZDNS4zODE1MSAzNC4zNjgyIDUuNTA2NTEgMzQuNDg2NyA1LjY2Nzk3IDM0LjU3MDFDNS44MzIwMyAzNC42NTA4IDYuMDI2MDQgMzQuNjkxMiA2LjI1IDM0LjY5MTJDNi40NzM5NiAzNC42OTEyIDYuNjY2NjcgMzQuNjUwOCA2LjgyODEyIDM0LjU3MDFDNi45ODk1OCAzNC40ODY3IDcuMTEzMjggMzQuMzY4MiA3LjE5OTIyIDM0LjIxNDZDNy4yODc3NiAzNC4wNTgzIDcuMzMyMDMgMzMuODcwOCA3LjMzMjAzIDMzLjY1MjFaTTcuOTI1NzggMzAuOTk5OEM3LjkyNTc4IDMxLjI3NTggNy44NTI4NiAzMS41MjQ1IDcuNzA3MDMgMzEuNzQ1OEM3LjU2MTIgMzEuOTY3MiA3LjM2MTk4IDMyLjE0MTcgNy4xMDkzOCAzMi4yNjkzQzYuODU2NzcgMzIuMzk2OSA2LjU3MDMxIDMyLjQ2MDcgNi4yNSAzMi40NjA3QzUuOTI0NDggMzIuNDYwNyA1LjYzNDExIDMyLjM5NjkgNS4zNzg5MSAzMi4yNjkzQzUuMTI2MyAzMi4xNDE3IDQuOTI4MzkgMzEuOTY3MiA0Ljc4NTE2IDMxLjc0NThDNC42NDE5MyAzMS41MjQ1IDQuNTcwMzEgMzEuMjc1OCA0LjU3MDMxIDMwLjk5OThDNC41NzAzMSAzMC42NjkgNC42NDE5MyAzMC4zODc4IDQuNzg1MTYgMzAuMTU2QzQuOTMwOTkgMjkuOTI0MiA1LjEzMDIxIDI5Ljc0NzIgNS4zODI4MSAyOS42MjQ4QzUuNjM1NDIgMjkuNTAyNCA1LjkyMzE4IDI5LjQ0MTIgNi4yNDYwOSAyOS40NDEyQzYuNTcxNjEgMjkuNDQxMiA2Ljg2MDY4IDI5LjUwMjQgNy4xMTMyOCAyOS42MjQ4QzcuMzY1ODkgMjkuNzQ3MiA3LjU2MzggMjkuOTI0MiA3LjcwNzAzIDMwLjE1NkM3Ljg1Mjg2IDMwLjM4NzggNy45MjU3OCAzMC42NjkgNy45MjU3OCAzMC45OTk4Wk03LjIwMzEyIDMxLjAxMTVDNy4yMDMxMiAzMC44MjE0IDcuMTYyNzYgMzAuNjUzNCA3LjA4MjAzIDMwLjUwNzZDNy4wMDEzIDMwLjM2MTcgNi44ODkzMiAzMC4yNDcyIDYuNzQ2MDkgMzAuMTYzOEM2LjYwMjg2IDMwLjA3NzkgNi40MzYyIDMwLjAzNDkgNi4yNDYwOSAzMC4wMzQ5QzYuMDU1OTkgMzAuMDM0OSA1Ljg4OTMyIDMwLjA3NTMgNS43NDYwOSAzMC4xNTZDNS42MDU0NyAzMC4yMzQxIDUuNDk0NzkgMzAuMzQ2MSA1LjQxNDA2IDMwLjQ5MTlDNS4zMzU5NCAzMC42Mzc4IDUuMjk2ODggMzAuODExIDUuMjk2ODggMzEuMDExNUM1LjI5Njg4IDMxLjIwNjggNS4zMzU5NCAzMS4zNzc0IDUuNDE0MDYgMzEuNTIzMkM1LjQ5NDc5IDMxLjY2OSA1LjYwNjc3IDMxLjc4MjMgNS43NSAzMS44NjNDNS44OTMyMyAzMS45NDM4IDYuMDU5OSAzMS45ODQxIDYuMjUgMzEuOTg0MUM2LjQ0MDEgMzEuOTg0MSA2LjYwNTQ3IDMxLjk0MzggNi43NDYwOSAzMS44NjNDNi44ODkzMiAzMS43ODIzIDcuMDAxMyAzMS42NjkgNy4wODIwMyAzMS41MjMyQzcuMTYyNzYgMzEuMzc3NCA3LjIwMzEyIDMxLjIwNjggNy4yMDMxMiAzMS4wMTE1Wk0xMi42NzUyIDMxLjkwOTlWMzIuNzc3MUMxMi42NzUyIDMzLjI0MzIgMTIuNjMzNSAzMy42MzY1IDEyLjU1MDIgMzMuOTU2OEMxMi40NjY4IDM0LjI3NzEgMTIuMzQ3IDM0LjUzNDkgMTIuMTkwOCAzNC43MzAyQzEyLjAzNDUgMzQuOTI1NSAxMS44NDU3IDM1LjA2NzUgMTEuNjI0NCAzNS4xNTZDMTEuNDA1NiAzNS4yNDE5IDExLjE1ODIgMzUuMjg0OSAxMC44ODIyIDM1LjI4NDlDMTAuNjYzNSAzNS4yODQ5IDEwLjQ2MTYgMzUuMjU3NiAxMC4yNzY3IDM1LjIwMjlDMTAuMDkxOCAzNS4xNDgyIDkuOTI1MTcgMzUuMDYxIDkuNzc2NzMgMzQuOTQxMkM5LjYzMDkgMzQuODE4OCA5LjUwNTkgMzQuNjU5OSA5LjQwMTczIDM0LjQ2NDZDOS4yOTc1NyAzNC4yNjkzIDkuMjE4MTQgMzQuMDMyMyA5LjE2MzQ1IDMzLjc1MzdDOS4xMDg3NyAzMy40NzUgOS4wODE0MiAzMy4xNDk1IDkuMDgxNDIgMzIuNzc3MVYzMS45MDk5QzkuMDgxNDIgMzEuNDQzOCA5LjEyMzA5IDMxLjA1MzEgOS4yMDY0MiAzMC43MzhDOS4yOTIzNiAzMC40MjI5IDkuNDEzNDUgMzAuMTcwMyA5LjU2OTcgMjkuOTgwMkM5LjcyNTk1IDI5Ljc4NzUgOS45MTM0NSAyOS42NDk1IDEwLjEzMjIgMjkuNTY2MkMxMC4zNTM2IDI5LjQ4MjggMTAuNjAxIDI5LjQ0MTIgMTAuODc0NCAyOS40NDEyQzExLjA5NTcgMjkuNDQxMiAxMS4yOTg5IDI5LjQ2ODUgMTEuNDgzOCAyOS41MjMyQzExLjY3MTMgMjkuNTc1MyAxMS44Mzc5IDI5LjY1OTkgMTEuOTgzOCAyOS43NzcxQzEyLjEyOTYgMjkuODkxNyAxMi4yNTMzIDMwLjA0NTMgMTIuMzU0OSAzMC4yMzhDMTIuNDU5IDMwLjQyODEgMTIuNTM4NSAzMC42NjEyIDEyLjU5MzEgMzAuOTM3M0MxMi42NDc4IDMxLjIxMzMgMTIuNjc1MiAzMS41Mzc1IDEyLjY3NTIgMzEuOTA5OVpNMTEuOTQ4NiAzMi44OTQzVjMxLjc4ODhDMTEuOTQ4NiAzMS41MzM2IDExLjkzMyAzMS4zMDk3IDExLjkwMTcgMzEuMTE2OUMxMS44NzMxIDMwLjkyMTYgMTEuODMwMSAzMC43NTUgMTEuNzcyOCAzMC42MTY5QzExLjcxNTUgMzAuNDc4OSAxMS42NDI2IDMwLjM2NjkgMTEuNTU0MSAzMC4yODFDMTEuNDY4MSAzMC4xOTUxIDExLjM2NzkgMzAuMTMyNiAxMS4yNTMzIDMwLjA5MzVDMTEuMTQxMyAzMC4wNTE4IDExLjAxNSAzMC4wMzEgMTAuODc0NCAzMC4wMzFDMTAuNzAyNSAzMC4wMzEgMTAuNTUwMiAzMC4wNjM2IDEwLjQxNzQgMzAuMTI4N0MxMC4yODQ1IDMwLjE5MTIgMTAuMTcyNiAzMC4yOTE0IDEwLjA4MTQgMzAuNDI5NEM5Ljk5Mjg4IDMwLjU2NzUgOS45MjUxNyAzMC43NDg1IDkuODc4MyAzMC45NzI0QzkuODMxNDIgMzEuMTk2NCA5LjgwNzk4IDMxLjQ2ODUgOS44MDc5OCAzMS43ODg4VjMyLjg5NDNDOS44MDc5OCAzMy4xNDk1IDkuODIyMzEgMzMuMzc0OCA5Ljg1MDk1IDMzLjU3MDFDOS44ODIyIDMzLjc2NTQgOS45Mjc3OCAzMy45MzQ3IDkuOTg3NjcgMzQuMDc3OUMxMC4wNDc2IDM0LjIxODUgMTAuMTIwNSAzNC4zMzQ0IDEwLjIwNjQgMzQuNDI1NUMxMC4yOTI0IDM0LjUxNjcgMTAuMzkxMyAzNC41ODQ0IDEwLjUwMzMgMzQuNjI4N0MxMC42MTc5IDM0LjY3MDMgMTAuNzQ0MiAzNC42OTEyIDEwLjg4MjIgMzQuNjkxMkMxMS4wNTkzIDM0LjY5MTIgMTEuMjE0MiAzNC42NTczIDExLjM0NyAzNC41ODk2QzExLjQ3OTkgMzQuNTIxOSAxMS41OTA1IDM0LjQxNjQgMTEuNjc5MSAzNC4yNzMyQzExLjc3MDIgMzQuMTI3NCAxMS44Mzc5IDMzLjk0MTIgMTEuODgyMiAzMy43MTQ2QzExLjkyNjUgMzMuNDg1NCAxMS45NDg2IDMzLjIxMiAxMS45NDg2IDMyLjg5NDNaTTEzLjY3NDYgMzAuOTEzOFYzMC42MTNDMTMuNjc0NiAzMC4zOTY5IDEzLjcyMTQgMzAuMjAwMyAxMy44MTUyIDMwLjAyMzJDMTMuOTA4OSAyOS44NDYxIDE0LjA0MzEgMjkuNzA0MiAxNC4yMTc1IDI5LjU5NzRDMTQuMzkyIDI5LjQ5MDYgMTQuNTk5IDI5LjQzNzMgMTQuODM4NiAyOS40MzczQzE1LjA4MzQgMjkuNDM3MyAxNS4yOTE4IDI5LjQ5MDYgMTUuNDYzNiAyOS41OTc0QzE1LjYzODEgMjkuNzA0MiAxNS43NzIyIDI5Ljg0NjEgMTUuODY2IDMwLjAyMzJDMTUuOTU5NyAzMC4yMDAzIDE2LjAwNjYgMzAuMzk2OSAxNi4wMDY2IDMwLjYxM1YzMC45MTM4QzE2LjAwNjYgMzEuMTI0OCAxNS45NTk3IDMxLjMxODggMTUuODY2IDMxLjQ5NThDMTUuNzc0OCAzMS42NzI5IDE1LjY0MiAzMS44MTQ5IDE1LjQ2NzUgMzEuOTIxNkMxNS4yOTU3IDMyLjAyODQgMTUuMDg4NiAzMi4wODE4IDE0Ljg0NjQgMzIuMDgxOEMxNC42MDQzIDMyLjA4MTggMTQuMzk0NiAzMi4wMjg0IDE0LjIxNzUgMzEuOTIxNkMxNC4wNDMxIDMxLjgxNDkgMTMuOTA4OSAzMS42NzI5IDEzLjgxNTIgMzEuNDk1OEMxMy43MjE0IDMxLjMxODggMTMuNjc0NiAzMS4xMjQ4IDEzLjY3NDYgMzAuOTEzOFpNMTQuMjE3NSAzMC42MTNWMzAuOTEzOEMxNC4yMTc1IDMxLjAzMzYgMTQuMjM5NyAzMS4xNDY5IDE0LjI4MzkgMzEuMjUzN0MxNC4zMzA4IDMxLjM2MDQgMTQuNDAxMSAzMS40NDc3IDE0LjQ5NDkgMzEuNTE1NEMxNC41ODg2IDMxLjU4MDUgMTQuNzA1OCAzMS42MTMgMTQuODQ2NCAzMS42MTNDMTQuOTg3MSAzMS42MTMgMTUuMTAyOSAzMS41ODA1IDE1LjE5NDEgMzEuNTE1NEMxNS4yODUyIDMxLjQ0NzcgMTUuMzUyOSAzMS4zNjA0IDE1LjM5NzIgMzEuMjUzN0MxNS40NDE1IDMxLjE0NjkgMTUuNDYzNiAzMS4wMzM2IDE1LjQ2MzYgMzAuOTEzOFYzMC42MTNDMTUuNDYzNiAzMC40OTA2IDE1LjQ0MDIgMzAuMzc2MSAxNS4zOTMzIDMwLjI2OTNDMTUuMzQ5IDMwLjE1OTkgMTUuMjggMzAuMDcyNyAxNS4xODYzIDMwLjAwNzZDMTUuMDk1MSAyOS45Mzk5IDE0Ljk3OTMgMjkuOTA2IDE0LjgzODYgMjkuOTA2QzE0LjcwMDYgMjkuOTA2IDE0LjU4NDcgMjkuOTM5OSAxNC40OTEgMzAuMDA3NkMxNC4zOTk4IDMwLjA3MjcgMTQuMzMwOCAzMC4xNTk5IDE0LjI4MzkgMzAuMjY5M0MxNC4yMzk3IDMwLjM3NjEgMTQuMjE3NSAzMC40OTA2IDE0LjIxNzUgMzAuNjEzWk0xNi40NDQxIDM0LjExNjlWMzMuODEyM0MxNi40NDQxIDMzLjU5ODcgMTYuNDkxIDMzLjQwMzQgMTYuNTg0NyAzMy4yMjYzQzE2LjY3ODUgMzMuMDQ5MiAxNi44MTI2IDMyLjkwNzMgMTYuOTg3MSAzMi44MDA1QzE3LjE2MTUgMzIuNjkzOCAxNy4zNjg2IDMyLjY0MDQgMTcuNjA4MiAzMi42NDA0QzE3Ljg1MjkgMzIuNjQwNCAxOC4wNjEzIDMyLjY5MzggMTguMjMzMiAzMi44MDA1QzE4LjQwNzYgMzIuOTA3MyAxOC41NDE4IDMzLjA0OTIgMTguNjM1NSAzMy4yMjYzQzE4LjcyOTMgMzMuNDAzNCAxOC43NzYxIDMzLjU5ODcgMTguNzc2MSAzMy44MTIzVjM0LjExNjlDMTguNzc2MSAzNC4zMzA1IDE4LjcyOTMgMzQuNTI1OCAxOC42MzU1IDM0LjcwMjlDMTguNTQ0NCAzNC44OCAxOC40MTE1IDM1LjAyMTkgMTguMjM3MSAzNS4xMjg3QzE4LjA2NTIgMzUuMjM1NCAxNy44NTgyIDM1LjI4ODggMTcuNjE2IDM1LjI4ODhDMTcuMzczOCAzNS4yODg4IDE3LjE2NTQgMzUuMjM1NCAxNi45OTEgMzUuMTI4N0MxNi44MTY1IDM1LjAyMTkgMTYuNjgxMSAzNC44OCAxNi41ODQ3IDM0LjcwMjlDMTYuNDkxIDM0LjUyNTggMTYuNDQ0MSAzNC4zMzA1IDE2LjQ0NDEgMzQuMTE2OVpNMTYuOTg3MSAzMy44MTIzVjM0LjExNjlDMTYuOTg3MSAzNC4yMzY3IDE3LjAwOTIgMzQuMzUxMyAxNy4wNTM1IDM0LjQ2MDdDMTcuMTAwMyAzNC41Njc1IDE3LjE3MDcgMzQuNjU0NyAxNy4yNjQ0IDM0LjcyMjRDMTcuMzU4MiAzNC43ODc1IDE3LjQ3NTMgMzQuODIwMSAxNy42MTYgMzQuODIwMUMxNy43NTY2IDM0LjgyMDEgMTcuODcyNSAzNC43ODc1IDE3Ljk2MzYgMzQuNzIyNEMxOC4wNTc0IDM0LjY1NDcgMTguMTI2NCAzNC41Njc1IDE4LjE3MDcgMzQuNDYwN0MxOC4yMTQ5IDM0LjM1MzkgMTguMjM3MSAzNC4yMzkzIDE4LjIzNzEgMzQuMTE2OVYzMy44MTIzQzE4LjIzNzEgMzMuNjg5OSAxOC4yMTM2IDMzLjU3NTMgMTguMTY2OCAzMy40Njg1QzE4LjEyMjUgMzMuMzYxNyAxOC4wNTM1IDMzLjI3NTggMTcuOTU5NyAzMy4yMTA3QzE3Ljg2ODYgMzMuMTQzIDE3Ljc1MTQgMzMuMTA5MSAxNy42MDgyIDMzLjEwOTFDMTcuNDcwMSAzMy4xMDkxIDE3LjM1NDMgMzMuMTQzIDE3LjI2MDUgMzMuMjEwN0MxNy4xNjk0IDMzLjI3NTggMTcuMTAwMyAzMy4zNjE3IDE3LjA1MzUgMzMuNDY4NUMxNy4wMDkyIDMzLjU3NTMgMTYuOTg3MSAzMy42ODk5IDE2Ljk4NzEgMzMuODEyM1pNMTcuNzg3OCAzMC4zMjc5TDE1LjAxMDUgMzQuNzczMkwxNC42MDQzIDM0LjUxNTRMMTcuMzgxNiAzMC4wNzAxTDE3Ljc4NzggMzAuMzI3OVoiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuNTQiLz4KPHBhdGggZD0iTTcuMjQ2MDkgNTcuNzE4M0g3LjMwODU5VjU4LjMzMTVINy4yNDYwOUM2Ljg2MzI4IDU4LjMzMTUgNi41NDI5NyA1OC4zOTQgNi4yODUxNiA1OC41MTlDNi4wMjczNCA1OC42NDE0IDUuODIyOTIgNTguODA2OCA1LjY3MTg4IDU5LjAxNTFDNS41MjA4MyA1OS4yMjA5IDUuNDExNDYgNTkuNDUyNiA1LjM0Mzc1IDU5LjcxMDRDNS4yNzg2NSA1OS45NjgzIDUuMjQ2MDkgNjAuMjMgNS4yNDYwOSA2MC40OTU2VjYxLjMzMTVDNS4yNDYwOSA2MS41ODQxIDUuMjc2MDQgNjEuODA4MSA1LjMzNTk0IDYyLjAwMzRDNS4zOTU4MyA2Mi4xOTYxIDUuNDc3ODYgNjIuMzU4OSA1LjU4MjAzIDYyLjQ5MTdDNS42ODYyIDYyLjYyNDUgNS44MDMzOSA2Mi43MjQ4IDUuOTMzNTkgNjIuNzkyNUM2LjA2NjQxIDYyLjg2MDIgNi4yMDQ0MyA2Mi44OTQgNi4zNDc2NiA2Mi44OTRDNi41MTQzMiA2Mi44OTQgNi42NjI3NiA2Mi44NjI4IDYuNzkyOTcgNjIuODAwM0M2LjkyMzE4IDYyLjczNTIgNy4wMzI1NSA2Mi42NDUzIDcuMTIxMDkgNjIuNTMwOEM3LjIxMjI0IDYyLjQxMzYgNy4yODEyNSA2Mi4yNzU2IDcuMzI4MTIgNjIuMTE2N0M3LjM3NSA2MS45NTc4IDcuMzk4NDQgNjEuNzgzNCA3LjM5ODQ0IDYxLjU5MzNDNy4zOTg0NCA2MS40MjQgNy4zNzc2IDYxLjI2MTIgNy4zMzU5NCA2MS4xMDVDNy4yOTQyNyA2MC45NDYxIDcuMjMwNDcgNjAuODA1NSA3LjE0NDUzIDYwLjY4MzFDNy4wNTg1OSA2MC41NTgxIDYuOTUwNTIgNjAuNDYwNCA2LjgyMDMxIDYwLjM5MDFDNi42OTI3MSA2MC4zMTcyIDYuNTQwMzYgNjAuMjgwOCA2LjM2MzI4IDYwLjI4MDhDNi4xNjI3NiA2MC4yODA4IDUuOTc1MjYgNjAuMzMwMiA1LjgwMDc4IDYwLjQyOTJDNS42Mjg5MSA2MC41MjU2IDUuNDg2OTggNjAuNjUzMiA1LjM3NSA2MC44MTJDNS4yNjU2MiA2MC45NjgzIDUuMjAzMTIgNjEuMTM4OCA1LjE4NzUgNjEuMzIzN0w0LjgwNDY5IDYxLjMxOThDNC44NDExNSA2MS4wMjgyIDQuOTA4ODUgNjAuNzc5NSA1LjAwNzgxIDYwLjU3MzdDNS4xMDkzOCA2MC4zNjU0IDUuMjM0MzggNjAuMTk2MSA1LjM4MjgxIDYwLjA2NTlDNS41MzM4NSA1OS45MzMxIDUuNzAxODIgNTkuODM2OCA1Ljg4NjcyIDU5Ljc3NjlDNi4wNzQyMiA1OS43MTQ0IDYuMjcyMTQgNTkuNjgzMSA2LjQ4MDQ3IDU5LjY4MzFDNi43NjQzMiA1OS42ODMxIDcuMDA5MTEgNTkuNzM2NSA3LjIxNDg0IDU5Ljg0MzNDNy40MjA1NyA1OS45NSA3LjU4OTg0IDYwLjA5MzMgNy43MjI2NiA2MC4yNzI5QzcuODU1NDcgNjAuNDUgNy45NTMxMiA2MC42NTA2IDguMDE1NjIgNjAuODc0NUM4LjA4MDczIDYxLjA5NTkgOC4xMTMyOCA2MS4zMjM3IDguMTEzMjggNjEuNTU4MUM4LjExMzI4IDYxLjgyNjMgOC4wNzU1MiA2Mi4wNzc2IDggNjIuMzEyQzcuOTI0NDggNjIuNTQ2NCA3LjgxMTIgNjIuNzUyMSA3LjY2MDE2IDYyLjkyOTJDNy41MTE3MiA2My4xMDYzIDcuMzI4MTIgNjMuMjQ0MyA3LjEwOTM4IDYzLjM0MzNDNi44OTA2MiA2My40NDIyIDYuNjM2NzIgNjMuNDkxNyA2LjM0NzY2IDYzLjQ5MTdDNi4wNDAzNiA2My40OTE3IDUuNzcyMTQgNjMuNDI5MiA1LjU0Mjk3IDYzLjMwNDJDNS4zMTM4IDYzLjE3NjYgNS4xMjM3IDYzLjAwNzMgNC45NzI2NiA2Mi43OTY0QzQuODIxNjEgNjIuNTg1NCA0LjcwODMzIDYyLjM1MTEgNC42MzI4MSA2Mi4wOTMzQzQuNTU3MjkgNjEuODM1NCA0LjUxOTUzIDYxLjU3MzcgNC41MTk1MyA2MS4zMDgxVjYwLjk2ODNDNC41MTk1MyA2MC41NjcyIDQuNTU5OSA2MC4xNzQgNC42NDA2MiA1OS43ODg2QzQuNzIxMzUgNTkuNDAzMiA0Ljg2MDY4IDU5LjA1NDIgNS4wNTg1OSA1OC43NDE3QzUuMjU5MTEgNTguNDI5MiA1LjUzNjQ2IDU4LjE4MDUgNS44OTA2MiA1Ny45OTU2QzYuMjQ0NzkgNTcuODEwNyA2LjY5NjYxIDU3LjcxODMgNy4yNDYwOSA1Ny43MTgzWk0xMi42NzUyIDYwLjExNjdWNjAuOTgzOUMxMi42NzUyIDYxLjQ1IDEyLjYzMzUgNjEuODQzMyAxMi41NTAyIDYyLjE2MzZDMTIuNDY2OCA2Mi40ODM5IDEyLjM0NyA2Mi43NDE3IDEyLjE5MDggNjIuOTM3QzEyLjAzNDUgNjMuMTMyMyAxMS44NDU3IDYzLjI3NDMgMTEuNjI0NCA2My4zNjI4QzExLjQwNTYgNjMuNDQ4NyAxMS4xNTgyIDYzLjQ5MTcgMTAuODgyMiA2My40OTE3QzEwLjY2MzUgNjMuNDkxNyAxMC40NjE2IDYzLjQ2NDQgMTAuMjc2NyA2My40MDk3QzEwLjA5MTggNjMuMzU1IDkuOTI1MTcgNjMuMjY3NyA5Ljc3NjczIDYzLjE0NzlDOS42MzA5IDYzLjAyNTYgOS41MDU5IDYyLjg2NjcgOS40MDE3MyA2Mi42NzE0QzkuMjk3NTcgNjIuNDc2MSA5LjIxODE0IDYyLjIzOTEgOS4xNjM0NSA2MS45NjA0QzkuMTA4NzcgNjEuNjgxOCA5LjA4MTQyIDYxLjM1NjMgOS4wODE0MiA2MC45ODM5VjYwLjExNjdDOS4wODE0MiA1OS42NTA2IDkuMTIzMDkgNTkuMjU5OSA5LjIwNjQyIDU4Ljk0NDhDOS4yOTIzNiA1OC42Mjk3IDkuNDEzNDUgNTguMzc3MSA5LjU2OTcgNTguMTg3QzkuNzI1OTUgNTcuOTk0MyA5LjkxMzQ1IDU3Ljg1NjMgMTAuMTMyMiA1Ny43NzI5QzEwLjM1MzYgNTcuNjg5NiAxMC42MDEgNTcuNjQ3OSAxMC44NzQ0IDU3LjY0NzlDMTEuMDk1NyA1Ny42NDc5IDExLjI5ODkgNTcuNjc1MyAxMS40ODM4IDU3LjczQzExLjY3MTMgNTcuNzgyMSAxMS44Mzc5IDU3Ljg2NjcgMTEuOTgzOCA1Ny45ODM5QzEyLjEyOTYgNTguMDk4NSAxMi4yNTMzIDU4LjI1MjEgMTIuMzU0OSA1OC40NDQ4QzEyLjQ1OSA1OC42MzQ5IDEyLjUzODUgNTguODY4IDEyLjU5MzEgNTkuMTQ0QzEyLjY0NzggNTkuNDIwMSAxMi42NzUyIDU5Ljc0NDMgMTIuNjc1MiA2MC4xMTY3Wk0xMS45NDg2IDYxLjEwMTFWNTkuOTk1NkMxMS45NDg2IDU5Ljc0MDQgMTEuOTMzIDU5LjUxNjQgMTEuOTAxNyA1OS4zMjM3QzExLjg3MzEgNTkuMTI4NCAxMS44MzAxIDU4Ljk2MTggMTEuNzcyOCA1OC44MjM3QzExLjcxNTUgNTguNjg1NyAxMS42NDI2IDU4LjU3MzcgMTEuNTU0MSA1OC40ODc4QzExLjQ2ODEgNTguNDAxOSAxMS4zNjc5IDU4LjMzOTQgMTEuMjUzMyA1OC4zMDAzQzExLjE0MTMgNTguMjU4NiAxMS4wMTUgNTguMjM3OCAxMC44NzQ0IDU4LjIzNzhDMTAuNzAyNSA1OC4yMzc4IDEwLjU1MDIgNTguMjcwMyAxMC40MTc0IDU4LjMzNTRDMTAuMjg0NSA1OC4zOTc5IDEwLjE3MjYgNTguNDk4MiAxMC4wODE0IDU4LjYzNjJDOS45OTI4OCA1OC43NzQzIDkuOTI1MTcgNTguOTU1MiA5Ljg3ODMgNTkuMTc5MkM5LjgzMTQyIDU5LjQwMzIgOS44MDc5OCA1OS42NzUzIDkuODA3OTggNTkuOTk1NlY2MS4xMDExQzkuODA3OTggNjEuMzU2MyA5LjgyMjMxIDYxLjU4MTUgOS44NTA5NSA2MS43NzY5QzkuODgyMiA2MS45NzIyIDkuOTI3NzggNjIuMTQxNCA5Ljk4NzY3IDYyLjI4NDdDMTAuMDQ3NiA2Mi40MjUzIDEwLjEyMDUgNjIuNTQxMiAxMC4yMDY0IDYyLjYzMjNDMTAuMjkyNCA2Mi43MjM1IDEwLjM5MTMgNjIuNzkxMiAxMC41MDMzIDYyLjgzNTRDMTAuNjE3OSA2Mi44NzcxIDEwLjc0NDIgNjIuODk3OSAxMC44ODIyIDYyLjg5NzlDMTEuMDU5MyA2Mi44OTc5IDExLjIxNDIgNjIuODY0MSAxMS4zNDcgNjIuNzk2NEMxMS40Nzk5IDYyLjcyODcgMTEuNTkwNSA2Mi42MjMyIDExLjY3OTEgNjIuNDhDMTEuNzcwMiA2Mi4zMzQxIDExLjgzNzkgNjIuMTQ3OSAxMS44ODIyIDYxLjkyMTRDMTEuOTI2NSA2MS42OTIyIDExLjk0ODYgNjEuNDE4OCAxMS45NDg2IDYxLjEwMTFaTTEzLjY3NDYgNTkuMTIwNlY1OC44MTk4QzEzLjY3NDYgNTguNjAzNyAxMy43MjE0IDU4LjQwNzEgMTMuODE1MiA1OC4yM0MxMy45MDg5IDU4LjA1MjkgMTQuMDQzMSA1Ny45MTEgMTQuMjE3NSA1Ny44MDQyQzE0LjM5MiA1Ny42OTc0IDE0LjU5OSA1Ny42NDQgMTQuODM4NiA1Ny42NDRDMTUuMDgzNCA1Ny42NDQgMTUuMjkxOCA1Ny42OTc0IDE1LjQ2MzYgNTcuODA0MkMxNS42MzgxIDU3LjkxMSAxNS43NzIyIDU4LjA1MjkgMTUuODY2IDU4LjIzQzE1Ljk1OTcgNTguNDA3MSAxNi4wMDY2IDU4LjYwMzcgMTYuMDA2NiA1OC44MTk4VjU5LjEyMDZDMTYuMDA2NiA1OS4zMzE1IDE1Ljk1OTcgNTkuNTI1NiAxNS44NjYgNTkuNzAyNkMxNS43NzQ4IDU5Ljg3OTcgMTUuNjQyIDYwLjAyMTYgMTUuNDY3NSA2MC4xMjg0QzE1LjI5NTcgNjAuMjM1MiAxNS4wODg2IDYwLjI4ODYgMTQuODQ2NCA2MC4yODg2QzE0LjYwNDMgNjAuMjg4NiAxNC4zOTQ2IDYwLjIzNTIgMTQuMjE3NSA2MC4xMjg0QzE0LjA0MzEgNjAuMDIxNiAxMy45MDg5IDU5Ljg3OTcgMTMuODE1MiA1OS43MDI2QzEzLjcyMTQgNTkuNTI1NiAxMy42NzQ2IDU5LjMzMTUgMTMuNjc0NiA1OS4xMjA2Wk0xNC4yMTc1IDU4LjgxOThWNTkuMTIwNkMxNC4yMTc1IDU5LjI0MDQgMTQuMjM5NyA1OS4zNTM3IDE0LjI4MzkgNTkuNDYwNEMxNC4zMzA4IDU5LjU2NzIgMTQuNDAxMSA1OS42NTQ1IDE0LjQ5NDkgNTkuNzIyMkMxNC41ODg2IDU5Ljc4NzMgMTQuNzA1OCA1OS44MTk4IDE0Ljg0NjQgNTkuODE5OEMxNC45ODcxIDU5LjgxOTggMTUuMTAyOSA1OS43ODczIDE1LjE5NDEgNTkuNzIyMkMxNS4yODUyIDU5LjY1NDUgMTUuMzUyOSA1OS41NjcyIDE1LjM5NzIgNTkuNDYwNEMxNS40NDE1IDU5LjM1MzcgMTUuNDYzNiA1OS4yNDA0IDE1LjQ2MzYgNTkuMTIwNlY1OC44MTk4QzE1LjQ2MzYgNTguNjk3NCAxNS40NDAyIDU4LjU4MjggMTUuMzkzMyA1OC40NzYxQzE1LjM0OSA1OC4zNjY3IDE1LjI4IDU4LjI3OTUgMTUuMTg2MyA1OC4yMTQ0QzE1LjA5NTEgNTguMTQ2NiAxNC45NzkzIDU4LjExMjggMTQuODM4NiA1OC4xMTI4QzE0LjcwMDYgNTguMTEyOCAxNC41ODQ3IDU4LjE0NjYgMTQuNDkxIDU4LjIxNDRDMTQuMzk5OCA1OC4yNzk1IDE0LjMzMDggNTguMzY2NyAxNC4yODM5IDU4LjQ3NjFDMTQuMjM5NyA1OC41ODI4IDE0LjIxNzUgNTguNjk3NCAxNC4yMTc1IDU4LjgxOThaTTE2LjQ0NDEgNjIuMzIzN1Y2Mi4wMTlDMTYuNDQ0MSA2MS44MDU1IDE2LjQ5MSA2MS42MTAyIDE2LjU4NDcgNjEuNDMzMUMxNi42Nzg1IDYxLjI1NiAxNi44MTI2IDYxLjExNDEgMTYuOTg3MSA2MS4wMDczQzE3LjE2MTUgNjAuOTAwNiAxNy4zNjg2IDYwLjg0NzIgMTcuNjA4MiA2MC44NDcyQzE3Ljg1MjkgNjAuODQ3MiAxOC4wNjEzIDYwLjkwMDYgMTguMjMzMiA2MS4wMDczQzE4LjQwNzYgNjEuMTE0MSAxOC41NDE4IDYxLjI1NiAxOC42MzU1IDYxLjQzMzFDMTguNzI5MyA2MS42MTAyIDE4Ljc3NjEgNjEuODA1NSAxOC43NzYxIDYyLjAxOVY2Mi4zMjM3QzE4Ljc3NjEgNjIuNTM3MyAxOC43MjkzIDYyLjczMjYgMTguNjM1NSA2Mi45MDk3QzE4LjU0NDQgNjMuMDg2OCAxOC40MTE1IDYzLjIyODcgMTguMjM3MSA2My4zMzU0QzE4LjA2NTIgNjMuNDQyMiAxNy44NTgyIDYzLjQ5NTYgMTcuNjE2IDYzLjQ5NTZDMTcuMzczOCA2My40OTU2IDE3LjE2NTQgNjMuNDQyMiAxNi45OTEgNjMuMzM1NEMxNi44MTY1IDYzLjIyODcgMTYuNjgxMSA2My4wODY4IDE2LjU4NDcgNjIuOTA5N0MxNi40OTEgNjIuNzMyNiAxNi40NDQxIDYyLjUzNzMgMTYuNDQ0MSA2Mi4zMjM3Wk0xNi45ODcxIDYyLjAxOVY2Mi4zMjM3QzE2Ljk4NzEgNjIuNDQzNSAxNy4wMDkyIDYyLjU1ODEgMTcuMDUzNSA2Mi42Njc1QzE3LjEwMDMgNjIuNzc0MyAxNy4xNzA3IDYyLjg2MTUgMTcuMjY0NCA2Mi45MjkyQzE3LjM1ODIgNjIuOTk0MyAxNy40NzUzIDYzLjAyNjkgMTcuNjE2IDYzLjAyNjlDMTcuNzU2NiA2My4wMjY5IDE3Ljg3MjUgNjIuOTk0MyAxNy45NjM2IDYyLjkyOTJDMTguMDU3NCA2Mi44NjE1IDE4LjEyNjQgNjIuNzc0MyAxOC4xNzA3IDYyLjY2NzVDMTguMjE0OSA2Mi41NjA3IDE4LjIzNzEgNjIuNDQ2MSAxOC4yMzcxIDYyLjMyMzdWNjIuMDE5QzE4LjIzNzEgNjEuODk2NiAxOC4yMTM2IDYxLjc4MjEgMTguMTY2OCA2MS42NzUzQzE4LjEyMjUgNjEuNTY4NSAxOC4wNTM1IDYxLjQ4MjYgMTcuOTU5NyA2MS40MTc1QzE3Ljg2ODYgNjEuMzQ5OCAxNy43NTE0IDYxLjMxNTkgMTcuNjA4MiA2MS4zMTU5QzE3LjQ3MDEgNjEuMzE1OSAxNy4zNTQzIDYxLjM0OTggMTcuMjYwNSA2MS40MTc1QzE3LjE2OTQgNjEuNDgyNiAxNy4xMDAzIDYxLjU2ODUgMTcuMDUzNSA2MS42NzUzQzE3LjAwOTIgNjEuNzgyMSAxNi45ODcxIDYxLjg5NjYgMTYuOTg3MSA2Mi4wMTlaTTE3Ljc4NzggNTguNTM0N0wxNS4wMTA1IDYyLjk4TDE0LjYwNDMgNjIuNzIyMkwxNy4zODE2IDU4LjI3NjlMMTcuNzg3OCA1OC41MzQ3WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNOC4zMTY0MSA4OS43MDYzVjkwLjNINC4yMDcwM1Y4OS44NzQzTDYuNzUzOTEgODUuOTMyOUg3LjM0Mzc1TDYuNzEwOTQgODcuMDczNUw1LjAyNzM0IDg5LjcwNjNIOC4zMTY0MVpNNy41MjM0NCA4NS45MzI5VjkxLjYyMDRINi44MDA3OFY4NS45MzI5SDcuNTIzNDRaTTEyLjY3NTIgODguMzIzNVY4OS4xOTA3QzEyLjY3NTIgODkuNjU2OCAxMi42MzM1IDkwLjA1IDEyLjU1MDIgOTAuMzcwNEMxMi40NjY4IDkwLjY5MDcgMTIuMzQ3IDkwLjk0ODUgMTIuMTkwOCA5MS4xNDM4QzEyLjAzNDUgOTEuMzM5MSAxMS44NDU3IDkxLjQ4MSAxMS42MjQ0IDkxLjU2OTZDMTEuNDA1NiA5MS42NTU1IDExLjE1ODIgOTEuNjk4NSAxMC44ODIyIDkxLjY5ODVDMTAuNjYzNSA5MS42OTg1IDEwLjQ2MTYgOTEuNjcxMSAxMC4yNzY3IDkxLjYxNjVDMTAuMDkxOCA5MS41NjE4IDkuOTI1MTcgOTEuNDc0NSA5Ljc3NjczIDkxLjM1NDdDOS42MzA5IDkxLjIzMjMgOS41MDU5IDkxLjA3MzUgOS40MDE3MyA5MC44NzgyQzkuMjk3NTcgOTAuNjgyOSA5LjIxODE0IDkwLjQ0NTkgOS4xNjM0NSA5MC4xNjcyQzkuMTA4NzcgODkuODg4NiA5LjA4MTQyIDg5LjU2MzEgOS4wODE0MiA4OS4xOTA3Vjg4LjMyMzVDOS4wODE0MiA4Ny44NTczIDkuMTIzMDkgODcuNDY2NyA5LjIwNjQyIDg3LjE1MTZDOS4yOTIzNiA4Ni44MzY1IDkuNDEzNDUgODYuNTgzOSA5LjU2OTcgODYuMzkzOEM5LjcyNTk1IDg2LjIwMTEgOS45MTM0NSA4Ni4wNjMxIDEwLjEzMjIgODUuOTc5N0MxMC4zNTM2IDg1Ljg5NjQgMTAuNjAxIDg1Ljg1NDcgMTAuODc0NCA4NS44NTQ3QzExLjA5NTcgODUuODU0NyAxMS4yOTg5IDg1Ljg4MjEgMTEuNDgzOCA4NS45MzY4QzExLjY3MTMgODUuOTg4OSAxMS44Mzc5IDg2LjA3MzUgMTEuOTgzOCA4Ni4xOTA3QzEyLjEyOTYgODYuMzA1MyAxMi4yNTMzIDg2LjQ1ODkgMTIuMzU0OSA4Ni42NTE2QzEyLjQ1OSA4Ni44NDE3IDEyLjUzODUgODcuMDc0OCAxMi41OTMxIDg3LjM1MDhDMTIuNjQ3OCA4Ny42MjY5IDEyLjY3NTIgODcuOTUxMSAxMi42NzUyIDg4LjMyMzVaTTExLjk0ODYgODkuMzA3OVY4OC4yMDI0QzExLjk0ODYgODcuOTQ3MiAxMS45MzMgODcuNzIzMiAxMS45MDE3IDg3LjUzMDVDMTEuODczMSA4Ny4zMzUyIDExLjgzMDEgODcuMTY4NSAxMS43NzI4IDg3LjAzMDVDMTEuNzE1NSA4Ni44OTI1IDExLjY0MjYgODYuNzgwNSAxMS41NTQxIDg2LjY5NDZDMTEuNDY4MSA4Ni42MDg2IDExLjM2NzkgODYuNTQ2MSAxMS4yNTMzIDg2LjUwNzFDMTEuMTQxMyA4Ni40NjU0IDExLjAxNSA4Ni40NDQ2IDEwLjg3NDQgODYuNDQ0NkMxMC43MDI1IDg2LjQ0NDYgMTAuNTUwMiA4Ni40NzcxIDEwLjQxNzQgODYuNTQyMkMxMC4yODQ1IDg2LjYwNDcgMTAuMTcyNiA4Ni43MDUgMTAuMDgxNCA4Ni44NDNDOS45OTI4OCA4Ni45ODEgOS45MjUxNyA4Ny4xNjIgOS44NzgzIDg3LjM4NkM5LjgzMTQyIDg3LjYwOTkgOS44MDc5OCA4Ny44ODIxIDkuODA3OTggODguMjAyNFY4OS4zMDc5QzkuODA3OTggODkuNTYzMSA5LjgyMjMxIDg5Ljc4ODMgOS44NTA5NSA4OS45ODM2QzkuODgyMiA5MC4xNzkgOS45Mjc3OCA5MC4zNDgyIDkuOTg3NjcgOTAuNDkxNUMxMC4wNDc2IDkwLjYzMjEgMTAuMTIwNSA5MC43NDggMTAuMjA2NCA5MC44MzkxQzEwLjI5MjQgOTAuOTMwMyAxMC4zOTEzIDkwLjk5OCAxMC41MDMzIDkxLjA0MjJDMTAuNjE3OSA5MS4wODM5IDEwLjc0NDIgOTEuMTA0NyAxMC44ODIyIDkxLjEwNDdDMTEuMDU5MyA5MS4xMDQ3IDExLjIxNDIgOTEuMDcwOSAxMS4zNDcgOTEuMDAzMkMxMS40Nzk5IDkwLjkzNTUgMTEuNTkwNSA5MC44MyAxMS42NzkxIDkwLjY4NjhDMTEuNzcwMiA5MC41NDA5IDExLjgzNzkgOTAuMzU0NyAxMS44ODIyIDkwLjEyODJDMTEuOTI2NSA4OS44OTkgMTEuOTQ4NiA4OS42MjU2IDExLjk0ODYgODkuMzA3OVpNMTMuNjc0NiA4Ny4zMjc0Vjg3LjAyNjZDMTMuNjc0NiA4Ni44MTA1IDEzLjcyMTQgODYuNjEzOSAxMy44MTUyIDg2LjQzNjhDMTMuOTA4OSA4Ni4yNTk3IDE0LjA0MzEgODYuMTE3OCAxNC4yMTc1IDg2LjAxMUMxNC4zOTIgODUuOTA0MiAxNC41OTkgODUuODUwOCAxNC44Mzg2IDg1Ljg1MDhDMTUuMDgzNCA4NS44NTA4IDE1LjI5MTggODUuOTA0MiAxNS40NjM2IDg2LjAxMUMxNS42MzgxIDg2LjExNzggMTUuNzcyMiA4Ni4yNTk3IDE1Ljg2NiA4Ni40MzY4QzE1Ljk1OTcgODYuNjEzOSAxNi4wMDY2IDg2LjgxMDUgMTYuMDA2NiA4Ny4wMjY2Vjg3LjMyNzRDMTYuMDA2NiA4Ny41MzgzIDE1Ljk1OTcgODcuNzMyMyAxNS44NjYgODcuOTA5NEMxNS43NzQ4IDg4LjA4NjUgMTUuNjQyIDg4LjIyODQgMTUuNDY3NSA4OC4zMzUyQzE1LjI5NTcgODguNDQyIDE1LjA4ODYgODguNDk1NCAxNC44NDY0IDg4LjQ5NTRDMTQuNjA0MyA4OC40OTU0IDE0LjM5NDYgODguNDQyIDE0LjIxNzUgODguMzM1MkMxNC4wNDMxIDg4LjIyODQgMTMuOTA4OSA4OC4wODY1IDEzLjgxNTIgODcuOTA5NEMxMy43MjE0IDg3LjczMjMgMTMuNjc0NiA4Ny41MzgzIDEzLjY3NDYgODcuMzI3NFpNMTQuMjE3NSA4Ny4wMjY2Vjg3LjMyNzRDMTQuMjE3NSA4Ny40NDcyIDE0LjIzOTcgODcuNTYwNSAxNC4yODM5IDg3LjY2NzJDMTQuMzMwOCA4Ny43NzQgMTQuNDAxMSA4Ny44NjEyIDE0LjQ5NDkgODcuOTI5QzE0LjU4ODYgODcuOTk0MSAxNC43MDU4IDg4LjAyNjYgMTQuODQ2NCA4OC4wMjY2QzE0Ljk4NzEgODguMDI2NiAxNS4xMDI5IDg3Ljk5NDEgMTUuMTk0MSA4Ny45MjlDMTUuMjg1MiA4Ny44NjEyIDE1LjM1MjkgODcuNzc0IDE1LjM5NzIgODcuNjY3MkMxNS40NDE1IDg3LjU2MDUgMTUuNDYzNiA4Ny40NDcyIDE1LjQ2MzYgODcuMzI3NFY4Ny4wMjY2QzE1LjQ2MzYgODYuOTA0MiAxNS40NDAyIDg2Ljc4OTYgMTUuMzkzMyA4Ni42ODI5QzE1LjM0OSA4Ni41NzM1IDE1LjI4IDg2LjQ4NjIgMTUuMTg2MyA4Ni40MjExQzE1LjA5NTEgODYuMzUzNCAxNC45NzkzIDg2LjMxOTYgMTQuODM4NiA4Ni4zMTk2QzE0LjcwMDYgODYuMzE5NiAxNC41ODQ3IDg2LjM1MzQgMTQuNDkxIDg2LjQyMTFDMTQuMzk5OCA4Ni40ODYyIDE0LjMzMDggODYuNTczNSAxNC4yODM5IDg2LjY4MjlDMTQuMjM5NyA4Ni43ODk2IDE0LjIxNzUgODYuOTA0MiAxNC4yMTc1IDg3LjAyNjZaTTE2LjQ0NDEgOTAuNTMwNVY5MC4yMjU4QzE2LjQ0NDEgOTAuMDEyMyAxNi40OTEgODkuODE3IDE2LjU4NDcgODkuNjM5OUMxNi42Nzg1IDg5LjQ2MjggMTYuODEyNiA4OS4zMjA5IDE2Ljk4NzEgODkuMjE0MUMxNy4xNjE1IDg5LjEwNzMgMTcuMzY4NiA4OS4wNTQgMTcuNjA4MiA4OS4wNTRDMTcuODUyOSA4OS4wNTQgMTguMDYxMyA4OS4xMDczIDE4LjIzMzIgODkuMjE0MUMxOC40MDc2IDg5LjMyMDkgMTguNTQxOCA4OS40NjI4IDE4LjYzNTUgODkuNjM5OUMxOC43MjkzIDg5LjgxNyAxOC43NzYxIDkwLjAxMjMgMTguNzc2MSA5MC4yMjU4VjkwLjUzMDVDMTguNzc2MSA5MC43NDQxIDE4LjcyOTMgOTAuOTM5NCAxOC42MzU1IDkxLjExNjVDMTguNTQ0NCA5MS4yOTM1IDE4LjQxMTUgOTEuNDM1NSAxOC4yMzcxIDkxLjU0MjJDMTguMDY1MiA5MS42NDkgMTcuODU4MiA5MS43MDI0IDE3LjYxNiA5MS43MDI0QzE3LjM3MzggOTEuNzAyNCAxNy4xNjU0IDkxLjY0OSAxNi45OTEgOTEuNTQyMkMxNi44MTY1IDkxLjQzNTUgMTYuNjgxMSA5MS4yOTM1IDE2LjU4NDcgOTEuMTE2NUMxNi40OTEgOTAuOTM5NCAxNi40NDQxIDkwLjc0NDEgMTYuNDQ0MSA5MC41MzA1Wk0xNi45ODcxIDkwLjIyNThWOTAuNTMwNUMxNi45ODcxIDkwLjY1MDMgMTcuMDA5MiA5MC43NjQ5IDE3LjA1MzUgOTAuODc0M0MxNy4xMDAzIDkwLjk4MSAxNy4xNzA3IDkxLjA2ODMgMTcuMjY0NCA5MS4xMzZDMTcuMzU4MiA5MS4yMDExIDE3LjQ3NTMgOTEuMjMzNiAxNy42MTYgOTEuMjMzNkMxNy43NTY2IDkxLjIzMzYgMTcuODcyNSA5MS4yMDExIDE3Ljk2MzYgOTEuMTM2QzE4LjA1NzQgOTEuMDY4MyAxOC4xMjY0IDkwLjk4MSAxOC4xNzA3IDkwLjg3NDNDMTguMjE0OSA5MC43Njc1IDE4LjIzNzEgOTAuNjUyOSAxOC4yMzcxIDkwLjUzMDVWOTAuMjI1OEMxOC4yMzcxIDkwLjEwMzQgMTguMjEzNiA4OS45ODg5IDE4LjE2NjggODkuODgyMUMxOC4xMjI1IDg5Ljc3NTMgMTguMDUzNSA4OS42ODk0IDE3Ljk1OTcgODkuNjI0M0MxNy44Njg2IDg5LjU1NjYgMTcuNzUxNCA4OS41MjI3IDE3LjYwODIgODkuNTIyN0MxNy40NzAxIDg5LjUyMjcgMTcuMzU0MyA4OS41NTY2IDE3LjI2MDUgODkuNjI0M0MxNy4xNjk0IDg5LjY4OTQgMTcuMTAwMyA4OS43NzUzIDE3LjA1MzUgODkuODgyMUMxNy4wMDkyIDg5Ljk4ODkgMTYuOTg3MSA5MC4xMDM0IDE2Ljk4NzEgOTAuMjI1OFpNMTcuNzg3OCA4Ni43NDE1TDE1LjAxMDUgOTEuMTg2OEwxNC42MDQzIDkwLjkyOUwxNy4zODE2IDg2LjQ4MzZMMTcuNzg3OCA4Ni43NDE1WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNOC4xOTkyMiAxMTkuMjMzVjExOS44MjdINC40NzY1NlYxMTkuMzA4TDYuMzM5ODQgMTE3LjIzM0M2LjU2OTAxIDExNi45NzggNi43NDYwOSAxMTYuNzYyIDYuODcxMDkgMTE2LjU4NUM2Ljk5ODcgMTE2LjQwNSA3LjA4NzI0IDExNi4yNDUgNy4xMzY3MiAxMTYuMTA0QzcuMTg4OCAxMTUuOTYxIDcuMjE0ODQgMTE1LjgxNSA3LjIxNDg0IDExNS42NjdDNy4yMTQ4NCAxMTUuNDc5IDcuMTc1NzggMTE1LjMxIDcuMDk3NjYgMTE1LjE1OUM3LjAyMjE0IDExNS4wMDYgNi45MTAxNiAxMTQuODgzIDYuNzYxNzIgMTE0Ljc5MkM2LjYxMzI4IDExNC43MDEgNi40MzM1OSAxMTQuNjU1IDYuMjIyNjYgMTE0LjY1NUM1Ljk3MDA1IDExNC42NTUgNS43NTkxMSAxMTQuNzA1IDUuNTg5ODQgMTE0LjgwNEM1LjQyMzE4IDExNC45IDUuMjk4MTggMTE1LjAzNSA1LjIxNDg0IDExNS4yMUM1LjEzMTUxIDExNS4zODQgNS4wODk4NCAxMTUuNTg1IDUuMDg5ODQgMTE1LjgxMkg0LjM2NzE5QzQuMzY3MTkgMTE1LjQ5MSA0LjQzNzUgMTE1LjE5OCA0LjU3ODEyIDExNC45MzNDNC43MTg3NSAxMTQuNjY3IDQuOTI3MDggMTE0LjQ1NiA1LjIwMzEyIDExNC4zQzUuNDc5MTcgMTE0LjE0MSA1LjgxOTAxIDExNC4wNjIgNi4yMjI2NiAxMTQuMDYyQzYuNTgyMDMgMTE0LjA2MiA2Ljg4OTMyIDExNC4xMjUgNy4xNDQ1MyAxMTQuMjUzQzcuMzk5NzQgMTE0LjM3OCA3LjU5NTA1IDExNC41NTUgNy43MzA0NyAxMTQuNzg0QzcuODY4NDkgMTE1LjAxMSA3LjkzNzUgMTE1LjI3NiA3LjkzNzUgMTE1LjU4MUM3LjkzNzUgMTE1Ljc0OCA3LjkwODg1IDExNS45MTcgNy44NTE1NiAxMTYuMDg5QzcuNzk2ODggMTE2LjI1OCA3LjcyMDA1IDExNi40MjcgNy42MjEwOSAxMTYuNTk3QzcuNTI0NzQgMTE2Ljc2NiA3LjQxMTQ2IDExNi45MzMgNy4yODEyNSAxMTcuMDk3QzcuMTUzNjUgMTE3LjI2MSA3LjAxNjkzIDExNy40MjIgNi44NzEwOSAxMTcuNTgxTDUuMzQ3NjYgMTE5LjIzM0g4LjE5OTIyWk0xMi42NzUyIDExNi41M1YxMTcuMzk3QzEyLjY3NTIgMTE3Ljg2NCAxMi42MzM1IDExOC4yNTcgMTIuNTUwMiAxMTguNTc3QzEyLjQ2NjggMTE4Ljg5NyAxMi4zNDcgMTE5LjE1NSAxMi4xOTA4IDExOS4zNTFDMTIuMDM0NSAxMTkuNTQ2IDExLjg0NTcgMTE5LjY4OCAxMS42MjQ0IDExOS43NzZDMTEuNDA1NiAxMTkuODYyIDExLjE1ODIgMTE5LjkwNSAxMC44ODIyIDExOS45MDVDMTAuNjYzNSAxMTkuOTA1IDEwLjQ2MTYgMTE5Ljg3OCAxMC4yNzY3IDExOS44MjNDMTAuMDkxOCAxMTkuNzY5IDkuOTI1MTcgMTE5LjY4MSA5Ljc3NjczIDExOS41NjJDOS42MzA5IDExOS40MzkgOS41MDU5IDExOS4yOCA5LjQwMTczIDExOS4wODVDOS4yOTc1NyAxMTguODkgOS4yMTgxNCAxMTguNjUzIDkuMTYzNDUgMTE4LjM3NEM5LjEwODc3IDExOC4wOTUgOS4wODE0MiAxMTcuNzcgOS4wODE0MiAxMTcuMzk3VjExNi41M0M5LjA4MTQyIDExNi4wNjQgOS4xMjMwOSAxMTUuNjc0IDkuMjA2NDIgMTE1LjM1OEM5LjI5MjM2IDExNS4wNDMgOS40MTM0NSAxMTQuNzkxIDkuNTY5NyAxMTQuNjAxQzkuNzI1OTUgMTE0LjQwOCA5LjkxMzQ1IDExNC4yNyAxMC4xMzIyIDExNC4xODdDMTAuMzUzNiAxMTQuMTAzIDEwLjYwMSAxMTQuMDYyIDEwLjg3NDQgMTE0LjA2MkMxMS4wOTU3IDExNC4wNjIgMTEuMjk4OSAxMTQuMDg5IDExLjQ4MzggMTE0LjE0NEMxMS42NzEzIDExNC4xOTYgMTEuODM3OSAxMTQuMjggMTEuOTgzOCAxMTQuMzk3QzEyLjEyOTYgMTE0LjUxMiAxMi4yNTMzIDExNC42NjYgMTIuMzU0OSAxMTQuODU4QzEyLjQ1OSAxMTUuMDQ5IDEyLjUzODUgMTE1LjI4MiAxMi41OTMxIDExNS41NThDMTIuNjQ3OCAxMTUuODM0IDEyLjY3NTIgMTE2LjE1OCAxMi42NzUyIDExNi41M1pNMTEuOTQ4NiAxMTcuNTE1VjExNi40MDlDMTEuOTQ4NiAxMTYuMTU0IDExLjkzMyAxMTUuOTMgMTEuOTAxNyAxMTUuNzM3QzExLjg3MzEgMTE1LjU0MiAxMS44MzAxIDExNS4zNzUgMTEuNzcyOCAxMTUuMjM3QzExLjcxNTUgMTE1LjA5OSAxMS42NDI2IDExNC45ODcgMTEuNTU0MSAxMTQuOTAxQzExLjQ2ODEgMTE0LjgxNSAxMS4zNjc5IDExNC43NTMgMTEuMjUzMyAxMTQuNzE0QzExLjE0MTMgMTE0LjY3MiAxMS4wMTUgMTE0LjY1MSAxMC44NzQ0IDExNC42NTFDMTAuNzAyNSAxMTQuNjUxIDEwLjU1MDIgMTE0LjY4NCAxMC40MTc0IDExNC43NDlDMTAuMjg0NSAxMTQuODEyIDEwLjE3MjYgMTE0LjkxMiAxMC4wODE0IDExNS4wNUM5Ljk5Mjg4IDExNS4xODggOS45MjUxNyAxMTUuMzY5IDkuODc4MyAxMTUuNTkzQzkuODMxNDIgMTE1LjgxNyA5LjgwNzk4IDExNi4wODkgOS44MDc5OCAxMTYuNDA5VjExNy41MTVDOS44MDc5OCAxMTcuNzcgOS44MjIzMSAxMTcuOTk1IDkuODUwOTUgMTE4LjE5QzkuODgyMiAxMTguMzg2IDkuOTI3NzggMTE4LjU1NSA5Ljk4NzY3IDExOC42OThDMTAuMDQ3NiAxMTguODM5IDEwLjEyMDUgMTE4Ljk1NSAxMC4yMDY0IDExOS4wNDZDMTAuMjkyNCAxMTkuMTM3IDEwLjM5MTMgMTE5LjIwNSAxMC41MDMzIDExOS4yNDlDMTAuNjE3OSAxMTkuMjkxIDEwLjc0NDIgMTE5LjMxMiAxMC44ODIyIDExOS4zMTJDMTEuMDU5MyAxMTkuMzEyIDExLjIxNDIgMTE5LjI3OCAxMS4zNDcgMTE5LjIxQzExLjQ3OTkgMTE5LjE0MiAxMS41OTA1IDExOS4wMzcgMTEuNjc5MSAxMTguODk0QzExLjc3MDIgMTE4Ljc0OCAxMS44Mzc5IDExOC41NjIgMTEuODgyMiAxMTguMzM1QzExLjkyNjUgMTE4LjEwNiAxMS45NDg2IDExNy44MzIgMTEuOTQ4NiAxMTcuNTE1Wk0xMy42NzQ2IDExNS41MzRWMTE1LjIzM0MxMy42NzQ2IDExNS4wMTcgMTMuNzIxNCAxMTQuODIxIDEzLjgxNTIgMTE0LjY0NEMxMy45MDg5IDExNC40NjYgMTQuMDQzMSAxMTQuMzI1IDE0LjIxNzUgMTE0LjIxOEMxNC4zOTIgMTE0LjExMSAxNC41OTkgMTE0LjA1OCAxNC44Mzg2IDExNC4wNThDMTUuMDgzNCAxMTQuMDU4IDE1LjI5MTggMTE0LjExMSAxNS40NjM2IDExNC4yMThDMTUuNjM4MSAxMTQuMzI1IDE1Ljc3MjIgMTE0LjQ2NiAxNS44NjYgMTE0LjY0NEMxNS45NTk3IDExNC44MjEgMTYuMDA2NiAxMTUuMDE3IDE2LjAwNjYgMTE1LjIzM1YxMTUuNTM0QzE2LjAwNjYgMTE1Ljc0NSAxNS45NTk3IDExNS45MzkgMTUuODY2IDExNi4xMTZDMTUuNzc0OCAxMTYuMjkzIDE1LjY0MiAxMTYuNDM1IDE1LjQ2NzUgMTE2LjU0MkMxNS4yOTU3IDExNi42NDkgMTUuMDg4NiAxMTYuNzAyIDE0Ljg0NjQgMTE2LjcwMkMxNC42MDQzIDExNi43MDIgMTQuMzk0NiAxMTYuNjQ5IDE0LjIxNzUgMTE2LjU0MkMxNC4wNDMxIDExNi40MzUgMTMuOTA4OSAxMTYuMjkzIDEzLjgxNTIgMTE2LjExNkMxMy43MjE0IDExNS45MzkgMTMuNjc0NiAxMTUuNzQ1IDEzLjY3NDYgMTE1LjUzNFpNMTQuMjE3NSAxMTUuMjMzVjExNS41MzRDMTQuMjE3NSAxMTUuNjU0IDE0LjIzOTcgMTE1Ljc2NyAxNC4yODM5IDExNS44NzRDMTQuMzMwOCAxMTUuOTgxIDE0LjQwMTEgMTE2LjA2OCAxNC40OTQ5IDExNi4xMzZDMTQuNTg4NiAxMTYuMjAxIDE0LjcwNTggMTE2LjIzMyAxNC44NDY0IDExNi4yMzNDMTQuOTg3MSAxMTYuMjMzIDE1LjEwMjkgMTE2LjIwMSAxNS4xOTQxIDExNi4xMzZDMTUuMjg1MiAxMTYuMDY4IDE1LjM1MjkgMTE1Ljk4MSAxNS4zOTcyIDExNS44NzRDMTUuNDQxNSAxMTUuNzY3IDE1LjQ2MzYgMTE1LjY1NCAxNS40NjM2IDExNS41MzRWMTE1LjIzM0MxNS40NjM2IDExNS4xMTEgMTUuNDQwMiAxMTQuOTk2IDE1LjM5MzMgMTE0Ljg5QzE1LjM0OSAxMTQuNzggMTUuMjggMTE0LjY5MyAxNS4xODYzIDExNC42MjhDMTUuMDk1MSAxMTQuNTYgMTQuOTc5MyAxMTQuNTI2IDE0LjgzODYgMTE0LjUyNkMxNC43MDA2IDExNC41MjYgMTQuNTg0NyAxMTQuNTYgMTQuNDkxIDExNC42MjhDMTQuMzk5OCAxMTQuNjkzIDE0LjMzMDggMTE0Ljc4IDE0LjI4MzkgMTE0Ljg5QzE0LjIzOTcgMTE0Ljk5NiAxNC4yMTc1IDExNS4xMTEgMTQuMjE3NSAxMTUuMjMzWk0xNi40NDQxIDExOC43MzdWMTE4LjQzM0MxNi40NDQxIDExOC4yMTkgMTYuNDkxIDExOC4wMjQgMTYuNTg0NyAxMTcuODQ3QzE2LjY3ODUgMTE3LjY3IDE2LjgxMjYgMTE3LjUyOCAxNi45ODcxIDExNy40MjFDMTcuMTYxNSAxMTcuMzE0IDE3LjM2ODYgMTE3LjI2MSAxNy42MDgyIDExNy4yNjFDMTcuODUyOSAxMTcuMjYxIDE4LjA2MTMgMTE3LjMxNCAxOC4yMzMyIDExNy40MjFDMTguNDA3NiAxMTcuNTI4IDE4LjU0MTggMTE3LjY3IDE4LjYzNTUgMTE3Ljg0N0MxOC43MjkzIDExOC4wMjQgMTguNzc2MSAxMTguMjE5IDE4Ljc3NjEgMTE4LjQzM1YxMTguNzM3QzE4Ljc3NjEgMTE4Ljk1MSAxOC43MjkzIDExOS4xNDYgMTguNjM1NSAxMTkuMzIzQzE4LjU0NDQgMTE5LjUgMTguNDExNSAxMTkuNjQyIDE4LjIzNzEgMTE5Ljc0OUMxOC4wNjUyIDExOS44NTYgMTcuODU4MiAxMTkuOTA5IDE3LjYxNiAxMTkuOTA5QzE3LjM3MzggMTE5LjkwOSAxNy4xNjU0IDExOS44NTYgMTYuOTkxIDExOS43NDlDMTYuODE2NSAxMTkuNjQyIDE2LjY4MTEgMTE5LjUgMTYuNTg0NyAxMTkuMzIzQzE2LjQ5MSAxMTkuMTQ2IDE2LjQ0NDEgMTE4Ljk1MSAxNi40NDQxIDExOC43MzdaTTE2Ljk4NzEgMTE4LjQzM1YxMTguNzM3QzE2Ljk4NzEgMTE4Ljg1NyAxNy4wMDkyIDExOC45NzIgMTcuMDUzNSAxMTkuMDgxQzE3LjEwMDMgMTE5LjE4OCAxNy4xNzA3IDExOS4yNzUgMTcuMjY0NCAxMTkuMzQzQzE3LjM1ODIgMTE5LjQwOCAxNy40NzUzIDExOS40NCAxNy42MTYgMTE5LjQ0QzE3Ljc1NjYgMTE5LjQ0IDE3Ljg3MjUgMTE5LjQwOCAxNy45NjM2IDExOS4zNDNDMTguMDU3NCAxMTkuMjc1IDE4LjEyNjQgMTE5LjE4OCAxOC4xNzA3IDExOS4wODFDMTguMjE0OSAxMTguOTc0IDE4LjIzNzEgMTE4Ljg2IDE4LjIzNzEgMTE4LjczN1YxMTguNDMzQzE4LjIzNzEgMTE4LjMxIDE4LjIxMzYgMTE4LjE5NiAxOC4xNjY4IDExOC4wODlDMTguMTIyNSAxMTcuOTgyIDE4LjA1MzUgMTE3Ljg5NiAxNy45NTk3IDExNy44MzFDMTcuODY4NiAxMTcuNzYzIDE3Ljc1MTQgMTE3LjcyOSAxNy42MDgyIDExNy43MjlDMTcuNDcwMSAxMTcuNzI5IDE3LjM1NDMgMTE3Ljc2MyAxNy4yNjA1IDExNy44MzFDMTcuMTY5NCAxMTcuODk2IDE3LjEwMDMgMTE3Ljk4MiAxNy4wNTM1IDExOC4wODlDMTcuMDA5MiAxMTguMTk2IDE2Ljk4NzEgMTE4LjMxIDE2Ljk4NzEgMTE4LjQzM1pNMTcuNzg3OCAxMTQuOTQ4TDE1LjAxMDUgMTE5LjM5NEwxNC42MDQzIDExOS4xMzZMMTcuMzgxNiAxMTQuNjlMMTcuNzg3OCAxMTQuOTQ4WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNMTMuMDQzIDE0NC43MzdWMTQ1LjYwNEMxMy4wNDMgMTQ2LjA3IDEzLjAwMTMgMTQ2LjQ2NCAxMi45MTggMTQ2Ljc4NEMxMi44MzQ2IDE0Ny4xMDQgMTIuNzE0OCAxNDcuMzYyIDEyLjU1ODYgMTQ3LjU1N0MxMi40MDIzIDE0Ny43NTMgMTIuMjEzNSAxNDcuODk1IDExLjk5MjIgMTQ3Ljk4M0MxMS43NzM0IDE0OC4wNjkgMTEuNTI2IDE0OC4xMTIgMTEuMjUgMTQ4LjExMkMxMS4wMzEyIDE0OC4xMTIgMTAuODI5NCAxNDguMDg1IDEwLjY0NDUgMTQ4LjAzQzEwLjQ1OTYgMTQ3Ljk3NSAxMC4yOTMgMTQ3Ljg4OCAxMC4xNDQ1IDE0Ny43NjhDOS45OTg3IDE0Ny42NDYgOS44NzM3IDE0Ny40ODcgOS43Njk1MyAxNDcuMjkyQzkuNjY1MzYgMTQ3LjA5NiA5LjU4NTk0IDE0Ni44NTkgOS41MzEyNSAxNDYuNTgxQzkuNDc2NTYgMTQ2LjMwMiA5LjQ0OTIyIDE0NS45NzcgOS40NDkyMiAxNDUuNjA0VjE0NC43MzdDOS40NDkyMiAxNDQuMjcxIDkuNDkwODkgMTQzLjg4IDkuNTc0MjIgMTQzLjU2NUM5LjY2MDE2IDE0My4yNSA5Ljc4MTI1IDE0Mi45OTcgOS45Mzc1IDE0Mi44MDdDMTAuMDkzOCAxNDIuNjE1IDEwLjI4MTIgMTQyLjQ3NyAxMC41IDE0Mi4zOTNDMTAuNzIxNCAxNDIuMzEgMTAuOTY4OCAxNDIuMjY4IDExLjI0MjIgMTQyLjI2OEMxMS40NjM1IDE0Mi4yNjggMTEuNjY2NyAxNDIuMjk2IDExLjg1MTYgMTQyLjM1QzEyLjAzOTEgMTQyLjQwMiAxMi4yMDU3IDE0Mi40ODcgMTIuMzUxNiAxNDIuNjA0QzEyLjQ5NzQgMTQyLjcxOSAxMi42MjExIDE0Mi44NzIgMTIuNzIyNyAxNDMuMDY1QzEyLjgyNjggMTQzLjI1NSAxMi45MDYyIDE0My40ODggMTIuOTYwOSAxNDMuNzY0QzEzLjAxNTYgMTQ0LjA0IDEzLjA0MyAxNDQuMzY1IDEzLjA0MyAxNDQuNzM3Wk0xMi4zMTY0IDE0NS43MjFWMTQ0LjYxNkMxMi4zMTY0IDE0NC4zNjEgMTIuMzAwOCAxNDQuMTM3IDEyLjI2OTUgMTQzLjk0NEMxMi4yNDA5IDE0My43NDkgMTIuMTk3OSAxNDMuNTgyIDEyLjE0MDYgMTQzLjQ0NEMxMi4wODMzIDE0My4zMDYgMTIuMDEwNCAxNDMuMTk0IDExLjkyMTkgMTQzLjEwOEMxMS44MzU5IDE0My4wMjIgMTEuNzM1NyAxNDIuOTYgMTEuNjIxMSAxNDIuOTIxQzExLjUwOTEgMTQyLjg3OSAxMS4zODI4IDE0Mi44NTggMTEuMjQyMiAxNDIuODU4QzExLjA3MDMgMTQyLjg1OCAxMC45MTggMTQyLjg5MSAxMC43ODUyIDE0Mi45NTZDMTAuNjUyMyAxNDMuMDE4IDEwLjU0MDQgMTQzLjExOSAxMC40NDkyIDE0My4yNTdDMTAuMzYwNyAxNDMuMzk1IDEwLjI5MyAxNDMuNTc2IDEwLjI0NjEgMTQzLjhDMTAuMTk5MiAxNDQuMDI0IDEwLjE3NTggMTQ0LjI5NiAxMC4xNzU4IDE0NC42MTZWMTQ1LjcyMUMxMC4xNzU4IDE0NS45NzcgMTAuMTkwMSAxNDYuMjAyIDEwLjIxODggMTQ2LjM5N0MxMC4yNSAxNDYuNTkzIDEwLjI5NTYgMTQ2Ljc2MiAxMC4zNTU1IDE0Ni45MDVDMTAuNDE1NCAxNDcuMDQ2IDEwLjQ4ODMgMTQ3LjE2MiAxMC41NzQyIDE0Ny4yNTNDMTAuNjYwMiAxNDcuMzQ0IDEwLjc1OTEgMTQ3LjQxMiAxMC44NzExIDE0Ny40NTZDMTAuOTg1NyAxNDcuNDk3IDExLjExMiAxNDcuNTE4IDExLjI1IDE0Ny41MThDMTEuNDI3MSAxNDcuNTE4IDExLjU4MiAxNDcuNDg0IDExLjcxNDggMTQ3LjQxN0MxMS44NDc3IDE0Ny4zNDkgMTEuOTU4MyAxNDcuMjQ0IDEyLjA0NjkgMTQ3LjFDMTIuMTM4IDE0Ni45NTUgMTIuMjA1NyAxNDYuNzY4IDEyLjI1IDE0Ni41NDJDMTIuMjk0MyAxNDYuMzEzIDEyLjMxNjQgMTQ2LjAzOSAxMi4zMTY0IDE0NS43MjFaTTE0LjA0MjQgMTQzLjc0MVYxNDMuNDRDMTQuMDQyNCAxNDMuMjI0IDE0LjA4OTIgMTQzLjAyNyAxNC4xODMgMTQyLjg1QzE0LjI3NjcgMTQyLjY3MyAxNC40MTA4IDE0Mi41MzEgMTQuNTg1MyAxNDIuNDI1QzE0Ljc1OTggMTQyLjMxOCAxNC45NjY4IDE0Mi4yNjQgMTUuMjA2NCAxNDIuMjY0QzE1LjQ1MTIgMTQyLjI2NCAxNS42NTk1IDE0Mi4zMTggMTUuODMxNCAxNDIuNDI1QzE2LjAwNTkgMTQyLjUzMSAxNi4xNCAxNDIuNjczIDE2LjIzMzggMTQyLjg1QzE2LjMyNzUgMTQzLjAyNyAxNi4zNzQ0IDE0My4yMjQgMTYuMzc0NCAxNDMuNDRWMTQzLjc0MUMxNi4zNzQ0IDE0My45NTIgMTYuMzI3NSAxNDQuMTQ2IDE2LjIzMzggMTQ0LjMyM0MxNi4xNDI2IDE0NC41IDE2LjAwOTggMTQ0LjY0MiAxNS44MzUzIDE0NC43NDlDMTUuNjYzNSAxNDQuODU2IDE1LjQ1NjQgMTQ0LjkwOSAxNS4yMTQyIDE0NC45MDlDMTQuOTcyIDE0NC45MDkgMTQuNzYyNCAxNDQuODU2IDE0LjU4NTMgMTQ0Ljc0OUMxNC40MTA4IDE0NC42NDIgMTQuMjc2NyAxNDQuNSAxNC4xODMgMTQ0LjMyM0MxNC4wODkyIDE0NC4xNDYgMTQuMDQyNCAxNDMuOTUyIDE0LjA0MjQgMTQzLjc0MVpNMTQuNTg1MyAxNDMuNDRWMTQzLjc0MUMxNC41ODUzIDE0My44NjEgMTQuNjA3NSAxNDMuOTc0IDE0LjY1MTcgMTQ0LjA4MUMxNC42OTg2IDE0NC4xODggMTQuNzY4OSAxNDQuMjc1IDE0Ljg2MjcgMTQ0LjM0M0MxNC45NTY0IDE0NC40MDggMTUuMDczNiAxNDQuNDQgMTUuMjE0MiAxNDQuNDRDMTUuMzU0OSAxNDQuNDQgMTUuNDcwNyAxNDQuNDA4IDE1LjU2MTkgMTQ0LjM0M0MxNS42NTMgMTQ0LjI3NSAxNS43MjA3IDE0NC4xODggMTUuNzY1IDE0NC4wODFDMTUuODA5MyAxNDMuOTc0IDE1LjgzMTQgMTQzLjg2MSAxNS44MzE0IDE0My43NDFWMTQzLjQ0QzE1LjgzMTQgMTQzLjMxOCAxNS44MDggMTQzLjIwMyAxNS43NjExIDE0My4wOTZDMTUuNzE2OCAxNDIuOTg3IDE1LjY0NzggMTQyLjkgMTUuNTU0MSAxNDIuODM1QzE1LjQ2MjkgMTQyLjc2NyAxNS4zNDcgMTQyLjczMyAxNS4yMDY0IDE0Mi43MzNDMTUuMDY4NCAxNDIuNzMzIDE0Ljk1MjUgMTQyLjc2NyAxNC44NTg4IDE0Mi44MzVDMTQuNzY3NiAxNDIuOSAxNC42OTg2IDE0Mi45ODcgMTQuNjUxNyAxNDMuMDk2QzE0LjYwNzUgMTQzLjIwMyAxNC41ODUzIDE0My4zMTggMTQuNTg1MyAxNDMuNDRaTTE2LjgxMTkgMTQ2Ljk0NFYxNDYuNjM5QzE2LjgxMTkgMTQ2LjQyNiAxNi44NTg4IDE0Ni4yMzEgMTYuOTUyNSAxNDYuMDUzQzE3LjA0NjMgMTQ1Ljg3NiAxNy4xODA0IDE0NS43MzQgMTcuMzU0OSAxNDUuNjI4QzE3LjUyOTMgMTQ1LjUyMSAxNy43MzY0IDE0NS40NjggMTcuOTc2IDE0NS40NjhDMTguMjIwNyAxNDUuNDY4IDE4LjQyOTEgMTQ1LjUyMSAxOC42MDEgMTQ1LjYyOEMxOC43NzU0IDE0NS43MzQgMTguOTA5NSAxNDUuODc2IDE5LjAwMzMgMTQ2LjA1M0MxOS4wOTcgMTQ2LjIzMSAxOS4xNDM5IDE0Ni40MjYgMTkuMTQzOSAxNDYuNjM5VjE0Ni45NDRDMTkuMTQzOSAxNDcuMTU4IDE5LjA5NyAxNDcuMzUzIDE5LjAwMzMgMTQ3LjUzQzE4LjkxMjIgMTQ3LjcwNyAxOC43NzkzIDE0Ny44NDkgMTguNjA0OSAxNDcuOTU2QzE4LjQzMyAxNDguMDYzIDE4LjIyNiAxNDguMTE2IDE3Ljk4MzggMTQ4LjExNkMxNy43NDE2IDE0OC4xMTYgMTcuNTMzMiAxNDguMDYzIDE3LjM1ODggMTQ3Ljk1NkMxNy4xODQzIDE0Ny44NDkgMTcuMDQ4OSAxNDcuNzA3IDE2Ljk1MjUgMTQ3LjUzQzE2Ljg1ODggMTQ3LjM1MyAxNi44MTE5IDE0Ny4xNTggMTYuODExOSAxNDYuOTQ0Wk0xNy4zNTQ5IDE0Ni42MzlWMTQ2Ljk0NEMxNy4zNTQ5IDE0Ny4wNjQgMTcuMzc3IDE0Ny4xNzggMTcuNDIxMyAxNDcuMjg4QzE3LjQ2ODEgMTQ3LjM5NSAxNy41Mzg1IDE0Ny40ODIgMTcuNjMyMiAxNDcuNTVDMTcuNzI2IDE0Ny42MTUgMTcuODQzMSAxNDcuNjQ3IDE3Ljk4MzggMTQ3LjY0N0MxOC4xMjQ0IDE0Ny42NDcgMTguMjQwMyAxNDcuNjE1IDE4LjMzMTQgMTQ3LjU1QzE4LjQyNTIgMTQ3LjQ4MiAxOC40OTQyIDE0Ny4zOTUgMTguNTM4NSAxNDcuMjg4QzE4LjU4MjcgMTQ3LjE4MSAxOC42MDQ5IDE0Ny4wNjYgMTguNjA0OSAxNDYuOTQ0VjE0Ni42MzlDMTguNjA0OSAxNDYuNTE3IDE4LjU4MTQgMTQ2LjQwMiAxOC41MzQ1IDE0Ni4yOTZDMTguNDkwMyAxNDYuMTg5IDE4LjQyMTMgMTQ2LjEwMyAxOC4zMjc1IDE0Ni4wMzhDMTguMjM2NCAxNDUuOTcgMTguMTE5MiAxNDUuOTM2IDE3Ljk3NiAxNDUuOTM2QzE3LjgzNzkgMTQ1LjkzNiAxNy43MjIgMTQ1Ljk3IDE3LjYyODMgMTQ2LjAzOEMxNy41MzcyIDE0Ni4xMDMgMTcuNDY4MSAxNDYuMTg5IDE3LjQyMTMgMTQ2LjI5NkMxNy4zNzcgMTQ2LjQwMiAxNy4zNTQ5IDE0Ni41MTcgMTcuMzU0OSAxNDYuNjM5Wk0xOC4xNTU2IDE0My4xNTVMMTUuMzc4MyAxNDcuNkwxNC45NzIgMTQ3LjM0M0wxNy43NDk0IDE0Mi44OTdMMTguMTU1NiAxNDMuMTU1WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8cGF0aCBkPSJNMjUgNC4xNjExM0wyMDAgNC4xNjExNiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiLz4KPHBhdGggZD0iTTI1IDMzLjE2MTFMMjAwIDMzLjE2MTIiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1vcGFjaXR5PSIwLjEyIi8+CjxwYXRoIGQ9Ik0yNSA2MS4xNjExTDIwMCA2MS4xNjEyIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC4xMiIvPgo8cGF0aCBkPSJNMjUgODkuMTYxMUwyMDAgODkuMTYxMiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuMTIiLz4KPHBhdGggZD0iTTI1IDExOC4xNjFMMjAwIDExOC4xNjEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1vcGFjaXR5PSIwLjEyIi8+CjxsaW5lIHgxPSIyMy4yIiB5MT0iMTQ1Ljk2MSIgeDI9IjIwMi44IiB5Mj0iMTQ1Ljk2MSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuNyIgc3Ryb2tlLXdpZHRoPSIwLjQiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAxXzQxODJfMTExOTMpIj4KPGxpbmUgeDE9IjQwLjQ1IiB5MT0iMTQ3LjA3MiIgeDI9IjQwLjQ1IiB5Mj0iMTQ2LjI1IiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC41IiBzdHJva2Utd2lkdGg9IjAuNSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8cGF0aCBkPSJNMzIuNTA5MSAxNTIuMDI1VjE1Mi44OTNDMzIuNTA5MSAxNTMuMzU5IDMyLjQ2NzQgMTUzLjc1MiAzMi4zODQxIDE1NC4wNzJDMzIuMzAwNyAxNTQuMzkzIDMyLjE4MDkgMTU0LjY1IDMyLjAyNDcgMTU0Ljg0NkMzMS44Njg0IDE1NS4wNDEgMzEuNjc5NiAxNTUuMTgzIDMxLjQ1ODMgMTU1LjI3MUMzMS4yMzk1IDE1NS4zNTcgMzAuOTkyMSAxNTUuNCAzMC43MTYxIDE1NS40QzMwLjQ5NzMgMTU1LjQgMzAuMjk1NSAxNTUuMzczIDMwLjExMDYgMTU1LjMxOEMyOS45MjU3IDE1NS4yNjQgMjkuNzU5MSAxNTUuMTc2IDI5LjYxMDYgMTU1LjA1N0MyOS40NjQ4IDE1NC45MzQgMjkuMzM5OCAxNTQuNzc1IDI5LjIzNTYgMTU0LjU4QzI5LjEzMTUgMTU0LjM4NSAyOS4wNTIgMTU0LjE0OCAyOC45OTczIDE1My44NjlDMjguOTQyNyAxNTMuNTkgMjguOTE1MyAxNTMuMjY1IDI4LjkxNTMgMTUyLjg5M1YxNTIuMDI1QzI4LjkxNTMgMTUxLjU1OSAyOC45NTcgMTUxLjE2OSAyOS4wNDAzIDE1MC44NTRDMjkuMTI2MiAxNTAuNTM4IDI5LjI0NzMgMTUwLjI4NiAyOS40MDM2IDE1MC4wOTZDMjkuNTU5OCAxNDkuOTAzIDI5Ljc0NzMgMTQ5Ljc2NSAyOS45NjYxIDE0OS42ODJDMzAuMTg3NCAxNDkuNTk4IDMwLjQzNDggMTQ5LjU1NyAzMC43MDgzIDE0OS41NTdDMzAuOTI5NiAxNDkuNTU3IDMxLjEzMjggMTQ5LjU4NCAzMS4zMTc3IDE0OS42MzlDMzEuNTA1MiAxNDkuNjkxIDMxLjY3MTggMTQ5Ljc3NSAzMS44MTc3IDE0OS44OTNDMzEuOTYzNSAxNTAuMDA3IDMyLjA4NzIgMTUwLjE2MSAzMi4xODg3IDE1MC4zNTRDMzIuMjkyOSAxNTAuNTQ0IDMyLjM3MjMgMTUwLjc3NyAzMi40MjcgMTUxLjA1M0MzMi40ODE3IDE1MS4zMjkgMzIuNTA5MSAxNTEuNjUzIDMyLjUwOTEgMTUyLjAyNVpNMzEuNzgyNSAxNTMuMDFWMTUxLjkwNEMzMS43ODI1IDE1MS42NDkgMzEuNzY2OSAxNTEuNDI1IDMxLjczNTYgMTUxLjIzMkMzMS43MDcgMTUxLjAzNyAzMS42NjQgMTUwLjg3IDMxLjYwNjcgMTUwLjczMkMzMS41NDk0IDE1MC41OTQgMzEuNDc2NSAxNTAuNDgyIDMxLjM4OCAxNTAuMzk2QzMxLjMwMiAxNTAuMzExIDMxLjIwMTggMTUwLjI0OCAzMS4wODcyIDE1MC4yMDlDMzAuOTc1MiAxNTAuMTY3IDMwLjg0ODkgMTUwLjE0NiAzMC43MDgzIDE1MC4xNDZDMzAuNTM2NCAxNTAuMTQ2IDMwLjM4NDEgMTUwLjE3OSAzMC4yNTEyIDE1MC4yNDRDMzAuMTE4NCAxNTAuMzA3IDMwLjAwNjUgMTUwLjQwNyAyOS45MTUzIDE1MC41NDVDMjkuODI2OCAxNTAuNjgzIDI5Ljc1OTEgMTUwLjg2NCAyOS43MTIyIDE1MS4wODhDMjkuNjY1MyAxNTEuMzEyIDI5LjY0MTkgMTUxLjU4NCAyOS42NDE5IDE1MS45MDRWMTUzLjAxQzI5LjY0MTkgMTUzLjI2NSAyOS42NTYyIDE1My40OSAyOS42ODQ4IDE1My42ODZDMjkuNzE2MSAxNTMuODgxIDI5Ljc2MTcgMTU0LjA1IDI5LjgyMTYgMTU0LjE5M0MyOS44ODE1IDE1NC4zMzQgMjkuOTU0NCAxNTQuNDUgMzAuMDQwMyAxNTQuNTQxQzMwLjEyNjIgMTU0LjYzMiAzMC4yMjUyIDE1NC43IDMwLjMzNzIgMTU0Ljc0NEMzMC40NTE4IDE1NC43ODYgMzAuNTc4MSAxNTQuODA3IDMwLjcxNjEgMTU0LjgwN0MzMC44OTMyIDE1NC44MDcgMzEuMDQ4MSAxNTQuNzczIDMxLjE4MDkgMTU0LjcwNUMzMS4zMTM3IDE1NC42MzcgMzEuNDI0NCAxNTQuNTMyIDMxLjUxMyAxNTQuMzg5QzMxLjYwNDEgMTU0LjI0MyAzMS42NzE4IDE1NC4wNTcgMzEuNzE2MSAxNTMuODNDMzEuNzYwNCAxNTMuNjAxIDMxLjc4MjUgMTUzLjMyNyAzMS43ODI1IDE1My4wMVpNMzUuODk2NCAxNDkuNjA0VjE1NS4zMjJIMzUuMTczN1YxNTAuNTA2TDMzLjcxNjcgMTUxLjAzN1YxNTAuMzg1TDM1Ljc4MzEgMTQ5LjYwNEgzNS44OTY0Wk00MS4xMTI0IDE0OS42MzVWMTU1LjMyMkg0MC4zNTg1VjE0OS42MzVINDEuMTEyNFpNNDMuNDk1MiAxNTIuMTkzVjE1Mi44MTFINDAuOTQ4M1YxNTIuMTkzSDQzLjQ5NTJaTTQzLjg4MTkgMTQ5LjYzNVYxNTAuMjUySDQwLjk0ODNWMTQ5LjYzNUg0My44ODE5Wk00Ni40MjE2IDE1NS40QzQ2LjEyNzMgMTU1LjQgNDUuODYwNCAxNTUuMzUxIDQ1LjYyMDggMTU1LjI1MkM0NS4zODM4IDE1NS4xNSA0NS4xNzk0IDE1NS4wMDggNDUuMDA3NSAxNTQuODI2QzQ0LjgzODMgMTU0LjY0NCA0NC43MDgxIDE1NC40MjggNDQuNjE2OSAxNTQuMTc4QzQ0LjUyNTggMTUzLjkyOCA0NC40ODAyIDE1My42NTQgNDQuNDgwMiAxNTMuMzU3VjE1My4xOTNDNDQuNDgwMiAxNTIuODUgNDQuNTMxIDE1Mi41NDQgNDQuNjMyNSAxNTIuMjc1QzQ0LjczNDEgMTUyLjAwNSA0NC44NzIxIDE1MS43NzUgNDUuMDQ2NiAxNTEuNTg4QzQ1LjIyMTEgMTUxLjQgNDUuNDE5IDE1MS4yNTggNDUuNjQwMyAxNTEuMTYyQzQ1Ljg2MTcgMTUxLjA2NiA0Ni4wOTA5IDE1MS4wMTggNDYuMzI3OCAxNTEuMDE4QzQ2LjYyOTkgMTUxLjAxOCA0Ni44OTAzIDE1MS4wNyA0Ny4xMDkxIDE1MS4xNzRDNDcuMzMwNSAxNTEuMjc4IDQ3LjUxMTQgMTUxLjQyNCA0Ny42NTIxIDE1MS42MTFDNDcuNzkyNyAxNTEuNzk2IDQ3Ljg5NjkgMTUyLjAxNSA0Ny45NjQ2IDE1Mi4yNjhDNDguMDMyMyAxNTIuNTE4IDQ4LjA2NjEgMTUyLjc5MSA0OC4wNjYxIDE1My4wODhWMTUzLjQxMkg0NC45MDk5VjE1Mi44MjJINDcuMzQzNVYxNTIuNzY4QzQ3LjMzMzEgMTUyLjU4IDQ3LjI5NCAxNTIuMzk4IDQ3LjIyNjMgMTUyLjIyMUM0Ny4xNjEyIDE1Mi4wNDQgNDcuMDU3IDE1MS44OTggNDYuOTEzOCAxNTEuNzgzQzQ2Ljc3MDYgMTUxLjY2OSA0Ni41NzUyIDE1MS42MTEgNDYuMzI3OCAxNTEuNjExQzQ2LjE2MzggMTUxLjYxMSA0Ni4wMTI3IDE1MS42NDYgNDUuODc0NyAxNTEuNzE3QzQ1LjczNjcgMTUxLjc4NSA0NS42MTgyIDE1MS44ODYgNDUuNTE5MyAxNTIuMDIxQzQ1LjQyMDMgMTUyLjE1NyA0NS4zNDM1IDE1Mi4zMjIgNDUuMjg4OCAxNTIuNTE4QzQ1LjIzNDEgMTUyLjcxMyA0NS4yMDY4IDE1Mi45MzggNDUuMjA2OCAxNTMuMTkzVjE1My4zNTdDNDUuMjA2OCAxNTMuNTU4IDQ1LjIzNDEgMTUzLjc0NyA0NS4yODg4IDE1My45MjRDNDUuMzQ2MSAxNTQuMDk4IDQ1LjQyODEgMTU0LjI1MiA0NS41MzQ5IDE1NC4zODVDNDUuNjQ0MyAxNTQuNTE4IDQ1Ljc3NTggMTU0LjYyMiA0NS45Mjk0IDE1NC42OTdDNDYuMDg1NyAxNTQuNzczIDQ2LjI2MjcgMTU0LjgxMSA0Ni40NjA3IDE1NC44MTFDNDYuNzE1OSAxNTQuODExIDQ2LjkzMiAxNTQuNzU4IDQ3LjEwOTEgMTU0LjY1NEM0Ny4yODYyIDE1NC41NSA0Ny40NDExIDE1NC40MTEgNDcuNTczOSAxNTQuMjM2TDQ4LjAxMTQgMTU0LjU4NEM0Ny45MjAzIDE1NC43MjIgNDcuODA0NCAxNTQuODU0IDQ3LjY2MzggMTU0Ljk3OUM0Ny41MjMyIDE1NS4xMDQgNDcuMzUgMTU1LjIwNSA0Ny4xNDQzIDE1NS4yODNDNDYuOTQxMSAxNTUuMzYxIDQ2LjcwMDIgMTU1LjQgNDYuNDIxNiAxNTUuNFpNNDguOTg4NiAxNDkuMzIySDQ5LjcxNTJWMTU0LjUwMkw0OS42NTI3IDE1NS4zMjJINDguOTg4NlYxNDkuMzIyWk01Mi41NzA2IDE1My4xNzRWMTUzLjI1NkM1Mi41NzA2IDE1My41NjMgNTIuNTM0MiAxNTMuODQ4IDUyLjQ2MTMgMTU0LjExMUM1Mi4zODgzIDE1NC4zNzIgNTIuMjgxNiAxNTQuNTk4IDUyLjE0MDkgMTU0Ljc5MUM1Mi4wMDAzIDE1NC45ODQgNTEuODI4NCAxNTUuMTMzIDUxLjYyNTMgMTU1LjI0QzUxLjQyMjIgMTU1LjM0NyA1MS4xODkxIDE1NS40IDUwLjkyNjEgMTU1LjRDNTAuNjU3OSAxNTUuNCA1MC40MjIyIDE1NS4zNTUgNTAuMjE5MSAxNTUuMjY0QzUwLjAxODUgMTU1LjE3IDQ5Ljg0OTMgMTU1LjAzNiA0OS43MTEzIDE1NC44NjFDNDkuNTczMiAxNTQuNjg3IDQ5LjQ2MjYgMTU0LjQ3NiA0OS4zNzkyIDE1NC4yMjlDNDkuMjk4NSAxNTMuOTgxIDQ5LjI0MjUgMTUzLjcwMiA0OS4yMTEzIDE1My4zOTNWMTUzLjAzM0M0OS4yNDI1IDE1Mi43MjEgNDkuMjk4NSAxNTIuNDQxIDQ5LjM3OTIgMTUyLjE5M0M0OS40NjI2IDE1MS45NDYgNDkuNTczMiAxNTEuNzM1IDQ5LjcxMTMgMTUxLjU2MUM0OS44NDkzIDE1MS4zODMgNTAuMDE4NSAxNTEuMjQ5IDUwLjIxOTEgMTUxLjE1OEM1MC40MTk2IDE1MS4wNjQgNTAuNjUyNyAxNTEuMDE4IDUwLjkxODMgMTUxLjAxOEM1MS4xODM5IDE1MS4wMTggNTEuNDE5NiAxNTEuMDcgNTEuNjI1MyAxNTEuMTc0QzUxLjgzMSAxNTEuMjc1IDUyLjAwMjkgMTUxLjQyMSA1Mi4xNDA5IDE1MS42MTFDNTIuMjgxNiAxNTEuODAxIDUyLjM4ODMgMTUyLjAyOSA1Mi40NjEzIDE1Mi4yOTVDNTIuNTM0MiAxNTIuNTU4IDUyLjU3MDYgMTUyLjg1MSA1Mi41NzA2IDE1My4xNzRaTTUxLjg0NDEgMTUzLjI1NlYxNTMuMTc0QzUxLjg0NDEgMTUyLjk2MyA1MS44MjQ1IDE1Mi43NjUgNTEuNzg1NSAxNTIuNThDNTEuNzQ2NCAxNTIuMzkzIDUxLjY4MzkgMTUyLjIyOSA1MS41OTggMTUyLjA4OEM1MS41MTIgMTUxLjk0NSA1MS4zOTg4IDE1MS44MzMgNTEuMjU4MSAxNTEuNzUyQzUxLjExNzUgMTUxLjY2OSA1MC45NDQzIDE1MS42MjcgNTAuNzM4NiAxNTEuNjI3QzUwLjU1NjMgMTUxLjYyNyA1MC4zOTc1IDE1MS42NTggNTAuMjYyIDE1MS43MjFDNTAuMTI5MiAxNTEuNzgzIDUwLjAxNTkgMTUxLjg2OCA0OS45MjIyIDE1MS45NzVDNDkuODI4NCAxNTIuMDc5IDQ5Ljc1MTYgMTUyLjE5OSA0OS42OTE3IDE1Mi4zMzRDNDkuNjM0NCAxNTIuNDY3IDQ5LjU5MTUgMTUyLjYwNSA0OS41NjI4IDE1Mi43NDhWMTUzLjY4OUM0OS42MDQ1IDE1My44NzIgNDkuNjcyMiAxNTQuMDQ4IDQ5Ljc2NTkgMTU0LjIxN0M0OS44NjIzIDE1NC4zODMgNDkuOTg5OSAxNTQuNTIgNTAuMTQ4OCAxNTQuNjI3QzUwLjMxMDIgMTU0LjczNCA1MC41MDk0IDE1NC43ODcgNTAuNzQ2NCAxNTQuNzg3QzUwLjk0MTcgMTU0Ljc4NyA1MS4xMDg0IDE1NC43NDggNTEuMjQ2NCAxNTQuNjdDNTEuMzg3IDE1NC41ODkgNTEuNTAwMyAxNTQuNDc5IDUxLjU4NjMgMTU0LjMzOEM1MS42NzQ4IDE1NC4xOTcgNTEuNzM5OSAxNTQuMDM1IDUxLjc4MTYgMTUzLjg1QzUxLjgyMzIgMTUzLjY2NSA1MS44NDQxIDE1My40NjcgNTEuODQ0MSAxNTMuMjU2WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8L2c+CjxsaW5lIHgxPSI1OC4xNDk5IiB5MT0iMTQ3LjIzMyIgeDI9IjU4LjE0OTkiIHkyPSIxNDYuNDExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC41IiBzdHJva2Utd2lkdGg9IjAuNSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDJfNDE4Ml8xMTE5MykiPgo8bGluZSB4MT0iNzUuODQ5OSIgeTE9IjE0Ny4yMzMiIHgyPSI3NS44NDk5IiB5Mj0iMTQ2LjQxMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuNSIgc3Ryb2tlLXdpZHRoPSIwLjUiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz4KPHBhdGggZD0iTTY3LjkwOSAxNTIuMTg2VjE1My4wNTNDNjcuOTA5IDE1My41MiA2Ny44NjczIDE1My45MTMgNjcuNzg0IDE1NC4yMzNDNjcuNzAwNiAxNTQuNTUzIDY3LjU4MDggMTU0LjgxMSA2Ny40MjQ2IDE1NS4wMDdDNjcuMjY4MyAxNTUuMjAyIDY3LjA3OTUgMTU1LjM0NCA2Ni44NTgyIDE1NS40MzJDNjYuNjM5NCAxNTUuNTE4IDY2LjM5MiAxNTUuNTYxIDY2LjExNiAxNTUuNTYxQzY1Ljg5NzIgMTU1LjU2MSA2NS42OTU0IDE1NS41MzQgNjUuNTEwNSAxNTUuNDc5QzY1LjMyNTYgMTU1LjQyNSA2NS4xNTkgMTU1LjMzNyA2NS4wMTA1IDE1NS4yMThDNjQuODY0NyAxNTUuMDk1IDY0LjczOTcgMTU0LjkzNiA2NC42MzU1IDE1NC43NDFDNjQuNTMxNCAxNTQuNTQ2IDY0LjQ1MTkgMTU0LjMwOSA2NC4zOTcyIDE1NC4wM0M2NC4zNDI2IDE1My43NTEgNjQuMzE1MiAxNTMuNDI2IDY0LjMxNTIgMTUzLjA1M1YxNTIuMTg2QzY0LjMxNTIgMTUxLjcyIDY0LjM1NjkgMTUxLjMzIDY0LjQ0MDIgMTUxLjAxNEM2NC41MjYxIDE1MC42OTkgNjQuNjQ3MiAxNTAuNDQ3IDY0LjgwMzUgMTUwLjI1N0M2NC45NTk3IDE1MC4wNjQgNjUuMTQ3MiAxNDkuOTI2IDY1LjM2NiAxNDkuODQzQzY1LjU4NzMgMTQ5Ljc1OSA2NS44MzQ3IDE0OS43MTggNjYuMTA4MiAxNDkuNzE4QzY2LjMyOTUgMTQ5LjcxOCA2Ni41MzI3IDE0OS43NDUgNjYuNzE3NiAxNDkuOEM2Ni45MDUxIDE0OS44NTIgNjcuMDcxNyAxNDkuOTM2IDY3LjIxNzYgMTUwLjA1M0M2Ny4zNjM0IDE1MC4xNjggNjcuNDg3MSAxNTAuMzIyIDY3LjU4ODYgMTUwLjUxNEM2Ny42OTI4IDE1MC43MDUgNjcuNzcyMiAxNTAuOTM4IDY3LjgyNjkgMTUxLjIxNEM2Ny44ODE2IDE1MS40OSA2Ny45MDkgMTUxLjgxNCA2Ny45MDkgMTUyLjE4NlpNNjcuMTgyNCAxNTMuMTcxVjE1Mi4wNjVDNjcuMTgyNCAxNTEuODEgNjcuMTY2OCAxNTEuNTg2IDY3LjEzNTUgMTUxLjM5M0M2Ny4xMDY5IDE1MS4xOTggNjcuMDYzOSAxNTEuMDMxIDY3LjAwNjYgMTUwLjg5M0M2Ni45NDkzIDE1MC43NTUgNjYuODc2NCAxNTAuNjQzIDY2Ljc4NzkgMTUwLjU1N0M2Ni43MDE5IDE1MC40NzEgNjYuNjAxNyAxNTAuNDA5IDY2LjQ4NzEgMTUwLjM3QzY2LjM3NTEgMTUwLjMyOCA2Ni4yNDg4IDE1MC4zMDcgNjYuMTA4MiAxNTAuMzA3QzY1LjkzNjMgMTUwLjMwNyA2NS43ODQgMTUwLjM0IDY1LjY1MTEgMTUwLjQwNUM2NS41MTgzIDE1MC40NjggNjUuNDA2NCAxNTAuNTY4IDY1LjMxNTIgMTUwLjcwNkM2NS4yMjY3IDE1MC44NDQgNjUuMTU5IDE1MS4wMjUgNjUuMTEyMSAxNTEuMjQ5QzY1LjA2NTIgMTUxLjQ3MyA2NS4wNDE4IDE1MS43NDUgNjUuMDQxOCAxNTIuMDY1VjE1My4xNzFDNjUuMDQxOCAxNTMuNDI2IDY1LjA1NjEgMTUzLjY1MSA2NS4wODQ3IDE1My44NDZDNjUuMTE2IDE1NC4wNDIgNjUuMTYxNiAxNTQuMjExIDY1LjIyMTUgMTU0LjM1NEM2NS4yODE0IDE1NC40OTUgNjUuMzU0MyAxNTQuNjExIDY1LjQ0MDIgMTU0LjcwMkM2NS41MjYxIDE1NC43OTMgNjUuNjI1MSAxNTQuODYxIDY1LjczNzEgMTU0LjkwNUM2NS44NTE3IDE1NC45NDcgNjUuOTc4IDE1NC45NjggNjYuMTE2IDE1NC45NjhDNjYuMjkzMSAxNTQuOTY4IDY2LjQ0OCAxNTQuOTM0IDY2LjU4MDggMTU0Ljg2NkM2Ni43MTM2IDE1NC43OTggNjYuODI0MyAxNTQuNjkzIDY2LjkxMjkgMTU0LjU1QzY3LjAwNCAxNTQuNDA0IDY3LjA3MTcgMTU0LjIxOCA2Ny4xMTYgMTUzLjk5MUM2Ny4xNjAzIDE1My43NjIgNjcuMTgyNCAxNTMuNDg4IDY3LjE4MjQgMTUzLjE3MVpNNjkuOTc2IDE1Mi4yODRINzAuNDkxNkM3MC43NDQyIDE1Mi4yODQgNzAuOTUyNSAxNTIuMjQyIDcxLjExNjYgMTUyLjE1OUM3MS4yODMzIDE1Mi4wNzMgNzEuNDA3IDE1MS45NTcgNzEuNDg3NyAxNTEuODExQzcxLjU3MSAxNTEuNjYzIDcxLjYxMjcgMTUxLjQ5NiA3MS42MTI3IDE1MS4zMTFDNzEuNjEyNyAxNTEuMDkzIDcxLjU3NjIgMTUwLjkwOSA3MS41MDMzIDE1MC43NkM3MS40MzA0IDE1MC42MTIgNzEuMzIxIDE1MC41IDcxLjE3NTIgMTUwLjQyNUM3MS4wMjkzIDE1MC4zNDkgNzAuODQ0NSAxNTAuMzExIDcwLjYyMDUgMTUwLjMxMUM3MC40MTc0IDE1MC4zMTEgNzAuMjM3NyAxNTAuMzUyIDcwLjA4MTQgMTUwLjQzMkM2OS45Mjc4IDE1MC41MSA2OS44MDY3IDE1MC42MjIgNjkuNzE4MiAxNTAuNzY4QzY5LjYzMjIgMTUwLjkxNCA2OS41ODkyIDE1MS4wODYgNjkuNTg5MiAxNTEuMjg0SDY4Ljg2NjZDNjguODY2NiAxNTAuOTk1IDY4LjkzOTUgMTUwLjczMiA2OS4wODUzIDE1MC40OTVDNjkuMjMxMiAxNTAuMjU4IDY5LjQzNTYgMTUwLjA2OSA2OS42OTg2IDE0OS45MjhDNjkuOTY0MiAxNDkuNzg4IDcwLjI3MTUgMTQ5LjcxOCA3MC42MjA1IDE0OS43MThDNzAuOTY0MiAxNDkuNzE4IDcxLjI2NSAxNDkuNzc5IDcxLjUyMjggMTQ5LjkwMUM3MS43ODA3IDE1MC4wMjEgNzEuOTgxMiAxNTAuMjAxIDcyLjEyNDQgMTUwLjQ0QzcyLjI2NzYgMTUwLjY3NyA3Mi4zMzkyIDE1MC45NzMgNzIuMzM5MiAxNTEuMzI3QzcyLjMzOTIgMTUxLjQ3IDcyLjMwNTQgMTUxLjYyNCA3Mi4yMzc3IDE1MS43ODhDNzIuMTcyNiAxNTEuOTQ5IDcyLjA2OTcgMTUyLjEgNzEuOTI5MSAxNTIuMjQxQzcxLjc5MTEgMTUyLjM4MiA3MS42MTE0IDE1Mi40OTcgNzEuMzkgMTUyLjU4OUM3MS4xNjg3IDE1Mi42NzcgNzAuOTAzIDE1Mi43MjEgNzAuNTkzMiAxNTIuNzIxSDY5Ljk3NlYxNTIuMjg0Wk02OS45NzYgMTUyLjg3OFYxNTIuNDQ0SDcwLjU5MzJDNzAuOTU1MSAxNTIuNDQ0IDcxLjI1NDYgMTUyLjQ4NyA3MS40OTE2IDE1Mi41NzNDNzEuNzI4NiAxNTIuNjU5IDcxLjkxNDggMTUyLjc3NCA3Mi4wNTAyIDE1Mi45MTdDNzIuMTg4MiAxNTMuMDYgNzIuMjg0NiAxNTMuMjE4IDcyLjMzOTIgMTUzLjM4OUM3Mi4zOTY1IDE1My41NTkgNzIuNDI1MiAxNTMuNzI4IDcyLjQyNTIgMTUzLjg5N0M3Mi40MjUyIDE1NC4xNjMgNzIuMzc5NiAxNTQuMzk5IDcyLjI4ODUgMTU0LjYwNEM3Mi4xOTk5IDE1NC44MSA3Mi4wNzM2IDE1NC45ODQgNzEuOTA5NiAxNTUuMTI4QzcxLjc0ODEgMTU1LjI3MSA3MS41NTggMTU1LjM3OSA3MS4zMzkyIDE1NS40NTJDNzEuMTIwNSAxNTUuNTI1IDcwLjg4MjIgMTU1LjU2MSA3MC42MjQ0IDE1NS41NjFDNzAuMzc3IDE1NS41NjEgNzAuMTQzOSAxNTUuNTI2IDY5LjkyNTIgMTU1LjQ1NkM2OS43MDkgMTU1LjM4NSA2OS41MTc2IDE1NS4yODQgNjkuMzUxIDE1NS4xNTFDNjkuMTg0MyAxNTUuMDE2IDY5LjA1NDEgMTU0Ljg1IDY4Ljk2MDMgMTU0LjY1NUM2OC44NjY2IDE1NC40NTcgNjguODE5NyAxNTQuMjMyIDY4LjgxOTcgMTUzLjk3OUg2OS41NDI0QzY5LjU0MjQgMTU0LjE3NyA2OS41ODUzIDE1NC4zNSA2OS42NzEzIDE1NC40OTlDNjkuNzU5OCAxNTQuNjQ3IDY5Ljg4NDggMTU0Ljc2MyA3MC4wNDYzIDE1NC44NDZDNzAuMjEwMyAxNTQuOTI3IDcwLjQwMyAxNTQuOTY4IDcwLjYyNDQgMTU0Ljk2OEM3MC44NDU4IDE1NC45NjggNzEuMDM1OSAxNTQuOTMgNzEuMTk0NyAxNTQuODU0QzcxLjM1NjIgMTU0Ljc3NiA3MS40Nzk5IDE1NC42NTkgNzEuNTY1OCAxNTQuNTAzQzcxLjY1NDMgMTU0LjM0NiA3MS42OTg2IDE1NC4xNSA3MS42OTg2IDE1My45MTNDNzEuNjk4NiAxNTMuNjc2IDcxLjY0OTEgMTUzLjQ4MiA3MS41NTAyIDE1My4zMzFDNzEuNDUxMiAxNTMuMTc3IDcxLjMxMDYgMTUzLjA2NCA3MS4xMjgzIDE1Mi45OTFDNzAuOTQ4NiAxNTIuOTE1IDcwLjczNjQgMTUyLjg3OCA3MC40OTE2IDE1Mi44NzhINjkuOTc2Wk03Ni41MTIzIDE0OS43OTZWMTU1LjQ4M0g3NS43NTg0VjE0OS43OTZINzYuNTEyM1pNNzguODk1MSAxNTIuMzU0VjE1Mi45NzFINzYuMzQ4MlYxNTIuMzU0SDc4Ljg5NTFaTTc5LjI4MTggMTQ5Ljc5NlYxNTAuNDEzSDc2LjM0ODJWMTQ5Ljc5Nkg3OS4yODE4Wk04MS44MjE1IDE1NS41NjFDODEuNTI3MiAxNTUuNTYxIDgxLjI2MDMgMTU1LjUxMiA4MS4wMjA3IDE1NS40MTNDODAuNzgzNyAxNTUuMzExIDgwLjU3OTMgMTU1LjE2OSA4MC40MDc0IDE1NC45ODdDODAuMjM4MiAxNTQuODA1IDgwLjEwOCAxNTQuNTg5IDgwLjAxNjggMTU0LjMzOUM3OS45MjU3IDE1NC4wODkgNzkuODgwMSAxNTMuODE1IDc5Ljg4MDEgMTUzLjUxOFYxNTMuMzU0Qzc5Ljg4MDEgMTUzLjAxIDc5LjkzMDkgMTUyLjcwNSA4MC4wMzI0IDE1Mi40MzZDODAuMTM0IDE1Mi4xNjUgODAuMjcyIDE1MS45MzYgODAuNDQ2NSAxNTEuNzQ5QzgwLjYyMSAxNTEuNTYxIDgwLjgxODkgMTUxLjQxOSA4MS4wNDAyIDE1MS4zMjNDODEuMjYxNiAxNTEuMjI3IDgxLjQ5MDggMTUxLjE3OCA4MS43Mjc3IDE1MS4xNzhDODIuMDI5OCAxNTEuMTc4IDgyLjI5MDIgMTUxLjIzMSA4Mi41MDkgMTUxLjMzNUM4Mi43MzA0IDE1MS40MzkgODIuOTExMyAxNTEuNTg1IDgzLjA1MiAxNTEuNzcyQzgzLjE5MjYgMTUxLjk1NyA4My4yOTY4IDE1Mi4xNzYgODMuMzY0NSAxNTIuNDI4QzgzLjQzMjIgMTUyLjY3OCA4My40NjYgMTUyLjk1MiA4My40NjYgMTUzLjI0OVYxNTMuNTczSDgwLjMwOThWMTUyLjk4M0g4Mi43NDM0VjE1Mi45MjhDODIuNzMzIDE1Mi43NDEgODIuNjkzOSAxNTIuNTU5IDgyLjYyNjIgMTUyLjM4MkM4Mi41NjExIDE1Mi4yMDUgODIuNDU2OSAxNTIuMDU5IDgyLjMxMzcgMTUxLjk0NEM4Mi4xNzA1IDE1MS44MyA4MS45NzUxIDE1MS43NzIgODEuNzI3NyAxNTEuNzcyQzgxLjU2MzcgMTUxLjc3MiA4MS40MTI2IDE1MS44MDcgODEuMjc0NiAxNTEuODc4QzgxLjEzNjYgMTUxLjk0NSA4MS4wMTgxIDE1Mi4wNDcgODAuOTE5MiAxNTIuMTgyQzgwLjgyMDIgMTUyLjMxOCA4MC43NDM0IDE1Mi40ODMgODAuNjg4NyAxNTIuNjc4QzgwLjYzNCAxNTIuODc0IDgwLjYwNjcgMTUzLjA5OSA4MC42MDY3IDE1My4zNTRWMTUzLjUxOEM4MC42MDY3IDE1My43MTkgODAuNjM0IDE1My45MDggODAuNjg4NyAxNTQuMDg1QzgwLjc0NiAxNTQuMjU5IDgwLjgyOCAxNTQuNDEzIDgwLjkzNDggMTU0LjU0NkM4MS4wNDQyIDE1NC42NzggODEuMTc1NyAxNTQuNzgzIDgxLjMyOTMgMTU0Ljg1OEM4MS40ODU2IDE1NC45MzQgODEuNjYyNiAxNTQuOTcxIDgxLjg2MDYgMTU0Ljk3MUM4Mi4xMTU4IDE1NC45NzEgODIuMzMxOSAxNTQuOTE5IDgyLjUwOSAxNTQuODE1QzgyLjY4NjEgMTU0LjcxMSA4Mi44NDEgMTU0LjU3MiA4Mi45NzM4IDE1NC4zOTdMODMuNDExMyAxNTQuNzQ1QzgzLjMyMDIgMTU0Ljg4MyA4My4yMDQzIDE1NS4wMTQgODMuMDYzNyAxNTUuMTM5QzgyLjkyMzEgMTU1LjI2NCA4Mi43NDk5IDE1NS4zNjYgODIuNTQ0MiAxNTUuNDQ0QzgyLjM0MSAxNTUuNTIyIDgyLjEwMDEgMTU1LjU2MSA4MS44MjE1IDE1NS41NjFaTTg0LjM4ODUgMTQ5LjQ4M0g4NS4xMTUxVjE1NC42NjNMODUuMDUyNiAxNTUuNDgzSDg0LjM4ODVWMTQ5LjQ4M1pNODcuOTcwNSAxNTMuMzM1VjE1My40MTdDODcuOTcwNSAxNTMuNzI0IDg3LjkzNDEgMTU0LjAwOSA4Ny44NjEyIDE1NC4yNzJDODcuNzg4MiAxNTQuNTMzIDg3LjY4MTUgMTU0Ljc1OSA4Ny41NDA4IDE1NC45NTJDODcuNDAwMiAxNTUuMTQ1IDg3LjIyODMgMTU1LjI5NCA4Ny4wMjUyIDE1NS40MDFDODYuODIyMSAxNTUuNTA4IDg2LjU4OSAxNTUuNTYxIDg2LjMyNiAxNTUuNTYxQzg2LjA1NzggMTU1LjU2MSA4NS44MjIxIDE1NS41MTYgODUuNjE5IDE1NS40MjVDODUuNDE4NSAxNTUuMzMxIDg1LjI0OTIgMTU1LjE5NyA4NS4xMTEyIDE1NS4wMjJDODQuOTczMSAxNTQuODQ4IDg0Ljg2MjUgMTU0LjYzNyA4NC43NzkxIDE1NC4zODlDODQuNjk4NCAxNTQuMTQyIDg0LjY0MjQgMTUzLjg2MyA4NC42MTEyIDE1My41NTNWMTUzLjE5NEM4NC42NDI0IDE1Mi44ODIgODQuNjk4NCAxNTIuNjAyIDg0Ljc3OTEgMTUyLjM1NEM4NC44NjI1IDE1Mi4xMDcgODQuOTczMSAxNTEuODk2IDg1LjExMTIgMTUxLjcyMUM4NS4yNDkyIDE1MS41NDQgODUuNDE4NSAxNTEuNDEgODUuNjE5IDE1MS4zMTlDODUuODE5NSAxNTEuMjI1IDg2LjA1MjYgMTUxLjE3OCA4Ni4zMTgyIDE1MS4xNzhDODYuNTgzOCAxNTEuMTc4IDg2LjgxOTUgMTUxLjIzMSA4Ny4wMjUyIDE1MS4zMzVDODcuMjMxIDE1MS40MzYgODcuNDAyOCAxNTEuNTgyIDg3LjU0MDggMTUxLjc3MkM4Ny42ODE1IDE1MS45NjIgODcuNzg4MiAxNTIuMTkgODcuODYxMiAxNTIuNDU2Qzg3LjkzNDEgMTUyLjcxOSA4Ny45NzA1IDE1My4wMTIgODcuOTcwNSAxNTMuMzM1Wk04Ny4yNDQgMTUzLjQxN1YxNTMuMzM1Qzg3LjI0NCAxNTMuMTI0IDg3LjIyNDQgMTUyLjkyNiA4Ny4xODU0IDE1Mi43NDFDODcuMTQ2MyAxNTIuNTUzIDg3LjA4MzggMTUyLjM4OSA4Ni45OTc5IDE1Mi4yNDlDODYuOTExOSAxNTIuMTA2IDg2Ljc5ODcgMTUxLjk5NCA4Ni42NTggMTUxLjkxM0M4Ni41MTc0IDE1MS44MyA4Ni4zNDQyIDE1MS43ODggODYuMTM4NSAxNTEuNzg4Qzg1Ljk1NjIgMTUxLjc4OCA4NS43OTc0IDE1MS44MTkgODUuNjYxOSAxNTEuODgyQzg1LjUyOTEgMTUxLjk0NCA4NS40MTU4IDE1Mi4wMjkgODUuMzIyMSAxNTIuMTM1Qzg1LjIyODMgMTUyLjI0IDg1LjE1MTUgMTUyLjM1OSA4NS4wOTE2IDE1Mi40OTVDODUuMDM0MyAxNTIuNjI4IDg0Ljk5MTQgMTUyLjc2NiA4NC45NjI3IDE1Mi45MDlWMTUzLjg1Qzg1LjAwNDQgMTU0LjAzMyA4NS4wNzIxIDE1NC4yMDggODUuMTY1OCAxNTQuMzc4Qzg1LjI2MjIgMTU0LjU0NCA4NS4zODk4IDE1NC42ODEgODUuNTQ4NyAxNTQuNzg4Qzg1LjcxMDEgMTU0Ljg5NSA4NS45MDkzIDE1NC45NDggODYuMTQ2MyAxNTQuOTQ4Qzg2LjM0MTYgMTU0Ljk0OCA4Ni41MDgzIDE1NC45MDkgODYuNjQ2MyAxNTQuODMxQzg2Ljc4NjkgMTU0Ljc1IDg2LjkwMDIgMTU0LjYzOSA4Ni45ODYyIDE1NC40OTlDODcuMDc0NyAxNTQuMzU4IDg3LjEzOTggMTU0LjE5NSA4Ny4xODE1IDE1NC4wMUM4Ny4yMjMxIDE1My44MjYgODcuMjQ0IDE1My42MjggODcuMjQ0IDE1My40MTdaIiBmaWxsPSJibGFjayIgZmlsbC1vcGFjaXR5PSIwLjU0Ii8+CjwvZz4KPGxpbmUgeDE9IjkzLjU1IiB5MT0iMTQ3LjIzMyIgeDI9IjkzLjU1IiB5Mj0iMTQ2LjQxMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuNSIgc3Ryb2tlLXdpZHRoPSIwLjUiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAzXzQxODJfMTExOTMpIj4KPGxpbmUgeDE9IjExMS4yNSIgeTE9IjE0Ny4yMzMiIHgyPSIxMTEuMjUiIHkyPSIxNDYuNDExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC41IiBzdHJva2Utd2lkdGg9IjAuNSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8cGF0aCBkPSJNMTAzLjMwOSAxNTIuMTg2VjE1My4wNTNDMTAzLjMwOSAxNTMuNTIgMTAzLjI2NyAxNTMuOTEzIDEwMy4xODQgMTU0LjIzM0MxMDMuMTAxIDE1NC41NTMgMTAyLjk4MSAxNTQuODExIDEwMi44MjUgMTU1LjAwN0MxMDIuNjY4IDE1NS4yMDIgMTAyLjQ4IDE1NS4zNDQgMTAyLjI1OCAxNTUuNDMyQzEwMi4wNCAxNTUuNTE4IDEwMS43OTIgMTU1LjU2MSAxMDEuNTE2IDE1NS41NjFDMTAxLjI5NyAxNTUuNTYxIDEwMS4wOTYgMTU1LjUzNCAxMDAuOTExIDE1NS40NzlDMTAwLjcyNiAxNTUuNDI1IDEwMC41NTkgMTU1LjMzNyAxMDAuNDExIDE1NS4yMThDMTAwLjI2NSAxNTUuMDk1IDEwMC4xNCAxNTQuOTM2IDEwMC4wMzYgMTU0Ljc0MUM5OS45MzE1IDE1NC41NDYgOTkuODUyMSAxNTQuMzA5IDk5Ljc5NzQgMTU0LjAzQzk5Ljc0MjcgMTUzLjc1MSA5OS43MTU0IDE1My40MjYgOTkuNzE1NCAxNTMuMDUzVjE1Mi4xODZDOTkuNzE1NCAxNTEuNzIgOTkuNzU3IDE1MS4zMyA5OS44NDA0IDE1MS4wMTRDOTkuOTI2MyAxNTAuNjk5IDEwMC4wNDcgMTUwLjQ0NyAxMDAuMjA0IDE1MC4yNTdDMTAwLjM2IDE1MC4wNjQgMTAwLjU0NyAxNDkuOTI2IDEwMC43NjYgMTQ5Ljg0M0MxMDAuOTg3IDE0OS43NTkgMTAxLjIzNSAxNDkuNzE4IDEwMS41MDggMTQ5LjcxOEMxMDEuNzMgMTQ5LjcxOCAxMDEuOTMzIDE0OS43NDUgMTAyLjExOCAxNDkuOEMxMDIuMzA1IDE0OS44NTIgMTAyLjQ3MiAxNDkuOTM2IDEwMi42MTggMTUwLjA1M0MxMDIuNzY0IDE1MC4xNjggMTAyLjg4NyAxNTAuMzIyIDEwMi45ODkgMTUwLjUxNEMxMDMuMDkzIDE1MC43MDUgMTAzLjE3MiAxNTAuOTM4IDEwMy4yMjcgMTUxLjIxNEMxMDMuMjgyIDE1MS40OSAxMDMuMzA5IDE1MS44MTQgMTAzLjMwOSAxNTIuMTg2Wk0xMDIuNTgzIDE1My4xNzFWMTUyLjA2NUMxMDIuNTgzIDE1MS44MSAxMDIuNTY3IDE1MS41ODYgMTAyLjUzNiAxNTEuMzkzQzEwMi41MDcgMTUxLjE5OCAxMDIuNDY0IDE1MS4wMzEgMTAyLjQwNyAxNTAuODkzQzEwMi4zNDkgMTUwLjc1NSAxMDIuMjc3IDE1MC42NDMgMTAyLjE4OCAxNTAuNTU3QzEwMi4xMDIgMTUwLjQ3MSAxMDIuMDAyIDE1MC40MDkgMTAxLjg4NyAxNTAuMzdDMTAxLjc3NSAxNTAuMzI4IDEwMS42NDkgMTUwLjMwNyAxMDEuNTA4IDE1MC4zMDdDMTAxLjMzNiAxNTAuMzA3IDEwMS4xODQgMTUwLjM0IDEwMS4wNTEgMTUwLjQwNUMxMDAuOTE4IDE1MC40NjggMTAwLjgwNyAxNTAuNTY4IDEwMC43MTUgMTUwLjcwNkMxMDAuNjI3IDE1MC44NDQgMTAwLjU1OSAxNTEuMDI1IDEwMC41MTIgMTUxLjI0OUMxMDAuNDY1IDE1MS40NzMgMTAwLjQ0MiAxNTEuNzQ1IDEwMC40NDIgMTUyLjA2NVYxNTMuMTcxQzEwMC40NDIgMTUzLjQyNiAxMDAuNDU2IDE1My42NTEgMTAwLjQ4NSAxNTMuODQ2QzEwMC41MTYgMTU0LjA0MiAxMDAuNTYyIDE1NC4yMTEgMTAwLjYyMiAxNTQuMzU0QzEwMC42ODIgMTU0LjQ5NSAxMDAuNzU0IDE1NC42MTEgMTAwLjg0IDE1NC43MDJDMTAwLjkyNiAxNTQuNzkzIDEwMS4wMjUgMTU0Ljg2MSAxMDEuMTM3IDE1NC45MDVDMTAxLjI1MiAxNTQuOTQ3IDEwMS4zNzggMTU0Ljk2OCAxMDEuNTE2IDE1NC45NjhDMTAxLjY5MyAxNTQuOTY4IDEwMS44NDggMTU0LjkzNCAxMDEuOTgxIDE1NC44NjZDMTAyLjExNCAxNTQuNzk4IDEwMi4yMjQgMTU0LjY5MyAxMDIuMzEzIDE1NC41NUMxMDIuNDA0IDE1NC40MDQgMTAyLjQ3MiAxNTQuMjE4IDEwMi41MTYgMTUzLjk5MUMxMDIuNTYgMTUzLjc2MiAxMDIuNTgzIDE1My40ODggMTAyLjU4MyAxNTMuMTcxWk0xMDUuMjM1IDE1Mi43NzZMMTA0LjY1NyAxNTIuNjI4TDEwNC45NDMgMTQ5Ljc5NkgxMDcuODZWMTUwLjQ2NEgxMDUuNTU2TDEwNS4zODQgMTUyLjAxQzEwNS40ODggMTUxLjk1MSAxMDUuNjIgMTUxLjg5NSAxMDUuNzc4IDE1MS44NDNDMTA1Ljk0IDE1MS43OSAxMDYuMTI1IDE1MS43NjQgMTA2LjMzMyAxNTEuNzY0QzEwNi41OTYgMTUxLjc2NCAxMDYuODMyIDE1MS44MSAxMDcuMDQgMTUxLjkwMUMxMDcuMjQ5IDE1MS45OSAxMDcuNDI2IDE1Mi4xMTcgMTA3LjU3MSAxNTIuMjg0QzEwNy43MiAxNTIuNDUxIDEwNy44MzMgMTUyLjY1MSAxMDcuOTExIDE1Mi44ODVDMTA3Ljk4OSAxNTMuMTIgMTA4LjAyOCAxNTMuMzgyIDEwOC4wMjggMTUzLjY3MUMxMDguMDI4IDE1My45NDQgMTA3Ljk5MSAxNTQuMTk1IDEwNy45MTUgMTU0LjQyNUMxMDcuODQyIDE1NC42NTQgMTA3LjczMiAxNTQuODU0IDEwNy41ODMgMTU1LjAyNkMxMDcuNDM1IDE1NS4xOTUgMTA3LjI0NyAxNTUuMzI3IDEwNy4wMjEgMTU1LjQyMUMxMDYuNzk3IDE1NS41MTQgMTA2LjUzMiAxNTUuNTYxIDEwNi4yMjggMTU1LjU2MUMxMDUuOTk5IDE1NS41NjEgMTA1Ljc4MSAxNTUuNTMgMTA1LjU3NSAxNTUuNDY4QzEwNS4zNzIgMTU1LjQwMiAxMDUuMTkgMTU1LjMwNSAxMDUuMDI4IDE1NS4xNzVDMTA0Ljg3IDE1NS4wNDIgMTA0LjczOSAxNTQuODc4IDEwNC42MzggMTU0LjY4MkMxMDQuNTM5IDE1NC40ODQgMTA0LjQ3NiAxNTQuMjUzIDEwNC40NSAxNTMuOTg3SDEwNS4xMzhDMTA1LjE2OSAxNTQuMjAxIDEwNS4yMzIgMTU0LjM4IDEwNS4zMjUgMTU0LjUyNkMxMDUuNDE5IDE1NC42NzIgMTA1LjU0MSAxNTQuNzgzIDEwNS42OTMgMTU0Ljg1OEMxMDUuODQ2IDE1NC45MzEgMTA2LjAyNSAxNTQuOTY4IDEwNi4yMjggMTU0Ljk2OEMxMDYuNCAxNTQuOTY4IDEwNi41NTIgMTU0LjkzOCAxMDYuNjg1IDE1NC44NzhDMTA2LjgxOCAxNTQuODE4IDEwNi45MjkgMTU0LjczMiAxMDcuMDIxIDE1NC42MkMxMDcuMTEyIDE1NC41MDggMTA3LjE4MSAxNTQuMzcyIDEwNy4yMjggMTU0LjIxNEMxMDcuMjc3IDE1NC4wNTUgMTA3LjMwMiAxNTMuODc2IDEwNy4zMDIgMTUzLjY3OEMxMDcuMzAyIDE1My40OTkgMTA3LjI3NyAxNTMuMzMyIDEwNy4yMjggMTUzLjE3OEMxMDcuMTc4IDE1My4wMjUgMTA3LjEwNCAxNTIuODkxIDEwNy4wMDUgMTUyLjc3NkMxMDYuOTA5IDE1Mi42NjIgMTA2Ljc5IDE1Mi41NzMgMTA2LjY1IDE1Mi41MUMxMDYuNTA5IDE1Mi40NDUgMTA2LjM0NyAxNTIuNDEzIDEwNi4xNjUgMTUyLjQxM0MxMDUuOTIzIDE1Mi40MTMgMTA1LjczOSAxNTIuNDQ1IDEwNS42MTQgMTUyLjUxQzEwNS40OTIgMTUyLjU3NiAxMDUuMzY2IDE1Mi42NjQgMTA1LjIzNSAxNTIuNzc2Wk0xMTEuOTEyIDE0OS43OTZWMTU1LjQ4M0gxMTEuMTU5VjE0OS43OTZIMTExLjkxMlpNMTE0LjI5NSAxNTIuMzU0VjE1Mi45NzFIMTExLjc0OFYxNTIuMzU0SDExNC4yOTVaTTExNC42ODIgMTQ5Ljc5NlYxNTAuNDEzSDExMS43NDhWMTQ5Ljc5NkgxMTQuNjgyWk0xMTcuMjIyIDE1NS41NjFDMTE2LjkyNyAxNTUuNTYxIDExNi42NiAxNTUuNTEyIDExNi40MjEgMTU1LjQxM0MxMTYuMTg0IDE1NS4zMTEgMTE1Ljk3OSAxNTUuMTY5IDExNS44MDggMTU0Ljk4N0MxMTUuNjM4IDE1NC44MDUgMTE1LjUwOCAxNTQuNTg5IDExNS40MTcgMTU0LjMzOUMxMTUuMzI2IDE1NC4wODkgMTE1LjI4IDE1My44MTUgMTE1LjI4IDE1My41MThWMTUzLjM1NEMxMTUuMjggMTUzLjAxIDExNS4zMzEgMTUyLjcwNSAxMTUuNDMzIDE1Mi40MzZDMTE1LjUzNCAxNTIuMTY1IDExNS42NzIgMTUxLjkzNiAxMTUuODQ3IDE1MS43NDlDMTE2LjAyMSAxNTEuNTYxIDExNi4yMTkgMTUxLjQxOSAxMTYuNDQgMTUxLjMyM0MxMTYuNjYyIDE1MS4yMjcgMTE2Ljg5MSAxNTEuMTc4IDExNy4xMjggMTUxLjE3OEMxMTcuNDMgMTUxLjE3OCAxMTcuNjkgMTUxLjIzMSAxMTcuOTA5IDE1MS4zMzVDMTE4LjEzIDE1MS40MzkgMTE4LjMxMSAxNTEuNTg1IDExOC40NTIgMTUxLjc3MkMxMTguNTkzIDE1MS45NTcgMTE4LjY5NyAxNTIuMTc2IDExOC43NjUgMTUyLjQyOEMxMTguODMyIDE1Mi42NzggMTE4Ljg2NiAxNTIuOTUyIDExOC44NjYgMTUzLjI0OVYxNTMuNTczSDExNS43MVYxNTIuOTgzSDExOC4xNDRWMTUyLjkyOEMxMTguMTMzIDE1Mi43NDEgMTE4LjA5NCAxNTIuNTU5IDExOC4wMjYgMTUyLjM4MkMxMTcuOTYxIDE1Mi4yMDUgMTE3Ljg1NyAxNTIuMDU5IDExNy43MTQgMTUxLjk0NEMxMTcuNTcxIDE1MS44MyAxMTcuMzc1IDE1MS43NzIgMTE3LjEyOCAxNTEuNzcyQzExNi45NjQgMTUxLjc3MiAxMTYuODEzIDE1MS44MDcgMTE2LjY3NSAxNTEuODc4QzExNi41MzcgMTUxLjk0NSAxMTYuNDE4IDE1Mi4wNDcgMTE2LjMxOSAxNTIuMTgyQzExNi4yMiAxNTIuMzE4IDExNi4xNDQgMTUyLjQ4MyAxMTYuMDg5IDE1Mi42NzhDMTE2LjAzNCAxNTIuODc0IDExNi4wMDcgMTUzLjA5OSAxMTYuMDA3IDE1My4zNTRWMTUzLjUxOEMxMTYuMDA3IDE1My43MTkgMTE2LjAzNCAxNTMuOTA4IDExNi4wODkgMTU0LjA4NUMxMTYuMTQ2IDE1NC4yNTkgMTE2LjIyOCAxNTQuNDEzIDExNi4zMzUgMTU0LjU0NkMxMTYuNDQ0IDE1NC42NzggMTE2LjU3NiAxNTQuNzgzIDExNi43MjkgMTU0Ljg1OEMxMTYuODg2IDE1NC45MzQgMTE3LjA2MyAxNTQuOTcxIDExNy4yNjEgMTU0Ljk3MUMxMTcuNTE2IDE1NC45NzEgMTE3LjczMiAxNTQuOTE5IDExNy45MDkgMTU0LjgxNUMxMTguMDg2IDE1NC43MTEgMTE4LjI0MSAxNTQuNTcyIDExOC4zNzQgMTU0LjM5N0wxMTguODExIDE1NC43NDVDMTE4LjcyIDE1NC44ODMgMTE4LjYwNCAxNTUuMDE0IDExOC40NjQgMTU1LjEzOUMxMTguMzIzIDE1NS4yNjQgMTE4LjE1IDE1NS4zNjYgMTE3Ljk0NCAxNTUuNDQ0QzExNy43NDEgMTU1LjUyMiAxMTcuNSAxNTUuNTYxIDExNy4yMjIgMTU1LjU2MVpNMTE5Ljc4OSAxNDkuNDgzSDEyMC41MTVWMTU0LjY2M0wxMjAuNDUzIDE1NS40ODNIMTE5Ljc4OVYxNDkuNDgzWk0xMjMuMzcxIDE1My4zMzVWMTUzLjQxN0MxMjMuMzcxIDE1My43MjQgMTIzLjMzNCAxNTQuMDA5IDEyMy4yNjEgMTU0LjI3MkMxMjMuMTg4IDE1NC41MzMgMTIzLjA4MiAxNTQuNzU5IDEyMi45NDEgMTU0Ljk1MkMxMjIuOCAxNTUuMTQ1IDEyMi42MjggMTU1LjI5NCAxMjIuNDI1IDE1NS40MDFDMTIyLjIyMiAxNTUuNTA4IDEyMS45ODkgMTU1LjU2MSAxMjEuNzI2IDE1NS41NjFDMTIxLjQ1OCAxNTUuNTYxIDEyMS4yMjIgMTU1LjUxNiAxMjEuMDE5IDE1NS40MjVDMTIwLjgxOSAxNTUuMzMxIDEyMC42NDkgMTU1LjE5NyAxMjAuNTExIDE1NS4wMjJDMTIwLjM3MyAxNTQuODQ4IDEyMC4yNjMgMTU0LjYzNyAxMjAuMTc5IDE1NC4zODlDMTIwLjA5OSAxNTQuMTQyIDEyMC4wNDMgMTUzLjg2MyAxMjAuMDExIDE1My41NTNWMTUzLjE5NEMxMjAuMDQzIDE1Mi44ODIgMTIwLjA5OSAxNTIuNjAyIDEyMC4xNzkgMTUyLjM1NEMxMjAuMjYzIDE1Mi4xMDcgMTIwLjM3MyAxNTEuODk2IDEyMC41MTEgMTUxLjcyMUMxMjAuNjQ5IDE1MS41NDQgMTIwLjgxOSAxNTEuNDEgMTIxLjAxOSAxNTEuMzE5QzEyMS4yMiAxNTEuMjI1IDEyMS40NTMgMTUxLjE3OCAxMjEuNzE4IDE1MS4xNzhDMTIxLjk4NCAxNTEuMTc4IDEyMi4yMiAxNTEuMjMxIDEyMi40MjUgMTUxLjMzNUMxMjIuNjMxIDE1MS40MzYgMTIyLjgwMyAxNTEuNTgyIDEyMi45NDEgMTUxLjc3MkMxMjMuMDgyIDE1MS45NjIgMTIzLjE4OCAxNTIuMTkgMTIzLjI2MSAxNTIuNDU2QzEyMy4zMzQgMTUyLjcxOSAxMjMuMzcxIDE1My4wMTIgMTIzLjM3MSAxNTMuMzM1Wk0xMjIuNjQ0IDE1My40MTdWMTUzLjMzNUMxMjIuNjQ0IDE1My4xMjQgMTIyLjYyNSAxNTIuOTI2IDEyMi41ODYgMTUyLjc0MUMxMjIuNTQ2IDE1Mi41NTMgMTIyLjQ4NCAxNTIuMzg5IDEyMi4zOTggMTUyLjI0OUMxMjIuMzEyIDE1Mi4xMDYgMTIyLjE5OSAxNTEuOTk0IDEyMi4wNTggMTUxLjkxM0MxMjEuOTE4IDE1MS44MyAxMjEuNzQ0IDE1MS43ODggMTIxLjUzOSAxNTEuNzg4QzEyMS4zNTYgMTUxLjc4OCAxMjEuMTk4IDE1MS44MTkgMTIxLjA2MiAxNTEuODgyQzEyMC45MjkgMTUxLjk0NCAxMjAuODE2IDE1Mi4wMjkgMTIwLjcyMiAxNTIuMTM1QzEyMC42MjggMTUyLjI0IDEyMC41NTIgMTUyLjM1OSAxMjAuNDkyIDE1Mi40OTVDMTIwLjQzNCAxNTIuNjI4IDEyMC4zOTIgMTUyLjc2NiAxMjAuMzYzIDE1Mi45MDlWMTUzLjg1QzEyMC40MDUgMTU0LjAzMyAxMjAuNDcyIDE1NC4yMDggMTIwLjU2NiAxNTQuMzc4QzEyMC42NjIgMTU0LjU0NCAxMjAuNzkgMTU0LjY4MSAxMjAuOTQ5IDE1NC43ODhDMTIxLjExIDE1NC44OTUgMTIxLjMwOSAxNTQuOTQ4IDEyMS41NDYgMTU0Ljk0OEMxMjEuNzQyIDE1NC45NDggMTIxLjkwOCAxNTQuOTA5IDEyMi4wNDYgMTU0LjgzMUMxMjIuMTg3IDE1NC43NSAxMjIuMyAxNTQuNjM5IDEyMi4zODYgMTU0LjQ5OUMxMjIuNDc1IDE1NC4zNTggMTIyLjU0IDE1NC4xOTUgMTIyLjU4MiAxNTQuMDFDMTIyLjYyMyAxNTMuODI2IDEyMi42NDQgMTUzLjYyOCAxMjIuNjQ0IDE1My40MTdaIiBmaWxsPSJibGFjayIgZmlsbC1vcGFjaXR5PSIwLjU0Ii8+CjwvZz4KPGxpbmUgeDE9IjEyOC45NSIgeTE9IjE0Ny4yMzMiIHgyPSIxMjguOTUiIHkyPSIxNDYuNDExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC41IiBzdHJva2Utd2lkdGg9IjAuNSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDRfNDE4Ml8xMTE5MykiPgo8bGluZSB4MT0iMTQ2LjY1IiB5MT0iMTQ3LjIzMyIgeDI9IjE0Ni42NSIgeTI9IjE0Ni40MTEiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1vcGFjaXR5PSIwLjUiIHN0cm9rZS13aWR0aD0iMC41IiBzdHJva2UtbGluZWNhcD0ic3F1YXJlIi8+CjxwYXRoIGQ9Ik0xMzguNzA5IDE1Mi4xODZWMTUzLjA1M0MxMzguNzA5IDE1My41MiAxMzguNjY3IDE1My45MTMgMTM4LjU4NCAxNTQuMjMzQzEzOC41MDEgMTU0LjU1MyAxMzguMzgxIDE1NC44MTEgMTM4LjIyNSAxNTUuMDA3QzEzOC4wNjggMTU1LjIwMiAxMzcuODggMTU1LjM0NCAxMzcuNjU4IDE1NS40MzJDMTM3LjQzOSAxNTUuNTE4IDEzNy4xOTIgMTU1LjU2MSAxMzYuOTE2IDE1NS41NjFDMTM2LjY5NyAxNTUuNTYxIDEzNi40OTUgMTU1LjUzNCAxMzYuMzExIDE1NS40NzlDMTM2LjEyNiAxNTUuNDI1IDEzNS45NTkgMTU1LjMzNyAxMzUuODExIDE1NS4yMThDMTM1LjY2NSAxNTUuMDk1IDEzNS41NCAxNTQuOTM2IDEzNS40MzYgMTU0Ljc0MUMxMzUuMzMxIDE1NC41NDYgMTM1LjI1MiAxNTQuMzA5IDEzNS4xOTcgMTU0LjAzQzEzNS4xNDMgMTUzLjc1MSAxMzUuMTE1IDE1My40MjYgMTM1LjExNSAxNTMuMDUzVjE1Mi4xODZDMTM1LjExNSAxNTEuNzIgMTM1LjE1NyAxNTEuMzMgMTM1LjI0IDE1MS4wMTRDMTM1LjMyNiAxNTAuNjk5IDEzNS40NDcgMTUwLjQ0NyAxMzUuNjA0IDE1MC4yNTdDMTM1Ljc2IDE1MC4wNjQgMTM1Ljk0NyAxNDkuOTI2IDEzNi4xNjYgMTQ5Ljg0M0MxMzYuMzg3IDE0OS43NTkgMTM2LjYzNSAxNDkuNzE4IDEzNi45MDggMTQ5LjcxOEMxMzcuMTMgMTQ5LjcxOCAxMzcuMzMzIDE0OS43NDUgMTM3LjUxOCAxNDkuOEMxMzcuNzA1IDE0OS44NTIgMTM3Ljg3MiAxNDkuOTM2IDEzOC4wMTggMTUwLjA1M0MxMzguMTYzIDE1MC4xNjggMTM4LjI4NyAxNTAuMzIyIDEzOC4zODkgMTUwLjUxNEMxMzguNDkzIDE1MC43MDUgMTM4LjU3MiAxNTAuOTM4IDEzOC42MjcgMTUxLjIxNEMxMzguNjgyIDE1MS40OSAxMzguNzA5IDE1MS44MTQgMTM4LjcwOSAxNTIuMTg2Wk0xMzcuOTgyIDE1My4xNzFWMTUyLjA2NUMxMzcuOTgyIDE1MS44MSAxMzcuOTY3IDE1MS41ODYgMTM3LjkzNiAxNTEuMzkzQzEzNy45MDcgMTUxLjE5OCAxMzcuODY0IDE1MS4wMzEgMTM3LjgwNyAxNTAuODkzQzEzNy43NDkgMTUwLjc1NSAxMzcuNjc2IDE1MC42NDMgMTM3LjU4OCAxNTAuNTU3QzEzNy41MDIgMTUwLjQ3MSAxMzcuNDAyIDE1MC40MDkgMTM3LjI4NyAxNTAuMzdDMTM3LjE3NSAxNTAuMzI4IDEzNy4wNDkgMTUwLjMwNyAxMzYuOTA4IDE1MC4zMDdDMTM2LjczNiAxNTAuMzA3IDEzNi41ODQgMTUwLjM0IDEzNi40NTEgMTUwLjQwNUMxMzYuMzE4IDE1MC40NjggMTM2LjIwNiAxNTAuNTY4IDEzNi4xMTUgMTUwLjcwNkMxMzYuMDI3IDE1MC44NDQgMTM1Ljk1OSAxNTEuMDI1IDEzNS45MTIgMTUxLjI0OUMxMzUuODY1IDE1MS40NzMgMTM1Ljg0MiAxNTEuNzQ1IDEzNS44NDIgMTUyLjA2NVYxNTMuMTcxQzEzNS44NDIgMTUzLjQyNiAxMzUuODU2IDE1My42NTEgMTM1Ljg4NSAxNTMuODQ2QzEzNS45MTYgMTU0LjA0MiAxMzUuOTYyIDE1NC4yMTEgMTM2LjAyMiAxNTQuMzU0QzEzNi4wODEgMTU0LjQ5NSAxMzYuMTU0IDE1NC42MTEgMTM2LjI0IDE1NC43MDJDMTM2LjMyNiAxNTQuNzkzIDEzNi40MjUgMTU0Ljg2MSAxMzYuNTM3IDE1NC45MDVDMTM2LjY1MiAxNTQuOTQ3IDEzNi43NzggMTU0Ljk2OCAxMzYuOTE2IDE1NC45NjhDMTM3LjA5MyAxNTQuOTY4IDEzNy4yNDggMTU0LjkzNCAxMzcuMzgxIDE1NC44NjZDMTM3LjUxNCAxNTQuNzk4IDEzNy42MjQgMTU0LjY5MyAxMzcuNzEzIDE1NC41NUMxMzcuODA0IDE1NC40MDQgMTM3Ljg3MiAxNTQuMjE4IDEzNy45MTYgMTUzLjk5MUMxMzcuOTYgMTUzLjc2MiAxMzcuOTgyIDE1My40ODggMTM3Ljk4MiAxNTMuMTcxWk0xNDMuMzk3IDE0OS43OTZWMTUwLjIwMkwxNDEuMDQyIDE1NS40ODNIMTQwLjI4TDE0Mi42MzEgMTUwLjM4OUgxMzkuNTUzVjE0OS43OTZIMTQzLjM5N1pNMTQ3LjMxMiAxNDkuNzk2VjE1NS40ODNIMTQ2LjU1OFYxNDkuNzk2SDE0Ny4zMTJaTTE0OS42OTUgMTUyLjM1NFYxNTIuOTcxSDE0Ny4xNDhWMTUyLjM1NEgxNDkuNjk1Wk0xNTAuMDgyIDE0OS43OTZWMTUwLjQxM0gxNDcuMTQ4VjE0OS43OTZIMTUwLjA4MlpNMTUyLjYyMiAxNTUuNTYxQzE1Mi4zMjcgMTU1LjU2MSAxNTIuMDYgMTU1LjUxMiAxNTEuODIxIDE1NS40MTNDMTUxLjU4NCAxNTUuMzExIDE1MS4zNzkgMTU1LjE2OSAxNTEuMjA3IDE1NC45ODdDMTUxLjAzOCAxNTQuODA1IDE1MC45MDggMTU0LjU4OSAxNTAuODE3IDE1NC4zMzlDMTUwLjcyNiAxNTQuMDg5IDE1MC42OCAxNTMuODE1IDE1MC42OCAxNTMuNTE4VjE1My4zNTRDMTUwLjY4IDE1My4wMSAxNTAuNzMxIDE1Mi43MDUgMTUwLjgzMiAxNTIuNDM2QzE1MC45MzQgMTUyLjE2NSAxNTEuMDcyIDE1MS45MzYgMTUxLjI0NyAxNTEuNzQ5QzE1MS40MjEgMTUxLjU2MSAxNTEuNjE5IDE1MS40MTkgMTUxLjg0IDE1MS4zMjNDMTUyLjA2MiAxNTEuMjI3IDE1Mi4yOTEgMTUxLjE3OCAxNTIuNTI4IDE1MS4xNzhDMTUyLjgzIDE1MS4xNzggMTUzLjA5IDE1MS4yMzEgMTUzLjMwOSAxNTEuMzM1QzE1My41MyAxNTEuNDM5IDE1My43MTEgMTUxLjU4NSAxNTMuODUyIDE1MS43NzJDMTUzLjk5MyAxNTEuOTU3IDE1NC4wOTcgMTUyLjE3NiAxNTQuMTY1IDE1Mi40MjhDMTU0LjIzMiAxNTIuNjc4IDE1NC4yNjYgMTUyLjk1MiAxNTQuMjY2IDE1My4yNDlWMTUzLjU3M0gxNTEuMTFWMTUyLjk4M0gxNTMuNTQzVjE1Mi45MjhDMTUzLjUzMyAxNTIuNzQxIDE1My40OTQgMTUyLjU1OSAxNTMuNDI2IDE1Mi4zODJDMTUzLjM2MSAxNTIuMjA1IDE1My4yNTcgMTUyLjA1OSAxNTMuMTE0IDE1MS45NDRDMTUyLjk3MSAxNTEuODMgMTUyLjc3NSAxNTEuNzcyIDE1Mi41MjggMTUxLjc3MkMxNTIuMzY0IDE1MS43NzIgMTUyLjIxMyAxNTEuODA3IDE1Mi4wNzUgMTUxLjg3OEMxNTEuOTM3IDE1MS45NDUgMTUxLjgxOCAxNTIuMDQ3IDE1MS43MTkgMTUyLjE4MkMxNTEuNjIgMTUyLjMxOCAxNTEuNTQzIDE1Mi40ODMgMTUxLjQ4OSAxNTIuNjc4QzE1MS40MzQgMTUyLjg3NCAxNTEuNDA3IDE1My4wOTkgMTUxLjQwNyAxNTMuMzU0VjE1My41MThDMTUxLjQwNyAxNTMuNzE5IDE1MS40MzQgMTUzLjkwOCAxNTEuNDg5IDE1NC4wODVDMTUxLjU0NiAxNTQuMjU5IDE1MS42MjggMTU0LjQxMyAxNTEuNzM1IDE1NC41NDZDMTUxLjg0NCAxNTQuNjc4IDE1MS45NzYgMTU0Ljc4MyAxNTIuMTI5IDE1NC44NThDMTUyLjI4NiAxNTQuOTM0IDE1Mi40NjMgMTU0Ljk3MSAxNTIuNjYxIDE1NC45NzFDMTUyLjkxNiAxNTQuOTcxIDE1My4xMzIgMTU0LjkxOSAxNTMuMzA5IDE1NC44MTVDMTUzLjQ4NiAxNTQuNzExIDE1My42NDEgMTU0LjU3MiAxNTMuNzc0IDE1NC4zOTdMMTU0LjIxMSAxNTQuNzQ1QzE1NC4xMiAxNTQuODgzIDE1NC4wMDQgMTU1LjAxNCAxNTMuODY0IDE1NS4xMzlDMTUzLjcyMyAxNTUuMjY0IDE1My41NSAxNTUuMzY2IDE1My4zNDQgMTU1LjQ0NEMxNTMuMTQxIDE1NS41MjIgMTUyLjkgMTU1LjU2MSAxNTIuNjIyIDE1NS41NjFaTTE1NS4xODkgMTQ5LjQ4M0gxNTUuOTE1VjE1NC42NjNMMTU1Ljg1MyAxNTUuNDgzSDE1NS4xODlWMTQ5LjQ4M1pNMTU4Ljc3MSAxNTMuMzM1VjE1My40MTdDMTU4Ljc3MSAxNTMuNzI0IDE1OC43MzQgMTU0LjAwOSAxNTguNjYxIDE1NC4yNzJDMTU4LjU4OCAxNTQuNTMzIDE1OC40ODIgMTU0Ljc1OSAxNTguMzQxIDE1NC45NTJDMTU4LjIgMTU1LjE0NSAxNTguMDI4IDE1NS4yOTQgMTU3LjgyNSAxNTUuNDAxQzE1Ny42MjIgMTU1LjUwOCAxNTcuMzg5IDE1NS41NjEgMTU3LjEyNiAxNTUuNTYxQzE1Ni44NTggMTU1LjU2MSAxNTYuNjIyIDE1NS41MTYgMTU2LjQxOSAxNTUuNDI1QzE1Ni4yMTggMTU1LjMzMSAxNTYuMDQ5IDE1NS4xOTcgMTU1LjkxMSAxNTUuMDIyQzE1NS43NzMgMTU0Ljg0OCAxNTUuNjYzIDE1NC42MzcgMTU1LjU3OSAxNTQuMzg5QzE1NS40OTggMTU0LjE0MiAxNTUuNDQyIDE1My44NjMgMTU1LjQxMSAxNTMuNTUzVjE1My4xOTRDMTU1LjQ0MiAxNTIuODgyIDE1NS40OTggMTUyLjYwMiAxNTUuNTc5IDE1Mi4zNTRDMTU1LjY2MyAxNTIuMTA3IDE1NS43NzMgMTUxLjg5NiAxNTUuOTExIDE1MS43MjFDMTU2LjA0OSAxNTEuNTQ0IDE1Ni4yMTggMTUxLjQxIDE1Ni40MTkgMTUxLjMxOUMxNTYuNjIgMTUxLjIyNSAxNTYuODUzIDE1MS4xNzggMTU3LjExOCAxNTEuMTc4QzE1Ny4zODQgMTUxLjE3OCAxNTcuNjIgMTUxLjIzMSAxNTcuODI1IDE1MS4zMzVDMTU4LjAzMSAxNTEuNDM2IDE1OC4yMDMgMTUxLjU4MiAxNTguMzQxIDE1MS43NzJDMTU4LjQ4MiAxNTEuOTYyIDE1OC41ODggMTUyLjE5IDE1OC42NjEgMTUyLjQ1NkMxNTguNzM0IDE1Mi43MTkgMTU4Ljc3MSAxNTMuMDEyIDE1OC43NzEgMTUzLjMzNVpNMTU4LjA0NCAxNTMuNDE3VjE1My4zMzVDMTU4LjA0NCAxNTMuMTI0IDE1OC4wMjQgMTUyLjkyNiAxNTcuOTg1IDE1Mi43NDFDMTU3Ljk0NiAxNTIuNTUzIDE1Ny44ODQgMTUyLjM4OSAxNTcuNzk4IDE1Mi4yNDlDMTU3LjcxMiAxNTIuMTA2IDE1Ny41OTkgMTUxLjk5NCAxNTcuNDU4IDE1MS45MTNDMTU3LjMxNyAxNTEuODMgMTU3LjE0NCAxNTEuNzg4IDE1Ni45MzkgMTUxLjc4OEMxNTYuNzU2IDE1MS43ODggMTU2LjU5NyAxNTEuODE5IDE1Ni40NjIgMTUxLjg4MkMxNTYuMzI5IDE1MS45NDQgMTU2LjIxNiAxNTIuMDI5IDE1Ni4xMjIgMTUyLjEzNUMxNTYuMDI4IDE1Mi4yNCAxNTUuOTUyIDE1Mi4zNTkgMTU1Ljg5MiAxNTIuNDk1QzE1NS44MzQgMTUyLjYyOCAxNTUuNzkxIDE1Mi43NjYgMTU1Ljc2MyAxNTIuOTA5VjE1My44NUMxNTUuODA0IDE1NC4wMzMgMTU1Ljg3MiAxNTQuMjA4IDE1NS45NjYgMTU0LjM3OEMxNTYuMDYyIDE1NC41NDQgMTU2LjE5IDE1NC42ODEgMTU2LjM0OSAxNTQuNzg4QzE1Ni41MSAxNTQuODk1IDE1Ni43MDkgMTU0Ljk0OCAxNTYuOTQ2IDE1NC45NDhDMTU3LjE0MiAxNTQuOTQ4IDE1Ny4zMDggMTU0LjkwOSAxNTcuNDQ2IDE1NC44MzFDMTU3LjU4NyAxNTQuNzUgMTU3LjcgMTU0LjYzOSAxNTcuNzg2IDE1NC40OTlDMTU3Ljg3NSAxNTQuMzU4IDE1Ny45NCAxNTQuMTk1IDE1Ny45ODIgMTU0LjAxQzE1OC4wMjMgMTUzLjgyNiAxNTguMDQ0IDE1My42MjggMTU4LjA0NCAxNTMuNDE3WiIgZmlsbD0iYmxhY2siIGZpbGwtb3BhY2l0eT0iMC41NCIvPgo8L2c+CjxsaW5lIHgxPSIxNjQuMzUiIHkxPSIxNDcuMjMzIiB4Mj0iMTY0LjM1IiB5Mj0iMTQ2LjQxMSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLW9wYWNpdHk9IjAuNSIgc3Ryb2tlLXdpZHRoPSIwLjUiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXA1XzQxODJfMTExOTMpIj4KPGxpbmUgeDE9IjE4Mi4wNSIgeTE9IjE0Ny4yMzMiIHgyPSIxODIuMDUiIHkyPSIxNDYuNDExIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utb3BhY2l0eT0iMC41IiBzdHJva2Utd2lkdGg9IjAuNSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8cGF0aCBkPSJNMTc0LjEwOSAxNTIuMTg2VjE1My4wNTNDMTc0LjEwOSAxNTMuNTIgMTc0LjA2NyAxNTMuOTEzIDE3My45ODQgMTU0LjIzM0MxNzMuOTAxIDE1NC41NTMgMTczLjc4MSAxNTQuODExIDE3My42MjUgMTU1LjAwN0MxNzMuNDY5IDE1NS4yMDIgMTczLjI4IDE1NS4zNDQgMTczLjA1OCAxNTUuNDMyQzE3Mi44NCAxNTUuNTE4IDE3Mi41OTIgMTU1LjU2MSAxNzIuMzE2IDE1NS41NjFDMTcyLjA5NyAxNTUuNTYxIDE3MS44OTYgMTU1LjUzNCAxNzEuNzExIDE1NS40NzlDMTcxLjUyNiAxNTUuNDI1IDE3MS4zNTkgMTU1LjMzNyAxNzEuMjExIDE1NS4yMThDMTcxLjA2NSAxNTUuMDk1IDE3MC45NCAxNTQuOTM2IDE3MC44MzYgMTU0Ljc0MUMxNzAuNzMyIDE1NC41NDYgMTcwLjY1MiAxNTQuMzA5IDE3MC41OTcgMTU0LjAzQzE3MC41NDMgMTUzLjc1MSAxNzAuNTE1IDE1My40MjYgMTcwLjUxNSAxNTMuMDUzVjE1Mi4xODZDMTcwLjUxNSAxNTEuNzIgMTcwLjU1NyAxNTEuMzMgMTcwLjY0IDE1MS4wMTRDMTcwLjcyNiAxNTAuNjk5IDE3MC44NDcgMTUwLjQ0NyAxNzEuMDA0IDE1MC4yNTdDMTcxLjE2IDE1MC4wNjQgMTcxLjM0NyAxNDkuOTI2IDE3MS41NjYgMTQ5Ljg0M0MxNzEuNzg4IDE0OS43NTkgMTcyLjAzNSAxNDkuNzE4IDE3Mi4zMDggMTQ5LjcxOEMxNzIuNTMgMTQ5LjcxOCAxNzIuNzMzIDE0OS43NDUgMTcyLjkxOCAxNDkuOEMxNzMuMTA1IDE0OS44NTIgMTczLjI3MiAxNDkuOTM2IDE3My40MTggMTUwLjA1M0MxNzMuNTY0IDE1MC4xNjggMTczLjY4NyAxNTAuMzIyIDE3My43ODkgMTUwLjUxNEMxNzMuODkzIDE1MC43MDUgMTczLjk3MiAxNTAuOTM4IDE3NC4wMjcgMTUxLjIxNEMxNzQuMDgyIDE1MS40OSAxNzQuMTA5IDE1MS44MTQgMTc0LjEwOSAxNTIuMTg2Wk0xNzMuMzgzIDE1My4xNzFWMTUyLjA2NUMxNzMuMzgzIDE1MS44MSAxNzMuMzY3IDE1MS41ODYgMTczLjMzNiAxNTEuMzkzQzE3My4zMDcgMTUxLjE5OCAxNzMuMjY0IDE1MS4wMzEgMTczLjIwNyAxNTAuODkzQzE3My4xNSAxNTAuNzU1IDE3My4wNzcgMTUwLjY0MyAxNzIuOTg4IDE1MC41NTdDMTcyLjkwMiAxNTAuNDcxIDE3Mi44MDIgMTUwLjQwOSAxNzIuNjg3IDE1MC4zN0MxNzIuNTc1IDE1MC4zMjggMTcyLjQ0OSAxNTAuMzA3IDE3Mi4zMDggMTUwLjMwN0MxNzIuMTM2IDE1MC4zMDcgMTcxLjk4NCAxNTAuMzQgMTcxLjg1MSAxNTAuNDA1QzE3MS43MTkgMTUwLjQ2OCAxNzEuNjA3IDE1MC41NjggMTcxLjUxNSAxNTAuNzA2QzE3MS40MjcgMTUwLjg0NCAxNzEuMzU5IDE1MS4wMjUgMTcxLjMxMiAxNTEuMjQ5QzE3MS4yNjUgMTUxLjQ3MyAxNzEuMjQyIDE1MS43NDUgMTcxLjI0MiAxNTIuMDY1VjE1My4xNzFDMTcxLjI0MiAxNTMuNDI2IDE3MS4yNTYgMTUzLjY1MSAxNzEuMjg1IDE1My44NDZDMTcxLjMxNiAxNTQuMDQyIDE3MS4zNjIgMTU0LjIxMSAxNzEuNDIyIDE1NC4zNTRDMTcxLjQ4MiAxNTQuNDk1IDE3MS41NTQgMTU0LjYxMSAxNzEuNjQgMTU0LjcwMkMxNzEuNzI2IDE1NC43OTMgMTcxLjgyNSAxNTQuODYxIDE3MS45MzcgMTU0LjkwNUMxNzIuMDUyIDE1NC45NDcgMTcyLjE3OCAxNTQuOTY4IDE3Mi4zMTYgMTU0Ljk2OEMxNzIuNDkzIDE1NC45NjggMTcyLjY0OCAxNTQuOTM0IDE3Mi43ODEgMTU0Ljg2NkMxNzIuOTE0IDE1NC43OTggMTczLjAyNSAxNTQuNjkzIDE3My4xMTMgMTU0LjU1QzE3My4yMDQgMTU0LjQwNCAxNzMuMjcyIDE1NC4yMTggMTczLjMxNiAxNTMuOTkxQzE3My4zNiAxNTMuNzYyIDE3My4zODMgMTUzLjQ4OCAxNzMuMzgzIDE1My4xNzFaTTE3NS44NCAxNTQuODc4SDE3NS45MTRDMTc2LjMzMSAxNTQuODc4IDE3Ni42NyAxNTQuODE5IDE3Ni45MyAxNTQuNzAyQzE3Ny4xOSAxNTQuNTg1IDE3Ny4zOTEgMTU0LjQyNyAxNzcuNTMyIDE1NC4yMjlDMTc3LjY3MiAxNTQuMDMxIDE3Ny43NjkgMTUzLjgwOSAxNzcuODIxIDE1My41NjFDMTc3Ljg3MyAxNTMuMzExIDE3Ny44OTkgMTUzLjA1NSAxNzcuODk5IDE1Mi43OTJWMTUxLjkyMUMxNzcuODk5IDE1MS42NjMgMTc3Ljg2OSAxNTEuNDM0IDE3Ny44MDkgMTUxLjIzM0MxNzcuNzUyIDE1MS4wMzMgMTc3LjY3MSAxNTAuODY1IDE3Ny41NjcgMTUwLjcyOUMxNzcuNDY1IDE1MC41OTQgMTc3LjM0OSAxNTAuNDkxIDE3Ny4yMTkgMTUwLjQyMUMxNzcuMDg5IDE1MC4zNSAxNzYuOTUxIDE1MC4zMTUgMTc2LjgwNSAxNTAuMzE1QzE3Ni42MzggMTUwLjMxNSAxNzYuNDg5IDE1MC4zNDkgMTc2LjM1NiAxNTAuNDE3QzE3Ni4yMjYgMTUwLjQ4MiAxNzYuMTE1IDE1MC41NzQgMTc2LjAyNCAxNTAuNjk0QzE3NS45MzUgMTUwLjgxNCAxNzUuODY4IDE1MC45NTUgMTc1LjgyMSAxNTEuMTE2QzE3NS43NzQgMTUxLjI3NyAxNzUuNzUgMTUxLjQ1MyAxNzUuNzUgMTUxLjY0M0MxNzUuNzUgMTUxLjgxMyAxNzUuNzcxIDE1MS45NzcgMTc1LjgxMyAxNTIuMTM1QzE3NS44NTUgMTUyLjI5NCAxNzUuOTE4IDE1Mi40MzggMTc2LjAwNCAxNTIuNTY1QzE3Ni4wOSAxNTIuNjkzIDE3Ni4xOTcgMTUyLjc5NCAxNzYuMzI1IDE1Mi44N0MxNzYuNDU1IDE1Mi45NDMgMTc2LjYwNyAxNTIuOTc5IDE3Ni43ODIgMTUyLjk3OUMxNzYuOTQzIDE1Mi45NzkgMTc3LjA5NCAxNTIuOTQ4IDE3Ny4yMzUgMTUyLjg4NUMxNzcuMzc4IDE1Mi44MiAxNzcuNTA0IDE1Mi43MzMgMTc3LjYxNCAxNTIuNjI0QzE3Ny43MjYgMTUyLjUxMiAxNzcuODE0IDE1Mi4zODUgMTc3Ljg3OSAxNTIuMjQ1QzE3Ny45NDcgMTUyLjEwNCAxNzcuOTg2IDE1MS45NTcgMTc3Ljk5NiAxNTEuODAzSDE3OC4zNEMxNzguMzQgMTUyLjAyIDE3OC4yOTcgMTUyLjIzMyAxNzguMjExIDE1Mi40NDRDMTc4LjEyOCAxNTIuNjUyIDE3OC4wMTEgMTUyLjg0MyAxNzcuODYgMTUzLjAxNEMxNzcuNzA5IDE1My4xODYgMTc3LjUzMiAxNTMuMzI0IDE3Ny4zMjkgMTUzLjQyOEMxNzcuMTI1IDE1My41MyAxNzYuOTA0IDE1My41ODEgMTc2LjY2NCAxNTMuNTgxQzE3Ni4zODMgMTUzLjU4MSAxNzYuMTQgMTUzLjUyNiAxNzUuOTM0IDE1My40MTdDMTc1LjcyOCAxNTMuMzA3IDE3NS41NTkgMTUzLjE2MiAxNzUuNDI2IDE1Mi45NzlDMTc1LjI5NiAxNTIuNzk3IDE3NS4xOTggMTUyLjU5NCAxNzUuMTMzIDE1Mi4zN0MxNzUuMDcxIDE1Mi4xNDMgMTc1LjAzOSAxNTEuOTE0IDE3NS4wMzkgMTUxLjY4MkMxNzUuMDM5IDE1MS40MTIgMTc1LjA3NyAxNTEuMTU4IDE3NS4xNTMgMTUwLjkyMUMxNzUuMjI4IDE1MC42ODQgMTc1LjM0IDE1MC40NzUgMTc1LjQ4OSAxNTAuMjk2QzE3NS42MzcgMTUwLjExMyAxNzUuODIxIDE0OS45NzEgMTc2LjAzOSAxNDkuODdDMTc2LjI2MSAxNDkuNzY4IDE3Ni41MTYgMTQ5LjcxOCAxNzYuODA1IDE0OS43MThDMTc3LjEzMSAxNDkuNzE4IDE3Ny40MDggMTQ5Ljc4MyAxNzcuNjM3IDE0OS45MTNDMTc3Ljg2NiAxNTAuMDQzIDE3OC4wNTIgMTUwLjIxOCAxNzguMTk2IDE1MC40MzZDMTc4LjM0MiAxNTAuNjU1IDE3OC40NDggMTUwLjkwMSAxNzguNTE2IDE1MS4xNzVDMTc4LjU4NCAxNTEuNDQ4IDE3OC42MTggMTUxLjcyOSAxNzguNjE4IDE1Mi4wMThWMTUyLjI4QzE3OC42MTggMTUyLjU3NCAxNzguNTk4IDE1Mi44NzQgMTc4LjU1OSAxNTMuMTc4QzE3OC41MjMgMTUzLjQ4MSAxNzguNDUxIDE1My43NyAxNzguMzQ0IDE1NC4wNDZDMTc4LjI0IDE1NC4zMjIgMTc4LjA4OCAxNTQuNTY5IDE3Ny44ODcgMTU0Ljc4OEMxNzcuNjg3IDE1NS4wMDQgMTc3LjQyNSAxNTUuMTc2IDE3Ny4xMDIgMTU1LjMwM0MxNzYuNzgyIDE1NS40MjggMTc2LjM4NiAxNTUuNDkxIDE3NS45MTQgMTU1LjQ5MUgxNzUuODRWMTU0Ljg3OFpNMTgyLjcxMyAxNDkuNzk2VjE1NS40ODNIMTgxLjk1OVYxNDkuNzk2SDE4Mi43MTNaTTE4NS4wOTUgMTUyLjM1NFYxNTIuOTcxSDE4Mi41NDhWMTUyLjM1NEgxODUuMDk1Wk0xODUuNDgyIDE0OS43OTZWMTUwLjQxM0gxODIuNTQ4VjE0OS43OTZIMTg1LjQ4MlpNMTg4LjAyMiAxNTUuNTYxQzE4Ny43MjcgMTU1LjU2MSAxODcuNDYgMTU1LjUxMiAxODcuMjIxIDE1NS40MTNDMTg2Ljk4NCAxNTUuMzExIDE4Ni43OCAxNTUuMTY5IDE4Ni42MDggMTU0Ljk4N0MxODYuNDM4IDE1NC44MDUgMTg2LjMwOCAxNTQuNTg5IDE4Ni4yMTcgMTU0LjMzOUMxODYuMTI2IDE1NC4wODkgMTg2LjA4IDE1My44MTUgMTg2LjA4IDE1My41MThWMTUzLjM1NEMxODYuMDggMTUzLjAxIDE4Ni4xMzEgMTUyLjcwNSAxODYuMjMzIDE1Mi40MzZDMTg2LjMzNCAxNTIuMTY1IDE4Ni40NzIgMTUxLjkzNiAxODYuNjQ3IDE1MS43NDlDMTg2LjgyMSAxNTEuNTYxIDE4Ny4wMTkgMTUxLjQxOSAxODcuMjQgMTUxLjMyM0MxODcuNDYyIDE1MS4yMjcgMTg3LjY5MSAxNTEuMTc4IDE4Ny45MjggMTUxLjE3OEMxODguMjMgMTUxLjE3OCAxODguNDkgMTUxLjIzMSAxODguNzA5IDE1MS4zMzVDMTg4LjkzMSAxNTEuNDM5IDE4OS4xMTIgMTUxLjU4NSAxODkuMjUyIDE1MS43NzJDMTg5LjM5MyAxNTEuOTU3IDE4OS40OTcgMTUyLjE3NiAxODkuNTY1IDE1Mi40MjhDMTg5LjYzMiAxNTIuNjc4IDE4OS42NjYgMTUyLjk1MiAxODkuNjY2IDE1My4yNDlWMTUzLjU3M0gxODYuNTFWMTUyLjk4M0gxODguOTQ0VjE1Mi45MjhDMTg4LjkzMyAxNTIuNzQxIDE4OC44OTQgMTUyLjU1OSAxODguODI2IDE1Mi4zODJDMTg4Ljc2MSAxNTIuMjA1IDE4OC42NTcgMTUyLjA1OSAxODguNTE0IDE1MS45NDRDMTg4LjM3MSAxNTEuODMgMTg4LjE3NSAxNTEuNzcyIDE4Ny45MjggMTUxLjc3MkMxODcuNzY0IDE1MS43NzIgMTg3LjYxMyAxNTEuODA3IDE4Ny40NzUgMTUxLjg3OEMxODcuMzM3IDE1MS45NDUgMTg3LjIxOCAxNTIuMDQ3IDE4Ny4xMTkgMTUyLjE4MkMxODcuMDIgMTUyLjMxOCAxODYuOTQ0IDE1Mi40ODMgMTg2Ljg4OSAxNTIuNjc4QzE4Ni44MzQgMTUyLjg3NCAxODYuODA3IDE1My4wOTkgMTg2LjgwNyAxNTMuMzU0VjE1My41MThDMTg2LjgwNyAxNTMuNzE5IDE4Ni44MzQgMTUzLjkwOCAxODYuODg5IDE1NC4wODVDMTg2Ljk0NiAxNTQuMjU5IDE4Ny4wMjggMTU0LjQxMyAxODcuMTM1IDE1NC41NDZDMTg3LjI0NCAxNTQuNjc4IDE4Ny4zNzYgMTU0Ljc4MyAxODcuNTMgMTU0Ljg1OEMxODcuNjg2IDE1NC45MzQgMTg3Ljg2MyAxNTQuOTcxIDE4OC4wNjEgMTU0Ljk3MUMxODguMzE2IDE1NC45NzEgMTg4LjUzMiAxNTQuOTE5IDE4OC43MDkgMTU0LjgxNUMxODguODg2IDE1NC43MTEgMTg5LjA0MSAxNTQuNTcyIDE4OS4xNzQgMTU0LjM5N0wxODkuNjEyIDE1NC43NDVDMTg5LjUyIDE1NC44ODMgMTg5LjQwNSAxNTUuMDE0IDE4OS4yNjQgMTU1LjEzOUMxODkuMTIzIDE1NS4yNjQgMTg4Ljk1IDE1NS4zNjYgMTg4Ljc0NCAxNTUuNDQ0QzE4OC41NDEgMTU1LjUyMiAxODguMyAxNTUuNTYxIDE4OC4wMjIgMTU1LjU2MVpNMTkwLjU4OSAxNDkuNDgzSDE5MS4zMTVWMTU0LjY2M0wxOTEuMjUzIDE1NS40ODNIMTkwLjU4OVYxNDkuNDgzWk0xOTQuMTcxIDE1My4zMzVWMTUzLjQxN0MxOTQuMTcxIDE1My43MjQgMTk0LjEzNCAxNTQuMDA5IDE5NC4wNjEgMTU0LjI3MkMxOTMuOTg4IDE1NC41MzMgMTkzLjg4MiAxNTQuNzU5IDE5My43NDEgMTU0Ljk1MkMxOTMuNiAxNTUuMTQ1IDE5My40MjkgMTU1LjI5NCAxOTMuMjI1IDE1NS40MDFDMTkzLjAyMiAxNTUuNTA4IDE5Mi43ODkgMTU1LjU2MSAxOTIuNTI2IDE1NS41NjFDMTkyLjI1OCAxNTUuNTYxIDE5Mi4wMjIgMTU1LjUxNiAxOTEuODE5IDE1NS40MjVDMTkxLjYxOSAxNTUuMzMxIDE5MS40NDkgMTU1LjE5NyAxOTEuMzExIDE1NS4wMjJDMTkxLjE3MyAxNTQuODQ4IDE5MS4wNjMgMTU0LjYzNyAxOTAuOTc5IDE1NC4zODlDMTkwLjg5OSAxNTQuMTQyIDE5MC44NDMgMTUzLjg2MyAxOTAuODExIDE1My41NTNWMTUzLjE5NEMxOTAuODQzIDE1Mi44ODIgMTkwLjg5OSAxNTIuNjAyIDE5MC45NzkgMTUyLjM1NEMxOTEuMDYzIDE1Mi4xMDcgMTkxLjE3MyAxNTEuODk2IDE5MS4zMTEgMTUxLjcyMUMxOTEuNDQ5IDE1MS41NDQgMTkxLjYxOSAxNTEuNDEgMTkxLjgxOSAxNTEuMzE5QzE5Mi4wMiAxNTEuMjI1IDE5Mi4yNTMgMTUxLjE3OCAxOTIuNTE4IDE1MS4xNzhDMTkyLjc4NCAxNTEuMTc4IDE5My4wMiAxNTEuMjMxIDE5My4yMjUgMTUxLjMzNUMxOTMuNDMxIDE1MS40MzYgMTkzLjYwMyAxNTEuNTgyIDE5My43NDEgMTUxLjc3MkMxOTMuODgyIDE1MS45NjIgMTkzLjk4OCAxNTIuMTkgMTk0LjA2MSAxNTIuNDU2QzE5NC4xMzQgMTUyLjcxOSAxOTQuMTcxIDE1My4wMTIgMTk0LjE3MSAxNTMuMzM1Wk0xOTMuNDQ0IDE1My40MTdWMTUzLjMzNUMxOTMuNDQ0IDE1My4xMjQgMTkzLjQyNSAxNTIuOTI2IDE5My4zODYgMTUyLjc0MUMxOTMuMzQ3IDE1Mi41NTMgMTkzLjI4NCAxNTIuMzg5IDE5My4xOTggMTUyLjI0OUMxOTMuMTEyIDE1Mi4xMDYgMTkyLjk5OSAxNTEuOTk0IDE5Mi44NTggMTUxLjkxM0MxOTIuNzE4IDE1MS44MyAxOTIuNTQ0IDE1MS43ODggMTkyLjMzOSAxNTEuNzg4QzE5Mi4xNTYgMTUxLjc4OCAxOTEuOTk4IDE1MS44MTkgMTkxLjg2MiAxNTEuODgyQzE5MS43MjkgMTUxLjk0NCAxOTEuNjE2IDE1Mi4wMjkgMTkxLjUyMiAxNTIuMTM1QzE5MS40MjkgMTUyLjI0IDE5MS4zNTIgMTUyLjM1OSAxOTEuMjkyIDE1Mi40OTVDMTkxLjIzNSAxNTIuNjI4IDE5MS4xOTIgMTUyLjc2NiAxOTEuMTYzIDE1Mi45MDlWMTUzLjg1QzE5MS4yMDUgMTU0LjAzMyAxOTEuMjcyIDE1NC4yMDggMTkxLjM2NiAxNTQuMzc4QzE5MS40NjIgMTU0LjU0NCAxOTEuNTkgMTU0LjY4MSAxOTEuNzQ5IDE1NC43ODhDMTkxLjkxIDE1NC44OTUgMTkyLjExIDE1NC45NDggMTkyLjM0NyAxNTQuOTQ4QzE5Mi41NDIgMTU0Ljk0OCAxOTIuNzA4IDE1NC45MDkgMTkyLjg0NyAxNTQuODMxQzE5Mi45ODcgMTU0Ljc1IDE5My4xIDE1NC42MzkgMTkzLjE4NiAxNTQuNDk5QzE5My4yNzUgMTU0LjM1OCAxOTMuMzQgMTU0LjE5NSAxOTMuMzgyIDE1NC4wMUMxOTMuNDIzIDE1My44MjYgMTkzLjQ0NCAxNTMuNjI4IDE5My40NDQgMTUzLjQxN1oiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuNTQiLz4KPC9nPgo8Y2lyY2xlIGN4PSI0MSIgY3k9IjczLjE2MTEiIHI9IjMiIGZpbGw9IiMyMTk2RjMiLz4KPGNpcmNsZSBjeD0iNTkiIGN5PSI1MyIgcj0iMyIgZmlsbD0iIzIxOTZGMyIvPgo8Y2lyY2xlIGN4PSI3NyIgY3k9IjgxLjE2MTEiIHI9IjMiIGZpbGw9IiM0Q0FGNTAiLz4KPGNpcmNsZSBjeD0iOTUiIGN5PSI4NyIgcj0iMyIgZmlsbD0iIzRDQUY1MCIvPgo8Y2lyY2xlIGN4PSI0MSIgY3k9IjExMy4xNjEiIHI9IjMiIGZpbGw9IiM0Q0FGNTAiLz4KPGNpcmNsZSBjeD0iNTkiIGN5PSI5MyIgcj0iMyIgZmlsbD0iIzRDQUY1MCIvPgo8Y2lyY2xlIGN4PSIxMTIiIGN5PSI5MC4xNjExIiByPSIzIiBmaWxsPSIjNENBRjUwIi8+CjxjaXJjbGUgY3g9IjE0OCIgY3k9IjgxLjE2MTEiIHI9IjMiIGZpbGw9IiM0Q0FGNTAiLz4KPGNpcmNsZSBjeD0iMTMwIiBjeT0iMTAzIiByPSIzIiBmaWxsPSIjNENBRjUwIi8+CjxjaXJjbGUgY3g9IjE4MyIgY3k9IjEyMS4xNjEiIHI9IjMiIGZpbGw9IiM0Q0FGNTAiLz4KPGNpcmNsZSBjeD0iMTY2IiBjeT0iMTA5IiByPSIzIiBmaWxsPSIjNENBRjUwIi8+CjxjaXJjbGUgY3g9Ijc3IiBjeT0iMzciIHI9IjMiIGZpbGw9IiMyMTk2RjMiLz4KPGNpcmNsZSBjeD0iOTUiIGN5PSIzOSIgcj0iMyIgZmlsbD0iIzIxOTZGMyIvPgo8Y2lyY2xlIGN4PSIxMTIiIGN5PSIxOS4xNjExIiByPSIzIiBmaWxsPSIjMjE5NkYzIi8+CjxjaXJjbGUgY3g9IjE0OCIgY3k9IjM3IiByPSIzIiBmaWxsPSIjMjE5NkYzIi8+CjxjaXJjbGUgY3g9IjEzMCIgY3k9IjQ0IiByPSIzIiBmaWxsPSIjMjE5NkYzIi8+CjxjaXJjbGUgY3g9IjE4MyIgY3k9IjIzIiByPSIzIiBmaWxsPSIjMjE5NkYzIi8+CjxjaXJjbGUgY3g9IjE2NiIgY3k9IjQ0IiByPSIzIiBmaWxsPSIjMjE5NkYzIi8+CjxjaXJjbGUgY3g9Ijc3IiBjeT0iNzIiIHI9IjMiIGZpbGw9IiNGRkMxMDciLz4KPGNpcmNsZSBjeD0iOTUiIGN5PSI1NSIgcj0iMyIgZmlsbD0iI0ZGQzEwNyIvPgo8Y2lyY2xlIGN4PSIxMTIiIGN5PSI2Ni4xNjExIiByPSIzIiBmaWxsPSIjRkZDMTA3Ii8+CjxjaXJjbGUgY3g9IjE0OCIgY3k9IjUxLjE2MTEiIHI9IjMiIGZpbGw9IiNGRkMxMDciLz4KPGNpcmNsZSBjeD0iMTMwIiBjeT0iNzIiIHI9IjMiIGZpbGw9IiNGRkMxMDciLz4KPGNpcmNsZSBjeD0iMTgzIiBjeT0iODEiIHI9IjMiIGZpbGw9IiNGRkMxMDciLz4KPGNpcmNsZSBjeD0iMTY2IiBjeT0iNTkiIHI9IjMiIGZpbGw9IiNGRkMxMDciLz4KPGNpcmNsZSBjeD0iMjgiIGN5PSI4OSIgcj0iMyIgZmlsbD0iI0ZGQzEwNyIvPgo8Y2lyY2xlIGN4PSI0MSIgY3k9Ijk3IiByPSIzIiBmaWxsPSIjRkZDMTA3Ii8+CjxjaXJjbGUgY3g9IjU5IiBjeT0iNjguNTc4MSIgcj0iMyIgZmlsbD0iI0ZGQzEwNyIvPgo8Y2lyY2xlIGN4PSIyOCIgY3k9IjExOC4xNjEiIHI9IjMiIGZpbGw9IiMyMTk2RjMiLz4KPGNpcmNsZSBjeD0iMjgiIGN5PSIxMjkuNDg5IiByPSIzIiBmaWxsPSIjNENBRjUwIi8+CjwvZz4KPGRlZnM+CjxjbGlwUGF0aCBpZD0iY2xpcDBfNDE4Ml8xMTE5MyI+CjxyZWN0IHdpZHRoPSIyMDAiIGhlaWdodD0iMTYwIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8Y2xpcFBhdGggaWQ9ImNsaXAxXzQxODJfMTExOTMiPgo8cmVjdCB3aWR0aD0iMzUuNCIgaGVpZ2h0PSIxMCIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIzIDE0Ni4xNjEpIi8+CjwvY2xpcFBhdGg+CjxjbGlwUGF0aCBpZD0iY2xpcDJfNDE4Ml8xMTE5MyI+CjxyZWN0IHdpZHRoPSIzNS40IiBoZWlnaHQ9IjEwLjMyMiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDU4LjM5OTkgMTQ2LjE2MSkiLz4KPC9jbGlwUGF0aD4KPGNsaXBQYXRoIGlkPSJjbGlwM180MTgyXzExMTkzIj4KPHJlY3Qgd2lkdGg9IjM1LjQiIGhlaWdodD0iMTAuMzIyIiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTMuOCAxNDYuMTYxKSIvPgo8L2NsaXBQYXRoPgo8Y2xpcFBhdGggaWQ9ImNsaXA0XzQxODJfMTExOTMiPgo8cmVjdCB3aWR0aD0iMzUuNCIgaGVpZ2h0PSIxMC4zMjIiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjkuMiAxNDYuMTYxKSIvPgo8L2NsaXBQYXRoPgo8Y2xpcFBhdGggaWQ9ImNsaXA1XzQxODJfMTExOTMiPgo8cmVjdCB3aWR0aD0iMzUuNCIgaGVpZ2h0PSIxMC4zMjIiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjQuNiAxNDYuMTYxKSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=", + "description": "Displays changes to time-series data over time—for example, temperature or humidity readings.", + "descriptor": { + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "resources": [], + "templateHtml": "\n", + "templateCss": "", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n chartType: 'point',\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings('point'),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", + "settingsSchema": "{}", + "dataKeySettingsSchema": "{}", + "latestDataKeySettingsSchema": "{}", + "settingsDirective": "tb-time-series-chart-widget-settings", + "dataKeySettingsDirective": "tb-time-series-chart-key-settings", + "latestDataKeySettingsDirective": "", + "hasBasicMode": true, + "basicModeDirective": "tb-time-series-chart-basic-config", + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"dd MMM yyyy HH:mm:ss\",\"lastUpdateAgo\":false,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Point chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + }, + "tags": [ + "chart", + "time series", + "time-series", + "point", + "point chart" + ] +} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/time_series_chart.json b/application/src/main/data/json/system/widget_types/time_series_chart.json index 7d2fff170f..688cce76fb 100644 --- a/application/src/main/data/json/system/widget_types/time_series_chart.json +++ b/application/src/main/data/json/system/widget_types/time_series_chart.json @@ -10,12 +10,12 @@ "sizeY": 5, "resources": [], "templateHtml": "\n", - "templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n", + "templateCss": "", "controllerScript": "self.onInit = function() {\n self.ctx.$scope.timeSeriesChartWidget.onInit();\n};\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onDataUpdated();\n}\n\nself.onLatestDataUpdated = function() {\n self.ctx.$scope.timeSeriesChartWidget.onLatestDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '80%',\n embedTitlePanel: true,\n hasAdditionalLatestDataKeys: true,\n dataKeySettingsFunction: TbTimeSeriesChart.dataKeySettings(),\n defaultDataKeysFunction: function() {\n return [{ name: 'temperature', label: 'Temperature', type: 'timeseries', units: '°C', decimals: 0 }];\n }\n };\n}\n", "settingsSchema": "{}", "dataKeySettingsSchema": "{}", "latestDataKeySettingsSchema": "{}", - "settingsDirective": "", + "settingsDirective": "tb-time-series-chart-widget-settings", "dataKeySettingsDirective": "tb-time-series-chart-key-settings", "latestDataKeySettingsDirective": "", "hasBasicMode": true, @@ -29,6 +29,8 @@ "line", "line chart", "bar", - "bar chart" + "bar chart", + "point", + "point chart" ] } \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/timeseries_bar_chart.json b/application/src/main/data/json/system/widget_types/timeseries_bar_chart.json index ff9c7971f0..ebb0d2680d 100644 --- a/application/src/main/data/json/system/widget_types/timeseries_bar_chart.json +++ b/application/src/main/data/json/system/widget_types/timeseries_bar_chart.json @@ -1,8 +1,8 @@ { "fqn": "charts.timeseries_bars_flot", "name": "Timeseries Bar Chart", - "deprecated": false, - "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAMAAAB+IdObAAABOFBMVEUAAAA3oPR3d3d6enp8fHyBgYGDg4OGhoaNjY2RkZGSkpKTk5OUlJSVlZWWlpaXl5eYmJiZmZmampqcnJydnZ2enp6goKChoaGioqKjo6OkpKSlpaWmpqanp6eoqKipqamqqqqrq6usrKytra2urq6wsLCxsbGysrK0tLS1tbW2tra3t7e4uLi5ubm6urq8vLy9vb2+vr6/v7/AwMDBwcHDw8PExMTHx8fIyMjJycnLy8vNzc3Ozs7Pz8/S0tLT09PU1NTV1dXW1tbX19fZ2dna2trb29vc3Nzd3d3e3t7f39/h4eHi4uLj4+Pk5OTl5eXm5ubn5+fo6Ojq6urr6+vs7Ozt7e3u7u7v7+/w8PDx8fH09PT19fX29vb39/f4+Pj5+fn6+vr7+/v8/Pz9/f3+/v7/xx////8KXFhiAAAAAWJLR0RnW9PpswAAAvtJREFUeNrt3GtXElEUBuDpZlAqylVHCyMwyi4SpkaWAl4qk8wwUhJlmOn9//+gLzbKbc6AAm5991p82WvPOedZZw6zYM3aGupCQ4tYkZDSsKDrocNVvz8jHQKYY1ZiT/6OAJllRPSpsnzIqIG9SjYmHpKfAzI4CIuHjJeBtyHfZwCatiI1/m+BYV2Dw35NniOEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQUp/6Wx+DgbRbxOAhEb/fXJ98akiH1AIAHtSWlqRDSvdDGcOHnYR0SPV7zVsaQyHeO0jTJapEV5C9bUz9fIjsvHRIefhRxHqpjxzA3ftajXOudHGJOtHV+1rV04/wHenDc2QQkFbLJISQwUDaP90IIYQQQgghpAvIxRO9gFxG4lZ9XBFIx6sihJD+QVRjEEIIIYQQcoMgahkhhBDSe0iLX3ydQdSLIKR9ghCJkIYEIYQQIhPS8d+AhPQboppFw9HMxBrs/lqCIbObpgezP67YjnQ8iwagHDzrryUZUgsUz/prCYZY05vn+msJhiwM6XrR7q/V9OJU4xQuEpcxRsezNPbXEn3Yzz9Hulg3IYT0C3LxxI2CNCQIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQlpA7P5a0iF2fy3hkLP+WsIhVbu/lvRby+6vJR1i99eSG6ffu1XHxlRNcfWq3I0iIK4tJK2nXVyV0lOqEmvjGWAtvnCu+jMzkQWMiOlYdRSd3MAH/UnVPWR/ApFfSkcpiOBvRc3XtAeYW1ZUJbZMD5C8azhWLX4xvZVR692Se0huHm9ySogxkhs3lFVewPM4WlFUlUMoJEYUox1+jAFIbLuHrKaQWlMu8TicDp+4gdw7/qS4t2qBohk4UUF2nieBfLyDM/ItgXhBucT113i14QbixW7M+SRNb6EQ0u8kHavyZQxj2/kgNUCsYDRoqXfEF/Mdu4G8D43uOtakh3R9H1DsyKZvOmneDjt+D/0DTzolrPMHmggAAAAASUVORK5CYII=", + "deprecated": true, + "image": "tb-image:dGltZXNlcmllc19iYXJfY2hhcnRfc3lzdGVtX3dpZGdldF9pbWFnZS5wbmc=:IlRpbWVzZXJpZXMgQmFyIENoYXJ0IiBzeXN0ZW0gd2lkZ2V0IGltYWdl;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAMAAAB+IdObAAABOFBMVEUAAAA3oPR3d3d6enp8fHyBgYGDg4OGhoaNjY2RkZGSkpKTk5OUlJSVlZWWlpaXl5eYmJiZmZmampqcnJydnZ2enp6goKChoaGioqKjo6OkpKSlpaWmpqanp6eoqKipqamqqqqrq6usrKytra2urq6wsLCxsbGysrK0tLS1tbW2tra3t7e4uLi5ubm6urq8vLy9vb2+vr6/v7/AwMDBwcHDw8PExMTHx8fIyMjJycnLy8vNzc3Ozs7Pz8/S0tLT09PU1NTV1dXW1tbX19fZ2dna2trb29vc3Nzd3d3e3t7f39/h4eHi4uLj4+Pk5OTl5eXm5ubn5+fo6Ojq6urr6+vs7Ozt7e3u7u7v7+/w8PDx8fH09PT19fX29vb39/f4+Pj5+fn6+vr7+/v8/Pz9/f3+/v7/xx////8KXFhiAAAAAWJLR0RnW9PpswAAAvtJREFUeNrt3GtXElEUBuDpZlAqylVHCyMwyi4SpkaWAl4qk8wwUhJlmOn9//+gLzbKbc6AAm5991p82WvPOedZZw6zYM3aGupCQ4tYkZDSsKDrocNVvz8jHQKYY1ZiT/6OAJllRPSpsnzIqIG9SjYmHpKfAzI4CIuHjJeBtyHfZwCatiI1/m+BYV2Dw35NniOEEEIIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQUp/6Wx+DgbRbxOAhEb/fXJ98akiH1AIAHtSWlqRDSvdDGcOHnYR0SPV7zVsaQyHeO0jTJapEV5C9bUz9fIjsvHRIefhRxHqpjxzA3ftajXOudHGJOtHV+1rV04/wHenDc2QQkFbLJISQwUDaP90IIYQQQgghpAvIxRO9gFxG4lZ9XBFIx6sihJD+QVRjEEIIIYQQcoMgahkhhBDSe0iLX3ydQdSLIKR9ghCJkIYEIYQQIhPS8d+AhPQboppFw9HMxBrs/lqCIbObpgezP67YjnQ8iwagHDzrryUZUgsUz/prCYZY05vn+msJhiwM6XrR7q/V9OJU4xQuEpcxRsezNPbXEn3Yzz9Hulg3IYT0C3LxxI2CNCQIIYQQQgghhBBCCCGEEEIIIYQQQgghhBBCCCGEEEIIIYQQQlpA7P5a0iF2fy3hkLP+WsIhVbu/lvRby+6vJR1i99eSG6ffu1XHxlRNcfWq3I0iIK4tJK2nXVyV0lOqEmvjGWAtvnCu+jMzkQWMiOlYdRSd3MAH/UnVPWR/ApFfSkcpiOBvRc3XtAeYW1ZUJbZMD5C8azhWLX4xvZVR692Se0huHm9ySogxkhs3lFVewPM4WlFUlUMoJEYUox1+jAFIbLuHrKaQWlMu8TicDp+4gdw7/qS4t2qBohk4UUF2nieBfLyDM/ItgXhBucT113i14QbixW7M+SRNb6EQ0u8kHavyZQxj2/kgNUCsYDRoqXfEF/Mdu4G8D43uOtakh3R9H1DsyKZvOmneDjt+D/0DTzolrPMHmggAAAAASUVORK5CYII=", "description": "Displays changes to time-series data over time—for example, daily water consumption for the last month.", "descriptor": { "type": "timeseries", @@ -21,6 +21,5 @@ "basicModeDirective": "tb-flot-basic-config", "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000},\"aggregation\":{\"limit\":200,\"type\":\"AVG\"}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"stack\":true,\"fontSize\":10,\"fontColor\":\"#545454\",\"showTooltip\":true,\"tooltipIndividual\":false,\"tooltipCumulative\":false,\"hideZeros\":false,\"grid\":{\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1,\"color\":\"#545454\",\"backgroundColor\":null,\"tickColor\":\"#DDDDDD\"},\"xaxis\":{\"title\":null,\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"min\":null,\"max\":null,\"title\":null,\"showLabels\":true,\"color\":\"#545454\",\"tickSize\":null,\"tickDecimals\":0,\"ticksFormatter\":\"\"},\"defaultBarWidth\":600,\"barAlignment\":\"left\",\"comparisonEnabled\":false,\"xaxisSecond\":{\"axisPosition\":\"top\",\"title\":null,\"showLabels\":true},\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"bottom\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"customLegendEnabled\":false},\"title\":\"Timeseries Bar Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{},\"configMode\":\"basic\",\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\"}" }, - "externalId": null, "tags": null } \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/timeseries_line_chart.json b/application/src/main/data/json/system/widget_types/timeseries_line_chart.json index e83b213ae0..87f7330657 100644 --- a/application/src/main/data/json/system/widget_types/timeseries_line_chart.json +++ b/application/src/main/data/json/system/widget_types/timeseries_line_chart.json @@ -1,8 +1,8 @@ { "fqn": "charts.basic_timeseries", "name": "Timeseries Line Chart", - "deprecated": false, - "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAIAAADGnbT+AAAABmJLR0QA/wD/AP+gvaeTAAAXk0lEQVR42u2deXwb1bXH+Y+lfY/utK98WkogZSk7LcujBF4pAT6lLaWvlBZeCrTw4AGFvrbQkPYRwlIWfyCr7WA7XrN4wzZx7DjxIu+2vEteZHmTJdmOd8faR9K838y1FUWWZVmaGQM585mPPmNZR/fOvV+de+455849iw/7OOuss/gojpaWFhI8cwQFVlQqVbp4JCUlzc3NaTSaveKhVqsJLBKMHCx2eDyeuLg4r9ebl5c3NjZGGosEpQEL+qm+vh4XKSkp0F4ZGRkWi4XAIsFowdqzZw/HcbiAurLb7Z2dndnZ2QQWCUYFVnd3d1FRkU914XV2djY5OZnAIsGowIqPj/cNfOXl5bDiY2Nj+/v7/anC0UIHHeEdwZUQxkRY8WS8k6AENhb5sUiQwCJBAosancAisEiQwCJBAosancAisEiQwCJBAosancAisEiQwCJBAosancAisEiQwCJBAosECSwCiwQJLBIksEiQwCKwSJDAIkECiwQJLAKLBAksEiSwSJDAIrBIkMAiQQKLBAksAosECSwSJLBIkMAisEiQwCJBAuuzK5jV7SKwCCyJBd+pd35nz7x6xE1gEViSCb7XIFCF84lCO4FFYEkj+IFaoOqSuPn1cfMX75nvnvQQWARWtIKvFg6CqnWx8+83Op8ptuP6hWN2AovAikowsd3FqIppcDaOuIv7uUtj5y+JnR+a9RBYBFaEgvs6BKow9r1V6wBV7PzdYRve3KJyEFgEViSC6VrXxSJVL+YN+6jC+ZHOBQV2Wfz8uNW75lXVTni2q50/zbLWGN0E1qdAEP4q0AOqXq92ZKi6/cHC+auPBKX1dp1zTarq9vBweWytctyaamETVZy3pFim7V6FwMKOX2yPQmwup9Pp0tLScnJy2J5NBFaII7uHA1Xora3Vwgi4FKz9ncIQeXWC5aTTq1hVwU1OD/fMUfv3PjzF0w1JlieL7HcftOIaF0qA5Xa7ExISfG/t2LED79SJB4EV4ijs4+BWQD+9orIzjJaChfMnWUJfxrY45a6qYc6T1O56pMB2ady8j6cfpllfOOZI1bgaxMpgSnGVSNtbRf2ygzU9Pf3mm29iYybs+wUthe2Z8KbRaMSOmATWcgd6iFH1t3K7j6GgYCWIs8Ub91nsnPRVbWpu0Yx7Pmh03i/iy851cfP3HLS+WuU40s8trc/OJsHTtj52ric8H1vkYLlcLrPZDC21fft2QIZ9VvGmyWTKzc0lsIIeRwc4phX+Umb377OgYOH80X5BSaRpXBJW1eXhXy53XL131scTBtxNH9t2qJ2Vw1zQavjOxw8LPrb7DlkdbjnBws6XBoMBF9hVdXx8fOfOnbjGRpilpaUE1tKjwuD+brzQkc+V2AM6bDmwdoju+NvTrW6PZFVl4UicN6dY4YyFF63O5A7Nk+8Eed9PnIHstmqHjGBhp8Jdu3YdOHAAJjx2kysuLsbWvbt378ZemP5U0X6FOJLKdevjTqJLHs0cAUZhnukV3awjPyjRS1KNA6qudXtOrgMZhYPhV8P/fLe4/5LYk5jMJpTp5N2vEANi0GvSWL4DHqDL9wpKAhoiqCZYTmPhfLvOAcG7D1g93miranV578wQLKo/lTpClBj6hOAWlTAg3rDPsqKbjfxYMgo2jbqvFOdTyFloWL63lutIjFPf3yeIlw5xUVZ1c4XA6J0ZllqzOxqw6s3un4omPywzL4G1JoLNY27mE3rssB390bh6sHD+X6UAxC9ybNFUtXLYjfELqRPZ3dyKJYYGC6/HBrlrE4X7golGYCkniN9xy5h7W42DUYXYXwiqVuxmmMyYuOF7GszuyKoKz+dNycI3/KPSEU6J4VR1T4sTpGI60jnhIbBkF+ydEpxDd2Sccg49nG+rN4XbW8udfy1ziGrPFllVnz0qWEX3HrL6+I4eLJxPiRk+Pz5gtXEEljyCjKd/3zd9KhKyzwJT3ee5jhKsMgN3+V5B5cCrudqq5uo4CF7xoQUe//BLDKeqNSb3hnSLtIkYBJZwwAeNJKr/2G/1j6yBpzRtWDytqpuZ1nm+xL6qqo7Me68RjaF36hyrLTGcqsJiWy+6fIsHuGhatc7sZhH3Mxos/bQHmcQYAnw8wZLFuPDGkYHQtlQ0YBUtJgAitBdmVWHq/bZAyJJArkQEJYZZ1deqhWH6+iTLqCWSePngrOepIjtrRrTemQWW082PznvbTgjxsnsOWf2DIU8ese9rdzGeJOytEBGVVyocYd5jkhhtBPTHBzn5wIJu/kWugO9v8m2nnG1el3CGbNVZh/f1GgdTeBjoETxFVFResMb82JcbLLTFpM0LIwnauEDPJXe4/ppvQOfhZ/TLXBuGuasSTuWQsBNx/scL7QltrgCrXG6wPupdSAA8seiZDHGPUKvMK4vpW8QlhikIcK9LspyWi9H7DF/1Rb7jXn74XX6+GaD5V5Xz8Cka1/WiCO4IjYkoaqO46E1esKC64VeUFawdTc6NB63wPbK8qNAnxiAYT3ekWx4rtMe3LhtckxssnL/OE3TDPxcTAJe7R/QcS1tAnylT1Q/bhGxYhNih13nj+7zq7NPO2gtnau/jRxJ4x3DZEHfXolWK1KDM7lPaVF6wgD8zC+QDyzzvZfFgdkIbIyKLjJEHc23wJm/KHEHqyHv1Tnj/cns4mKVhWk4KgHWgU2gcuMfmHN4Q9xgjLlG8KcW6XMKCHFV9tkQYqV/K+YivPI9XncOP7uPHMviex/m6i/wh6z16TVLu83/Oyo1tnAr4BhnBwsDkM2KqZUuy/psY3IBNUAJoTGvAx3KC7QbdaMfLjSOh0ldYOGVXk3O5e2wdcyPlC5oYzg4lfwPwPjyRqZ4v+4oAkOGN0zy009pDha+XHb7fWv4lH2Heys+fbLzTpHmta6BGbXbICxZSY9m46wtiSA4WZlXQ2Ehqy+91rZXiWU5wuvnXaPHxtqcbR5ZlImkxARBuyaX3iDeZ++OPxxwKK9cW45i1ej3qX1DwcIF+wXJH5hYML2anAvfnik826yrN2q3zDbd7Kz/ng8xd9dWZpgd554gsYCEHbUO60Chv1DpYKAqRV8nB+suCF9u+hiNaUMHOgXphBBEberLlUfYjDnqyDHQopKX3+HcxsIjE4hqToqO22mw/qb4LNR+tvPmKuBOYLxtPemDVsA7FeVfKBOwKf5Em01xP37GRjs2W+ptx457K83mPTRawEtuE3yKcubBpYOWwZEUk0UoIFrwm+N1cFj+tbXt/qvm3zaaZTwxYHH7E6Jjp5l+5q74iXjykHrEF/fwuMUv4tjSLurk1aKQ5q4dT2BycaP096uysubh12PSQOMO4cnFFBiY90LKhS2wbNuj6imUZCi0u741ifgimXWzAZn/uOq6XECwsXX8k5bC5/FqmGGz117cZBj4JYOl7s1AfV/WFYL1zoJGr/gb+nG26v8k8v/TzcB1BJ6Fx3i/p890azHm2WmuLyq7wPGO4813U1lP5hc6BBvxZbuBYqg/0FhRE+E4+WcBiE5n7Mq2+Yt6sFZTWbUlTbq80YA2NaisL72VI2WuvstddLfRlzbfRkWsL1gGVxl57JSoz2B3P3tEONnPV38Q7c+q7m0yzS0XeqRca5/bkKV/bPF8SGGlWBqxefQGvOhdjmb43x/cmVnj/6bjDf066NmDBRckyTDK0tq6BamPnWzp9Yb3RCS8A3sQqvGjB4qZ4/YselWAtWisuMHR9AJug2TQ517hR/Kl90b9RlAerSfV3QX3WXeNvV2mGNK5qYaKOIbLZOLVcAiBSo3B/Bb0c81/DalbSM6IZbGcDt0n7RvQlSg9WjKpn84Hddccecldd4JspQJc01Lx8R0IH1L7LEylYXk7wy9UKv35Pxbl5BY+W6Uf8TE7HifbnxOLOMWtfWxOwwLdDJdx1r/7jgH+1G/odtZcJP4b6H2DOFZgAKJqhD+TYEKi4TpzrvF3nUGwCK04Dxx11l6N6Uy0Ph3aRKAuWtZs3x/KdD3lqvuHvQLPVXTve+hSGqgVvh+qc+iN31jan8B7rqsGaOsqrr2Hf01V+z8bExv85GsT+MHa+Iyrzs1EuNJnCYGFahKIxpVrGqh1ko6St/rrWYXNAAuCV8XPChEv0LyAAFV6JLoyz0d+j2mydb9ggKNTG25rMFkkaJwqwnKP8eLYQSKq/xB+mE6XfUpc+NNi9t214yFdM56AaHh1nxaJLrfqrfM9j/HSpGLZf6bD1CjEEJth45XBfFkt3LB4I/sPS9+ZiQBRsmsaNWapGxcDCbEgs95wAO8//bB0esdbdgLo5ar/bbujz/9cT2WZfOLxkgFsRqT5dJgZcfNWM6qqBnlS12RnxPeJHKM42LmobHpaqcVYP1vghvvdpvvHy0+JHdd/muzeN6JM2JHRihlzUH7xdDqmaYvLjmotuOyWovlaIRrnGg5fHTfN9/8tXfl74ZM3XhE96nQiZregzxIwGg6/AlurydoNeGbAmWzYJNrvqgdAfazGesNbfJMznay9tH+o9FaEr07EEQKxADCEO7YJpAbhcdHl/zjc49OvSQzjMlrtHUcef7an6knawRcLGWT1Yi34/vvrL/hFv/PcRMWEoRJejQvEtwoTxgfQ218Brp1QdAlL4Kug/X3rGgjl1ofiBc6dqf8Y7T+DtjnHPxaJhuzR7ZIn+GGb9h9l+d79KbrDQK6gnHIN5qrKVTTHjFHN0uWq+BZPZVyIidI8V2kMitRfuJdZoMInwJzyTtap3HbVXLLxZu97QtT2c4YyVqNMf8YrRwD7dIWkbZ/Vg9T7LG2NEmE4zwrHgjoVUkXobukIbDy4GyEDP5Me89kHeFxCA5ht4hR/P4tXXLbzTvpG3dPhmhYgrC4vpjjvCM6VnzKofiVPF8/t0+2UFC64EwVXd8XKYgvA7zKl/LHL/TaYqIIiEk4pgrddsmsbkmvksBPO/7kaMg75IEQRhTQ707LPXfo99APAZunYEdZv5n4WqfE/Vl/F5fLnkjSON8Q59hRmN/0NXQlQI4Qt8Elm2M45FA8s5xpt28k03nja8Qp+NpfvPCptH3cwLHILdwEcIqbRj7S+yqSIs6xXnO5GBhTmggEjV11tM4+ELQgMJMTUhuHZB10BtUEFM1jDD5aoWpkSYUYpIcctU1QVHlBhUOZshC1lMVJcbkedV68Rp4G/CbxalwTrcx7Ek8SpjWBVij/WBHzXwi+bqeN1TfP13+OH3eE9gdiVSGCCFVS6rbQJD105R4SNstwndKS1YsJph3+DLMQatlkjEeRDtEdn6yjFVeoCZD/3HNAqbaSIYF15VuV59nqXh1gW8qr4OvEB8ANNsLJ5v+GGY4+YagIWnXLBJsv+zN0NXCKlIF4u6ZzK89bcAC4+lY0NtuYGLoAkQvXJXf401ZatxVEKwYOiIxs1lDNnVjqHgcqL1CYEA1fmoJPNKQMuyia1Y4Q09faURVLWrv2qm6efsSwAovrPVaFycBj6JNy2qi4CvTDMbCcDC4zfR5bemWle15u5BMbcaidJhgsXyLf2fRLXaJtAOtTlr1jGzt8PQJQlYMJXY9FMcoSJ2gLngixGneP8K/6RX9S9syjLd/J9w00TZzd39lbNNP1nAq/ILY20vjHS8wlCDjSWfLyZasJAzjwdaosuxNmFVFcJiI5b0jaUNK5abVNbDHDwrPvYpdBMgXG9puIUNEJGpgYATowzTgj4zJVJ3JdetenzRg3DeZMt/aQY7JOxmuNamm355akavOrdXny+r9zhasFjWx10HLBEs5nw4P9xHVW9MnQgz1L9iEzSZT0ITMA8Qpk7RtB0whftHiAQMVEsSYDFrXp1o/QNST2WawAJWIAtw4buSO94VFVhY9MOS+LBqKoIKIe0TyZ9IAfVfXrf0QMY+m0WuVl0t3wQucTgQfr4TrY8HtV7Dabvxtv9mSVefkJzVsCMEQwqUGBVYsJDE0Kk14gptEp+vj0TQEIX+PFv4DMK00jYBxgIk0bI5fASJXJohLXQecr07DD2fLrCUEYwcLCyWxWI3TO4OdkXuHCrsc7E1wVg6F7RE+AwF62rvbLVR+iaA15tlHHDV/xZgcq3YdkjcgyCmWp9tPtYArD+XCjE7hHGirBDWH7OHeQb1u94nrvN5/iOjTE0AB8+s+j5mchk73w5TsKevjDmflnouCKyowOqbEfLNcX4cXjJaiAohSQGpCtB8Sx/OVCj6XZHWnFLRI18TwJMkprucwzyoLBISUtDFvNv+IBJY0oD1e1HNPF1sl6RCbHnkH47Ygy5LRFqzAm3X13uQTfEQuoaLMoQgclRYPA4TTAJLSrCwipKlGBwblCbGhJVhLGMEz87zlZUvZuj+IDnax2yuIkNhqI2loyDKdlyVFtwjarY4a4SkDOSonAl8KArWw3mrjtmtWCEkLDCLbSFM5F0IE2GhgZJth6DvnPpeMdn1vKAjHRIBWH7BcstQCawIwTomPo4BTnCVgZOwQogAsg1eak1CnbLFVdS3pCyEiZRsu0WTS1xr2vo7/+QTZASwgONy8WACK3Kw2DSN7XQlbYVeLrezdG9ucRU126d0TdquWvU+CwMLQethE3vzRNsfhVTgpp+dOXwoB5Zo96yw6DviJwqzRyE+J9ryt6VJ/PzW1Qoi/46ZXEgGR74U0ogRHkY8JHQUj8A6DSybzZaZmZmamqrVavGnRqNhexdiM7AAsGC2v9fglKlC/xCfVsDOD/xSv9eq7bBOiz3FAHkHWGnNFv+cUXxEC1Z+fr5er8cWmDExMezP0dHRoBoL1k9kD+cMp0Jwr98gLt3ckGHxL2UN2w7LE3wmF1JNfMMigbWKoRBbNSUmJvLibqvYpAk7geGdALAiq0r4FXpdfL7qrtOTcNa87fp1GTC5TJqtZxofEoDFNlmdmJjgxV3m7HY7tpXLzs5WGCysN0dOX8Mnr+2Qcxf0yQsEViiwsJXc/v37MRoygJhphT3lkpOTFQaLsUW99RkBS6VSbdu2LV08oLTKy8uxjS828O3v7/enCkdkW+PReaadp+1XeNoiZI6DGltqvCugsUjwTPRjEVgkSGCRIIFFggQWgUWCBBYJElgkSGBR25EggUWCBBYJEljUdiRIYJEggUWCBBY1OgkSWCRIYJEggUWNToIEFgkSWCRIYFGjkyCBRYIEFgkSWNToJEhgkSCBRYIEFjU6CRJYJEhgkSCBRY1OggQWCRJYJEhgUaOTIIFFggQWCRJY1OgkSGCRIIFFggQWNToJElgkSGCRIIFFjU5gEVgkqBRYOp0uLS0tJycH+1MQWCQoGVg7duzAZmB14kFgkaA0YEFLYXsmXBiNxry8PAKLBKUBy+VyxcXF4cJkMuXm5hJYJCjZULhz5068YiPM0tJSAosEJQOruLgYGxfu3r0be2EG7FdIBx3hHkE9CxgQQzgdeGUPKvHTWKLS90PHGXIQWHR8AsCqqKiA+YVXxepXVlaGEvEqd0HYqri3t7egoMD3Z3V19ZEjR+Qr0Wq1ZmZmpqamYp7k8/WkpKR4PB6ZSrTZbIcOHYL3G3eKP5ubm9G2WVlZISwfJcCanJxEK+ACNz81NaUAVdPT04mJibjA68zMjKxlDQ4O4gcTExPD/iwqKqqvr5e1RLgJ+/r6gJGv0MOHD2/ZsiUg4CHhgZ/KwMAASty+fbvdbt+zZw9+P1VVVQGecKXB6urqYg6I48eP41oBsNDEmJyirPj4ePma2/9Ai7MLdPbBgwfx+0YHyFqixWJJSkpijkOghvuV9U7n5uZaW1uzs7P9+TYYDGsJlkajYUMSXrVarQLd7HA4kpOToUjw6nQ6lQRr69atKL2jo0PW0RChs4SEhImJCWgRXOAe5QYLAZXCwkKoRvZnd3d3gBt8DcAaHh5mQR5UBT8vBboZ4fCSkhJcHD16lJkFioHFLkZGRvx/3JJbdfv378doyNQV9BYsns2bN/t6XfIDGEFB4mLXrl14haKSz6Q7a1UNAVsHowNeca2MxkLgEl2LV1wrCVZDQwN6GlYI2JKpLGjibdu2pYsH7Ff2pqwaS6/XoyVBM9gFTy+99BKGAplmY/8Pl7O7ukBGoYYAAAAASUVORK5CYII=", + "deprecated": true, + "image": "tb-image:Z2F0ZXdheV9nZW5lcmFsX2NoYXJ0X3N0YXRpc3RpY3Nfc3lzdGVtX3dpZGdldF9pbWFnZS5wbmc=:IkdhdGV3YXkgZ2VuZXJhbCBjaGFydCBzdGF0aXN0aWNzIiBzeXN0ZW0gd2lkZ2V0IGltYWdl;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAIAAADGnbT+AAAABmJLR0QA/wD/AP+gvaeTAAAXk0lEQVR42u2deXwb1bXH+Y+lfY/utK98WkogZSk7LcujBF4pAT6lLaWvlBZeCrTw4AGFvrbQkPYRwlIWfyCr7WA7XrN4wzZx7DjxIu+2vEteZHmTJdmOd8faR9K838y1FUWWZVmaGQM585mPPmNZR/fOvV+de+455849iw/7OOuss/gojpaWFhI8cwQFVlQqVbp4JCUlzc3NaTSaveKhVqsJLBKMHCx2eDyeuLg4r9ebl5c3NjZGGosEpQEL+qm+vh4XKSkp0F4ZGRkWi4XAIsFowdqzZw/HcbiAurLb7Z2dndnZ2QQWCUYFVnd3d1FRkU914XV2djY5OZnAIsGowIqPj/cNfOXl5bDiY2Nj+/v7/anC0UIHHeEdwZUQxkRY8WS8k6AENhb5sUiQwCJBAosancAisEiQwCJBAosancAisEiQwCJBAosancAisEiQwCJBAosancAisEiQwCJBAosECSwCiwQJLBIksEiQwCKwSJDAIkECiwQJLAKLBAksEiSwSJDAIrBIkMAiQQKLBAksAosECSwSJLBIkMAisEiQwCJBAuuzK5jV7SKwCCyJBd+pd35nz7x6xE1gEViSCb7XIFCF84lCO4FFYEkj+IFaoOqSuPn1cfMX75nvnvQQWARWtIKvFg6CqnWx8+83Op8ptuP6hWN2AovAikowsd3FqIppcDaOuIv7uUtj5y+JnR+a9RBYBFaEgvs6BKow9r1V6wBV7PzdYRve3KJyEFgEViSC6VrXxSJVL+YN+6jC+ZHOBQV2Wfz8uNW75lXVTni2q50/zbLWGN0E1qdAEP4q0AOqXq92ZKi6/cHC+auPBKX1dp1zTarq9vBweWytctyaamETVZy3pFim7V6FwMKOX2yPQmwup9Pp0tLScnJy2J5NBFaII7uHA1Xora3Vwgi4FKz9ncIQeXWC5aTTq1hVwU1OD/fMUfv3PjzF0w1JlieL7HcftOIaF0qA5Xa7ExISfG/t2LED79SJB4EV4ijs4+BWQD+9orIzjJaChfMnWUJfxrY45a6qYc6T1O56pMB2ady8j6cfpllfOOZI1bgaxMpgSnGVSNtbRf2ygzU9Pf3mm29iYybs+wUthe2Z8KbRaMSOmATWcgd6iFH1t3K7j6GgYCWIs8Ub91nsnPRVbWpu0Yx7Pmh03i/iy851cfP3HLS+WuU40s8trc/OJsHTtj52ric8H1vkYLlcLrPZDC21fft2QIZ9VvGmyWTKzc0lsIIeRwc4phX+Umb377OgYOH80X5BSaRpXBJW1eXhXy53XL131scTBtxNH9t2qJ2Vw1zQavjOxw8LPrb7DlkdbjnBws6XBoMBF9hVdXx8fOfOnbjGRpilpaUE1tKjwuD+brzQkc+V2AM6bDmwdoju+NvTrW6PZFVl4UicN6dY4YyFF63O5A7Nk+8Eed9PnIHstmqHjGBhp8Jdu3YdOHAAJjx2kysuLsbWvbt378ZemP5U0X6FOJLKdevjTqJLHs0cAUZhnukV3awjPyjRS1KNA6qudXtOrgMZhYPhV8P/fLe4/5LYk5jMJpTp5N2vEANi0GvSWL4DHqDL9wpKAhoiqCZYTmPhfLvOAcG7D1g93miranV578wQLKo/lTpClBj6hOAWlTAg3rDPsqKbjfxYMgo2jbqvFOdTyFloWL63lutIjFPf3yeIlw5xUVZ1c4XA6J0ZllqzOxqw6s3un4omPywzL4G1JoLNY27mE3rssB390bh6sHD+X6UAxC9ybNFUtXLYjfELqRPZ3dyKJYYGC6/HBrlrE4X7golGYCkniN9xy5h7W42DUYXYXwiqVuxmmMyYuOF7GszuyKoKz+dNycI3/KPSEU6J4VR1T4sTpGI60jnhIbBkF+ydEpxDd2Sccg49nG+rN4XbW8udfy1ziGrPFllVnz0qWEX3HrL6+I4eLJxPiRk+Pz5gtXEEljyCjKd/3zd9KhKyzwJT3ee5jhKsMgN3+V5B5cCrudqq5uo4CF7xoQUe//BLDKeqNSb3hnSLtIkYBJZwwAeNJKr/2G/1j6yBpzRtWDytqpuZ1nm+xL6qqo7Me68RjaF36hyrLTGcqsJiWy+6fIsHuGhatc7sZhH3Mxos/bQHmcQYAnw8wZLFuPDGkYHQtlQ0YBUtJgAitBdmVWHq/bZAyJJArkQEJYZZ1deqhWH6+iTLqCWSePngrOepIjtrRrTemQWW082PznvbTgjxsnsOWf2DIU8ese9rdzGeJOytEBGVVyocYd5jkhhtBPTHBzn5wIJu/kWugO9v8m2nnG1el3CGbNVZh/f1GgdTeBjoETxFVFResMb82JcbLLTFpM0LIwnauEDPJXe4/ppvQOfhZ/TLXBuGuasSTuWQsBNx/scL7QltrgCrXG6wPupdSAA8seiZDHGPUKvMK4vpW8QlhikIcK9LspyWi9H7DF/1Rb7jXn74XX6+GaD5V5Xz8Cka1/WiCO4IjYkoaqO46E1esKC64VeUFawdTc6NB63wPbK8qNAnxiAYT3ekWx4rtMe3LhtckxssnL/OE3TDPxcTAJe7R/QcS1tAnylT1Q/bhGxYhNih13nj+7zq7NPO2gtnau/jRxJ4x3DZEHfXolWK1KDM7lPaVF6wgD8zC+QDyzzvZfFgdkIbIyKLjJEHc23wJm/KHEHqyHv1Tnj/cns4mKVhWk4KgHWgU2gcuMfmHN4Q9xgjLlG8KcW6XMKCHFV9tkQYqV/K+YivPI9XncOP7uPHMviex/m6i/wh6z16TVLu83/Oyo1tnAr4BhnBwsDkM2KqZUuy/psY3IBNUAJoTGvAx3KC7QbdaMfLjSOh0ldYOGVXk3O5e2wdcyPlC5oYzg4lfwPwPjyRqZ4v+4oAkOGN0zy009pDha+XHb7fWv4lH2Heys+fbLzTpHmta6BGbXbICxZSY9m46wtiSA4WZlXQ2Ehqy+91rZXiWU5wuvnXaPHxtqcbR5ZlImkxARBuyaX3iDeZ++OPxxwKK9cW45i1ej3qX1DwcIF+wXJH5hYML2anAvfnik826yrN2q3zDbd7Kz/ng8xd9dWZpgd554gsYCEHbUO60Chv1DpYKAqRV8nB+suCF9u+hiNaUMHOgXphBBEberLlUfYjDnqyDHQopKX3+HcxsIjE4hqToqO22mw/qb4LNR+tvPmKuBOYLxtPemDVsA7FeVfKBOwKf5Em01xP37GRjs2W+ptx457K83mPTRawEtuE3yKcubBpYOWwZEUk0UoIFrwm+N1cFj+tbXt/qvm3zaaZTwxYHH7E6Jjp5l+5q74iXjykHrEF/fwuMUv4tjSLurk1aKQ5q4dT2BycaP096uysubh12PSQOMO4cnFFBiY90LKhS2wbNuj6imUZCi0u741ifgimXWzAZn/uOq6XECwsXX8k5bC5/FqmGGz117cZBj4JYOl7s1AfV/WFYL1zoJGr/gb+nG26v8k8v/TzcB1BJ6Fx3i/p890azHm2WmuLyq7wPGO4813U1lP5hc6BBvxZbuBYqg/0FhRE+E4+WcBiE5n7Mq2+Yt6sFZTWbUlTbq80YA2NaisL72VI2WuvstddLfRlzbfRkWsL1gGVxl57JSoz2B3P3tEONnPV38Q7c+q7m0yzS0XeqRca5/bkKV/bPF8SGGlWBqxefQGvOhdjmb43x/cmVnj/6bjDf066NmDBRckyTDK0tq6BamPnWzp9Yb3RCS8A3sQqvGjB4qZ4/YselWAtWisuMHR9AJug2TQ517hR/Kl90b9RlAerSfV3QX3WXeNvV2mGNK5qYaKOIbLZOLVcAiBSo3B/Bb0c81/DalbSM6IZbGcDt0n7RvQlSg9WjKpn84Hddccecldd4JspQJc01Lx8R0IH1L7LEylYXk7wy9UKv35Pxbl5BY+W6Uf8TE7HifbnxOLOMWtfWxOwwLdDJdx1r/7jgH+1G/odtZcJP4b6H2DOFZgAKJqhD+TYEKi4TpzrvF3nUGwCK04Dxx11l6N6Uy0Ph3aRKAuWtZs3x/KdD3lqvuHvQLPVXTve+hSGqgVvh+qc+iN31jan8B7rqsGaOsqrr2Hf01V+z8bExv85GsT+MHa+Iyrzs1EuNJnCYGFahKIxpVrGqh1ko6St/rrWYXNAAuCV8XPChEv0LyAAFV6JLoyz0d+j2mydb9ggKNTG25rMFkkaJwqwnKP8eLYQSKq/xB+mE6XfUpc+NNi9t214yFdM56AaHh1nxaJLrfqrfM9j/HSpGLZf6bD1CjEEJth45XBfFkt3LB4I/sPS9+ZiQBRsmsaNWapGxcDCbEgs95wAO8//bB0esdbdgLo5ar/bbujz/9cT2WZfOLxkgFsRqT5dJgZcfNWM6qqBnlS12RnxPeJHKM42LmobHpaqcVYP1vghvvdpvvHy0+JHdd/muzeN6JM2JHRihlzUH7xdDqmaYvLjmotuOyWovlaIRrnGg5fHTfN9/8tXfl74ZM3XhE96nQiZregzxIwGg6/AlurydoNeGbAmWzYJNrvqgdAfazGesNbfJMznay9tH+o9FaEr07EEQKxADCEO7YJpAbhcdHl/zjc49OvSQzjMlrtHUcef7an6knawRcLGWT1Yi34/vvrL/hFv/PcRMWEoRJejQvEtwoTxgfQ218Brp1QdAlL4Kug/X3rGgjl1ofiBc6dqf8Y7T+DtjnHPxaJhuzR7ZIn+GGb9h9l+d79KbrDQK6gnHIN5qrKVTTHjFHN0uWq+BZPZVyIidI8V2kMitRfuJdZoMInwJzyTtap3HbVXLLxZu97QtT2c4YyVqNMf8YrRwD7dIWkbZ/Vg9T7LG2NEmE4zwrHgjoVUkXobukIbDy4GyEDP5Me89kHeFxCA5ht4hR/P4tXXLbzTvpG3dPhmhYgrC4vpjjvCM6VnzKofiVPF8/t0+2UFC64EwVXd8XKYgvA7zKl/LHL/TaYqIIiEk4pgrddsmsbkmvksBPO/7kaMg75IEQRhTQ707LPXfo99APAZunYEdZv5n4WqfE/Vl/F5fLnkjSON8Q59hRmN/0NXQlQI4Qt8Elm2M45FA8s5xpt28k03nja8Qp+NpfvPCptH3cwLHILdwEcIqbRj7S+yqSIs6xXnO5GBhTmggEjV11tM4+ELQgMJMTUhuHZB10BtUEFM1jDD5aoWpkSYUYpIcctU1QVHlBhUOZshC1lMVJcbkedV68Rp4G/CbxalwTrcx7Ek8SpjWBVij/WBHzXwi+bqeN1TfP13+OH3eE9gdiVSGCCFVS6rbQJD105R4SNstwndKS1YsJph3+DLMQatlkjEeRDtEdn6yjFVeoCZD/3HNAqbaSIYF15VuV59nqXh1gW8qr4OvEB8ANNsLJ5v+GGY4+YagIWnXLBJsv+zN0NXCKlIF4u6ZzK89bcAC4+lY0NtuYGLoAkQvXJXf401ZatxVEKwYOiIxs1lDNnVjqHgcqL1CYEA1fmoJPNKQMuyia1Y4Q09faURVLWrv2qm6efsSwAovrPVaFycBj6JNy2qi4CvTDMbCcDC4zfR5bemWle15u5BMbcaidJhgsXyLf2fRLXaJtAOtTlr1jGzt8PQJQlYMJXY9FMcoSJ2gLngixGneP8K/6RX9S9syjLd/J9w00TZzd39lbNNP1nAq/ILY20vjHS8wlCDjSWfLyZasJAzjwdaosuxNmFVFcJiI5b0jaUNK5abVNbDHDwrPvYpdBMgXG9puIUNEJGpgYATowzTgj4zJVJ3JdetenzRg3DeZMt/aQY7JOxmuNamm355akavOrdXny+r9zhasFjWx10HLBEs5nw4P9xHVW9MnQgz1L9iEzSZT0ITMA8Qpk7RtB0whftHiAQMVEsSYDFrXp1o/QNST2WawAJWIAtw4buSO94VFVhY9MOS+LBqKoIKIe0TyZ9IAfVfXrf0QMY+m0WuVl0t3wQucTgQfr4TrY8HtV7Dabvxtv9mSVefkJzVsCMEQwqUGBVYsJDE0Kk14gptEp+vj0TQEIX+PFv4DMK00jYBxgIk0bI5fASJXJohLXQecr07DD2fLrCUEYwcLCyWxWI3TO4OdkXuHCrsc7E1wVg6F7RE+AwF62rvbLVR+iaA15tlHHDV/xZgcq3YdkjcgyCmWp9tPtYArD+XCjE7hHGirBDWH7OHeQb1u94nrvN5/iOjTE0AB8+s+j5mchk73w5TsKevjDmflnouCKyowOqbEfLNcX4cXjJaiAohSQGpCtB8Sx/OVCj6XZHWnFLRI18TwJMkprucwzyoLBISUtDFvNv+IBJY0oD1e1HNPF1sl6RCbHnkH47Ygy5LRFqzAm3X13uQTfEQuoaLMoQgclRYPA4TTAJLSrCwipKlGBwblCbGhJVhLGMEz87zlZUvZuj+IDnax2yuIkNhqI2loyDKdlyVFtwjarY4a4SkDOSonAl8KArWw3mrjtmtWCEkLDCLbSFM5F0IE2GhgZJth6DvnPpeMdn1vKAjHRIBWH7BcstQCawIwTomPo4BTnCVgZOwQogAsg1eak1CnbLFVdS3pCyEiZRsu0WTS1xr2vo7/+QTZASwgONy8WACK3Kw2DSN7XQlbYVeLrezdG9ucRU126d0TdquWvU+CwMLQethE3vzRNsfhVTgpp+dOXwoB5Zo96yw6DviJwqzRyE+J9ryt6VJ/PzW1Qoi/46ZXEgGR74U0ogRHkY8JHQUj8A6DSybzZaZmZmamqrVavGnRqNhexdiM7AAsGC2v9fglKlC/xCfVsDOD/xSv9eq7bBOiz3FAHkHWGnNFv+cUXxEC1Z+fr5er8cWmDExMezP0dHRoBoL1k9kD+cMp0Jwr98gLt3ckGHxL2UN2w7LE3wmF1JNfMMigbWKoRBbNSUmJvLibqvYpAk7geGdALAiq0r4FXpdfL7qrtOTcNa87fp1GTC5TJqtZxofEoDFNlmdmJjgxV3m7HY7tpXLzs5WGCysN0dOX8Mnr+2Qcxf0yQsEViiwsJXc/v37MRoygJhphT3lkpOTFQaLsUW99RkBS6VSbdu2LV08oLTKy8uxjS828O3v7/enCkdkW+PReaadp+1XeNoiZI6DGltqvCugsUjwTPRjEVgkSGCRIIFFggQWgUWCBBYJElgkSGBR25EggUWCBBYJEljUdiRIYJEggUWCBBY1OgkSWCRIYJEggUWNToIEFgkSWCRIYFGjkyCBRYIEFgkSWNToJEhgkSCBRYIEFjU6CRJYJEhgkSCBRY1OggQWCRJYJEhgUaOTIIFFggQWCRJY1OgkSGCRIIFFggQWNToJElgkSGCRIIFFjU5gEVgkqBRYOp0uLS0tJycH+1MQWCQoGVg7duzAZmB14kFgkaA0YEFLYXsmXBiNxry8PAKLBKUBy+VyxcXF4cJkMuXm5hJYJCjZULhz5068YiPM0tJSAosEJQOruLgYGxfu3r0be2EG7FdIBx3hHkE9CxgQQzgdeGUPKvHTWKLS90PHGXIQWHR8AsCqqKiA+YVXxepXVlaGEvEqd0HYqri3t7egoMD3Z3V19ZEjR+Qr0Wq1ZmZmpqamYp7k8/WkpKR4PB6ZSrTZbIcOHYL3G3eKP5ubm9G2WVlZISwfJcCanJxEK+ACNz81NaUAVdPT04mJibjA68zMjKxlDQ4O4gcTExPD/iwqKqqvr5e1RLgJ+/r6gJGv0MOHD2/ZsiUg4CHhgZ/KwMAASty+fbvdbt+zZw9+P1VVVQGecKXB6urqYg6I48eP41oBsNDEmJyirPj4ePma2/9Ai7MLdPbBgwfx+0YHyFqixWJJSkpijkOghvuV9U7n5uZaW1uzs7P9+TYYDGsJlkajYUMSXrVarQLd7HA4kpOToUjw6nQ6lQRr69atKL2jo0PW0RChs4SEhImJCWgRXOAe5QYLAZXCwkKoRvZnd3d3gBt8DcAaHh5mQR5UBT8vBboZ4fCSkhJcHD16lJkFioHFLkZGRvx/3JJbdfv378doyNQV9BYsns2bN/t6XfIDGEFB4mLXrl14haKSz6Q7a1UNAVsHowNeca2MxkLgEl2LV1wrCVZDQwN6GlYI2JKpLGjibdu2pYsH7Ff2pqwaS6/XoyVBM9gFTy+99BKGAplmY/8Pl7O7ukBGoYYAAAAASUVORK5CYII=", "description": "Displays changes to time-series data over time—for example, temperature or humidity readings.", "descriptor": { "type": "timeseries", @@ -22,6 +22,5 @@ "basicModeDirective": "tb-flot-basic-config", "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"stack\":false,\"fontSize\":10,\"fontColor\":\"#545454\",\"showTooltip\":true,\"tooltipIndividual\":false,\"tooltipCumulative\":false,\"hideZeros\":false,\"grid\":{\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1,\"color\":\"#545454\",\"backgroundColor\":null,\"tickColor\":\"#DDDDDD\"},\"xaxis\":{\"title\":null,\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"min\":null,\"max\":null,\"title\":null,\"showLabels\":true,\"color\":\"#545454\",\"tickSize\":null,\"tickDecimals\":0,\"ticksFormatter\":\"\"},\"shadowSize\":4,\"smoothLines\":false,\"comparisonEnabled\":false,\"xaxisSecond\":{\"axisPosition\":\"top\",\"title\":null,\"showLabels\":true},\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"bottom\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"customLegendEnabled\":false},\"title\":\"Timeseries Line Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\"}" }, - "externalId": null, "tags": null } \ No newline at end of file diff --git a/ui-ngx/src/app/core/api/data-aggregator.ts b/ui-ngx/src/app/core/api/data-aggregator.ts index c11c08ad2b..61cb1f1a85 100644 --- a/ui-ngx/src/app/core/api/data-aggregator.ts +++ b/ui-ngx/src/app/core/api/data-aggregator.ts @@ -14,24 +14,23 @@ /// limitations under the License. /// +import { AggKey, IndexedSubscriptionData, } from '@app/shared/models/telemetry/telemetry.models'; import { - AggKey, - IndexedSubscriptionData, -} from '@app/shared/models/telemetry/telemetry.models'; -import { - AggregationType, calculateAggIntervalWithSubscriptionTimeWindow, + AggregationType, + calculateAggIntervalWithSubscriptionTimeWindow, calculateIntervalComparisonEndTime, calculateIntervalEndTime, calculateIntervalStartEndTime, getCurrentTime, - getTime, IntervalMath, + getTime, + IntervalMath, SubscriptionTimewindow } from '@shared/models/time/time.models'; import { UtilsService } from '@core/services/utils.service'; import { deepClone, isDefinedAndNotNull, isNumber, isNumeric } from '@core/utils'; -import Timeout = NodeJS.Timeout; import { DataEntry, DataSet, IndexedData } from '@shared/models/widget.models'; import BTree from 'sorted-btree'; +import Timeout = NodeJS.Timeout; export declare type onAggregatedData = (data: IndexedData, detectChanges: boolean) => void; @@ -318,7 +317,9 @@ export class DataAggregator { this.startTs += tickTs; this.endTs += tickTs; } - this.updateLastInterval(); + if (this.subsTw.aggregation.type !== AggregationType.NONE) { + this.updateLastInterval(); + } this.data = this.updateData(); this.elapsed = this.elapsed - delta * this.aggregationTimeout; } diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.html index f6af2d1cad..fe642f3d6c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.html @@ -205,6 +205,13 @@ +
    + +
    + {{ 'tooltip.show-date-time-interval' | translate }} +
    +
    +
    {{ 'tooltip.background-color' | translate }}
    +
    + +
    + {{ 'tooltip.show-date-time-interval' | translate }} +
    +
    +
    {{ 'tooltip.background-color' | translate }}
    , protected widgetConfigComponent: WidgetConfigComponent, private $injector: Injector, @@ -86,6 +90,14 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon return this.timeSeriesChartWidgetConfigForm; } + protected setupConfig(widgetConfig: WidgetConfigComponentData) { + const params = widgetConfig.typeParameters as any; + if (isDefinedAndNotNull(params.chartType)) { + this.chartType = params.chartType; + } + super.setupConfig(widgetConfig); + } + protected defaultDataKeys(configData: WidgetConfigComponentData): DataKey[] { return [{ name: 'temperature', label: 'Temperature', type: DataKeyType.timeseries, units: '°C', decimals: 0 }]; } @@ -309,6 +321,4 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon processor.update(Date.now()); return processor.formatted; } - - protected readonly ValueType = ValueType; } diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss index be91ff173c..a44bd255e9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.scss @@ -68,7 +68,13 @@ .tb-label-field, .tb-units-field, .tb-color-field, .tb-decimals-field { display: none; @media #{$mat-gt-sm} { - display: block; + display: flex; + } + } + + .tb-time-series-type-field { + @media #{$mat-md} { + display: none; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts index b2710db346..55613334ff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.ts @@ -322,6 +322,7 @@ export class DataKeyRowComponent implements ControlValueAccessor, OnInit { if (this.showTimeSeriesType) { this.keyRowFormGroup.get('timeSeriesType').patchValue(this.modelValue.settings?.type, {emitEvent: false}); } + this.keyFormControl.patchValue(deepClone(this.modelValue), {emitEvent: false}); this.updateModel(); this.cd.markForCheck(); } diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.html index c13c6de357..4eff6b3881 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
    +
    {{ panelTitle }}
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.scss index 121ed2de77..94785d58f7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-keys-panel.component.scss @@ -15,56 +15,71 @@ */ @import '../../../../../../../../scss/constants'; -.tb-form-table-header-cell { - &.tb-source-header { - width: 108px; - min-width: 108px; - } - &.tb-key-header { - flex: 1; - min-width: 150px; - @media #{$mat-gt-sm} { - flex: 1 1 60%; +.tb-data-keys-panel { + .tb-form-table-header-cell { + &.tb-source-header { + width: 108px; + min-width: 108px; } - } - &.tb-label-header { - flex: 1 1 40%; - min-width: 100px; - } - &.tb-units-header { - width: 80px; - min-width: 80px; - } - &.tb-color-header { - width: 40px; - min-width: 40px; - } - &.tb-decimals-header { - width: 60px; - min-width: 60px; - } - &.tb-time-series-type-header { - width: 60px; - min-width: 60px; - } - &.tb-actions-header { - width: 40px; - min-width: 40px; - @media #{$mat-gt-md} { - width: 120px; - min-width: 120px; + + &.tb-key-header { + flex: 1; + min-width: 150px; + @media #{$mat-gt-sm} { + flex: 1 1 60%; + } } - } - &.tb-label-header, &.tb-units-header, &.tb-color-header, &.tb-decimals-header { - display: none; - @media #{$mat-gt-sm} { - display: block; + + &.tb-label-header { + flex: 1 1 40%; + min-width: 100px; + } + + &.tb-units-header { + width: 80px; + min-width: 80px; + } + + &.tb-color-header { + width: 40px; + min-width: 40px; + } + + &.tb-decimals-header { + width: 60px; + min-width: 60px; + } + + &.tb-time-series-type-header { + width: 60px; + min-width: 60px; + } + + &.tb-actions-header { + width: 40px; + min-width: 40px; + @media #{$mat-gt-md} { + width: 120px; + min-width: 120px; + } + } + + &.tb-label-header, &.tb-units-header, &.tb-color-header, &.tb-decimals-header { + display: none; + @media #{$mat-gt-sm} { + display: block; + } + } + &.tb-time-series-type-header { + @media #{$mat-md} { + display: none; + } } } -} -.tb-form-table-body { - tb-data-key-row { - overflow: hidden; + .tb-form-table-body { + tb-data-key-row { + overflow: hidden; + } } } diff --git a/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html index 37c85e173d..f472325d8d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/data-key-config.component.html @@ -196,6 +196,7 @@ diff --git a/ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts index a4a2e9cc7e..8636db1f77 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/widget-settings.component.ts @@ -49,6 +49,7 @@ import { Dashboard } from '@shared/models/dashboard.models'; import { WidgetService } from '@core/http/widget.service'; import { IAliasController } from '@core/api/widget-api.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models'; +import { DataKeysCallbacks } from '@home/components/widget/config/data-keys.component.models'; @Component({ selector: 'tb-widget-settings', @@ -77,6 +78,9 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On @Input() aliasController: IAliasController; + @Input() + dataKeyCallbacks: DataKeysCallbacks; + @Input() dashboard: Dashboard; @@ -98,7 +102,7 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On private definedSettingsComponent: IWidgetSettingsComponent; private widgetSettingsFormData: JsonFormComponentData; - private propagateChange = (v: any) => { }; + private propagateChange = (_v: any) => { }; constructor(private translate: TranslateService, private cfr: ComponentFactoryResolver, @@ -138,6 +142,11 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On this.definedSettingsComponent.aliasController = this.aliasController; } } + if (propName === 'dataKeyCallbacks') { + if (this.definedSettingsComponent) { + this.definedSettingsComponent.dataKeyCallbacks = this.dataKeyCallbacks; + } + } if (propName === 'widgetConfig') { if (this.definedSettingsComponent) { this.definedSettingsComponent.widgetConfig = this.widgetConfig; @@ -225,6 +234,7 @@ export class WidgetSettingsComponent implements ControlValueAccessor, OnInit, On this.definedSettingsComponentRef = this.definedSettingsContainer.createComponent(factory); this.definedSettingsComponent = this.definedSettingsComponentRef.instance; this.definedSettingsComponent.aliasController = this.aliasController; + this.definedSettingsComponent.dataKeyCallbacks = this.dataKeyCallbacks; this.definedSettingsComponent.dashboard = this.dashboard; this.definedSettingsComponent.widget = this.widget; this.definedSettingsComponent.widgetConfig = this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts index 37ce7a9c7f..4bf89a4cde 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts @@ -119,10 +119,17 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C style.rich = renderCtx.labelOption.rich; } + let borderRadius: number[]; + if (value < 0) { + borderRadius = [0, 0, renderCtx.visualSettings.borderRadius, renderCtx.visualSettings.borderRadius]; + } else { + borderRadius = [renderCtx.visualSettings.borderRadius, renderCtx.visualSettings.borderRadius, 0, 0]; + } + return rectShape && { type: 'rect', id: time + '', - shape: {...rectShape, r: renderCtx.visualSettings.borderRadius}, + shape: {...rectShape, r: borderRadius}, style, focus: 'series', transition: 'all', diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index dfcd1aaced..ad2083902c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -43,6 +43,21 @@ import { TbColorScheme } from '@shared/models/color.models'; import { AbstractControl, ValidationErrors } from '@angular/forms'; import { MarkLine2DDataItemOption } from 'echarts/types/src/component/marker/MarkLineModel'; +export enum TimeSeriesChartType { + default = 'default', + line = 'line', + bar = 'bar', + point = 'point' +} + +export const timeSeriesChartTypeTranslations = new Map( + [ + [TimeSeriesChartType.line, 'widgets.time-series-chart.type-line'], + [TimeSeriesChartType.bar, 'widgets.time-series-chart.type-bar'], + [TimeSeriesChartType.point, 'widgets.time-series-chart.type-point'] + ] +); + const timeSeriesChartColorScheme: TbColorScheme = { 'threshold.line': { light: 'rgba(0, 0, 0, 0.76)', diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 08761fbe36..4b9bc3ba84 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -21,15 +21,18 @@ import { createTimeSeriesXAxisOption, createTimeSeriesYAxis, generateChartData, - parseThresholdData, SeriesLabelPosition, + parseThresholdData, + SeriesLabelPosition, TimeSeriesChartDataItem, timeSeriesChartDefaultSettings, timeSeriesChartKeyDefaultSettings, TimeSeriesChartKeySettings, TimeSeriesChartSeriesType, TimeSeriesChartSettings, + TimeSeriesChartShape, TimeSeriesChartThresholdItem, TimeSeriesChartThresholdType, + TimeSeriesChartType, TimeSeriesChartYAxis, updateDarkMode } from '@home/components/widget/lib/chart/time-series-chart.models'; @@ -63,11 +66,23 @@ import { DataKeySettingsFunction } from '@home/components/widget/config/data-key export class TbTimeSeriesChart { - public static dataKeySettings(): DataKeySettingsFunction { + public static dataKeySettings(type = TimeSeriesChartType.default): DataKeySettingsFunction { return (key, isLatestDataKey) => { if (!isLatestDataKey) { - return mergeDeep({} as TimeSeriesChartKeySettings, + const settings = mergeDeep({} as TimeSeriesChartKeySettings, timeSeriesChartKeyDefaultSettings); + if (type === TimeSeriesChartType.line) { + settings.type = TimeSeriesChartSeriesType.line; + } else if (type === TimeSeriesChartType.bar) { + settings.type = TimeSeriesChartSeriesType.bar; + } else if (type === TimeSeriesChartType.point) { + settings.type = TimeSeriesChartSeriesType.line; + settings.lineSettings.showLine = false; + settings.lineSettings.showPoints = true; + settings.lineSettings.pointShape = TimeSeriesChartShape.circle; + settings.lineSettings.pointSize = 8; + } + return settings; } return null; }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.html index 443ee4abc5..e40470d75e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.html @@ -124,6 +124,13 @@
    +
    + +
    + {{ 'tooltip.show-date-time-interval' | translate }} +
    +
    +
    {{ 'tooltip.background-color' | translate }}
    +
    + +
    + {{ 'tooltip.show-date-time-interval' | translate }} +
    +
    +
    {{ 'tooltip.background-color' | translate }}
    -
    +
    widgets.time-series-chart.series.series-type
    {{ timeSeriesChartSeriesTypeTranslations.get(type) | translate }}
    + +
    {{ timeSeriesChartTypeTranslations.get(chartType) | translate }}
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts index 24fb200b0b..4da23f32e0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts @@ -19,13 +19,13 @@ import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.m import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { mergeDeep } from '@core/utils'; +import { isDefinedAndNotNull, mergeDeep } from '@core/utils'; import { timeSeriesChartKeyDefaultSettings, TimeSeriesChartKeySettings, TimeSeriesChartSeriesType, timeSeriesChartSeriesTypes, - timeSeriesChartSeriesTypeTranslations + timeSeriesChartSeriesTypeTranslations, TimeSeriesChartType, timeSeriesChartTypeTranslations } from '@home/components/widget/lib/chart/time-series-chart.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models'; @@ -36,6 +36,10 @@ import { WidgetConfigComponentData } from '@home/models/widget-component.models' }) export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent { + TimeSeriesChartType = TimeSeriesChartType; + + timeSeriesChartTypeTranslations = timeSeriesChartTypeTranslations; + TimeSeriesChartSeriesType = TimeSeriesChartSeriesType; timeSeriesChartSeriesTypes = timeSeriesChartSeriesTypes; @@ -44,6 +48,8 @@ export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent timeSeriesChartKeySettingsForm: UntypedFormGroup; + chartType = TimeSeriesChartType.default; + constructor(protected store: Store, private fb: UntypedFormBuilder) { super(store); @@ -55,7 +61,9 @@ export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent protected onWidgetConfigSet(widgetConfig: WidgetConfigComponentData) { const params = widgetConfig.typeParameters as any; - // const timeSeriesChartType = params.timeSeriesChartType; + if (isDefinedAndNotNull(params.chartType)) { + this.chartType = params.chartType; + } } protected defaultSettings(): WidgetSettings { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.html index d9a942053c..78f1129727 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.html @@ -16,7 +16,7 @@ --> -
    +
    widgets.time-series-chart.series.line.line
    @@ -57,57 +57,60 @@
    -
    +
    widgets.time-series-chart.series.point.points
    {{ 'widgets.time-series-chart.series.point.show-points' | translate }}
    -
    - -
    - {{ 'widgets.time-series-chart.series.point.point-label' | translate }} -
    -
    -
    - - - - {{ seriesLabelPositionTranslations.get(position) | translate }} - - - - - - - + +
    + + + + +
    + +
    + {{ 'widgets.time-series-chart.series.point.point-label' | translate }}
    -
    -
    -
    widgets.time-series-chart.series.point.point-shape
    - - - - {{ timeSeriesChartShapeTranslations.get(shape) | translate }} + +
    + + + + {{ seriesLabelPositionTranslations.get(position) | translate }} -
    -
    -
    widgets.time-series-chart.series.point.point-size
    - - - + + + +
    - - - +
    +
    widgets.time-series-chart.series.point.point-shape
    + + + + {{ timeSeriesChartShapeTranslations.get(shape) | translate }} + + + +
    +
    +
    widgets.time-series-chart.series.point.point-size
    + + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts index 46a75edc08..84533b26e4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-line-settings.component.ts @@ -29,7 +29,7 @@ import { seriesLabelPositions, seriesLabelPositionTranslations, timeSeriesChartShapes, - timeSeriesChartShapeTranslations, + timeSeriesChartShapeTranslations, TimeSeriesChartType, timeSeriesLineTypes, timeSeriesLineTypeTranslations } from '@home/components/widget/lib/chart/time-series-chart.models'; @@ -53,6 +53,8 @@ import { DataKeyConfigComponent } from '@home/components/widget/config/data-key- }) export class TimeSeriesChartLineSettingsComponent implements OnInit, ControlValueAccessor { + TimeSeriesChartType = TimeSeriesChartType; + lineSeriesStepTypes = lineSeriesStepTypes; lineSeriesStepTypeTranslations = lineSeriesStepTypeTranslations; @@ -74,6 +76,9 @@ export class TimeSeriesChartLineSettingsComponent implements OnInit, ControlValu @Input() disabled: boolean; + @Input() + chartType: TimeSeriesChartType; + private modelValue: LineSeriesSettings; private propagateChange = null; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html new file mode 100644 index 0000000000..2d8294987e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html @@ -0,0 +1,159 @@ + + + + +
    +
    widgets.time-series-chart.chart-style
    +
    + + {{ 'widgets.time-series-chart.data-zoom' | translate }} + +
    +
    + +
    + {{ 'widgets.time-series-chart.stack-mode' | translate }} +
    +
    +
    +
    +
    widgets.time-series-chart.axis.axes
    + + + + +
    +
    + + + + + {{ 'widget-config.legend' | translate }} + + + + +
    +
    {{ 'legend.label' | translate }}
    +
    + + + + +
    +
    + + +
    +
    +
    +
    + + + + + {{ 'widget-config.tooltip' | translate }} + + + + +
    +
    {{ 'tooltip.trigger' | translate }}
    + + {{ 'tooltip.trigger-point' | translate }} + {{ 'tooltip.trigger-axis' | translate }} + +
    +
    +
    {{ 'tooltip.value' | translate }}
    +
    + + + + +
    +
    +
    + + {{ 'tooltip.date' | translate }} + +
    + + + + + +
    +
    +
    + +
    + {{ 'tooltip.show-date-time-interval' | translate }} +
    +
    +
    +
    +
    {{ 'tooltip.background-color' | translate }}
    + + +
    +
    +
    {{ 'tooltip.background-blur' | translate }}
    + + +
    px
    +
    +
    +
    +
    +
    +
    +
    {{ 'widgets.background.background' | translate }}
    + + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts new file mode 100644 index 0000000000..0321d07ba8 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts @@ -0,0 +1,174 @@ +/// +/// 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, Injector } from '@angular/core'; +import { + Datasource, + legendPositions, + legendPositionTranslationMap, + WidgetSettings, + WidgetSettingsComponent +} from '@shared/models/widget.models'; +import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { formatValue, mergeDeep } from '@core/utils'; +import { DateFormatProcessor, DateFormatSettings } from '@shared/models/widget-settings.models'; +import { + barChartWithLabelsDefaultSettings +} from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.models'; +import { EChartsTooltipTrigger } from '../../chart/echarts-widget.models'; +import { + timeSeriesChartWidgetDefaultSettings, TimeSeriesChartWidgetSettings +} from '@home/components/widget/lib/chart/time-series-chart-widget.models'; + +@Component({ + selector: 'tb-time-series-chart-widget-settings', + templateUrl: './time-series-chart-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'] +}) +export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsComponent { + + public get datasource(): Datasource { + const datasources: Datasource[] = this.widgetConfig.config.datasources; + if (datasources && datasources.length) { + return datasources[0]; + } else { + return null; + } + } + + EChartsTooltipTrigger = EChartsTooltipTrigger; + + legendPositions = legendPositions; + + legendPositionTranslationMap = legendPositionTranslationMap; + + timeSeriesChartWidgetSettingsForm: UntypedFormGroup; + + tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); + + tooltipDatePreviewFn = this._tooltipDatePreviewFn.bind(this); + + constructor(protected store: Store, + private $injector: Injector, + private fb: UntypedFormBuilder) { + super(store); + } + + protected settingsForm(): UntypedFormGroup { + return this.timeSeriesChartWidgetSettingsForm; + } + + protected defaultSettings(): WidgetSettings { + return mergeDeep({} as TimeSeriesChartWidgetSettings, timeSeriesChartWidgetDefaultSettings); + } + + protected onSettingsSet(settings: WidgetSettings) { + this.timeSeriesChartWidgetSettingsForm = this.fb.group({ + + thresholds: [settings.thresholds, []], + + dataZoom: [settings.dataZoom, []], + stack: [settings.stack, []], + + yAxis: [settings.yAxis, []], + xAxis: [settings.xAxis, []], + + showLegend: [settings.showLegend, []], + legendLabelFont: [settings.legendLabelFont, []], + legendLabelColor: [settings.legendLabelColor, []], + legendConfig: [settings.legendConfig, []], + + showTooltip: [settings.showTooltip, []], + tooltipTrigger: [settings.tooltipTrigger, []], + tooltipValueFont: [settings.tooltipValueFont, []], + tooltipValueColor: [settings.tooltipValueColor, []], + tooltipShowDate: [settings.tooltipShowDate, []], + tooltipDateFormat: [settings.tooltipDateFormat, []], + tooltipDateFont: [settings.tooltipDateFont, []], + tooltipDateColor: [settings.tooltipDateColor, []], + tooltipDateInterval: [settings.tooltipDateInterval, []], + + tooltipBackgroundColor: [settings.tooltipBackgroundColor, []], + tooltipBackgroundBlur: [settings.tooltipBackgroundBlur, []], + + background: [settings.background, []] + }); + } + + protected validatorTriggers(): string[] { + return ['showLegend', 'showTooltip', 'tooltipShowDate']; + } + + protected updateValidators(emitEvent: boolean) { + const showLegend: boolean = this.timeSeriesChartWidgetSettingsForm.get('showLegend').value; + const showTooltip: boolean = this.timeSeriesChartWidgetSettingsForm.get('showTooltip').value; + const tooltipShowDate: boolean = this.timeSeriesChartWidgetSettingsForm.get('tooltipShowDate').value; + + if (showLegend) { + this.timeSeriesChartWidgetSettingsForm.get('legendLabelFont').enable(); + this.timeSeriesChartWidgetSettingsForm.get('legendLabelColor').enable(); + this.timeSeriesChartWidgetSettingsForm.get('legendConfig').enable(); + } else { + this.timeSeriesChartWidgetSettingsForm.get('legendLabelFont').disable(); + this.timeSeriesChartWidgetSettingsForm.get('legendLabelColor').disable(); + this.timeSeriesChartWidgetSettingsForm.get('legendConfig').disable(); + } + + if (showTooltip) { + this.timeSeriesChartWidgetSettingsForm.get('tooltipTrigger').enable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipValueFont').enable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipValueColor').enable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipShowDate').enable({emitEvent: false}); + this.timeSeriesChartWidgetSettingsForm.get('tooltipBackgroundColor').enable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipBackgroundBlur').enable(); + if (tooltipShowDate) { + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateFormat').enable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateFont').enable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateColor').enable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateInterval').enable(); + } else { + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateFormat').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateFont').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateColor').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateInterval').disable(); + } + } else { + this.timeSeriesChartWidgetSettingsForm.get('tooltipValueFont').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipValueColor').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipShowDate').disable({emitEvent: false}); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateFormat').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateFont').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateColor').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipDateInterval').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipBackgroundColor').disable(); + this.timeSeriesChartWidgetSettingsForm.get('tooltipBackgroundBlur').disable(); + } + } + + private _tooltipValuePreviewFn(): string { + return formatValue(22, 0, '°C', false); + } + + private _tooltipDatePreviewFn(): string { + const dateFormat: DateFormatSettings = this.timeSeriesChartWidgetSettingsForm.get('tooltipDateFormat').value; + const processor = DateFormatProcessor.fromSettings(this.$injector, dateFormat); + processor.update(Date.now()); + return processor.formatted; + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html index a9db62ff89..473afe2608 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html @@ -49,10 +49,12 @@
    {{ 'widgets.time-series-chart.threshold.threshold-settings' | translate }}
    +
    +
    widget-config.units-short
    + + +
    +
    +
    widget-config.decimals-short
    + + + +
    +
    + + {{ 'widgets.time-series-chart.threshold.label' | translate }} + +
    + + + + {{ timeSeriesThresholdLabelPositionTranslations.get(position) | translate }} + + + + + + + +
    +
    widgets.time-series-chart.threshold.line-appearance
    @@ -46,7 +82,7 @@
    widgets.time-series-chart.threshold.start-symbol
    - + {{ timeSeriesChartShapeTranslations.get(shape) | translate }} @@ -54,7 +90,7 @@
    widgets.time-series-chart.threshold.symbol-size
    - + @@ -63,7 +99,7 @@
    widgets.time-series-chart.threshold.end-symbol
    - + {{ timeSeriesChartShapeTranslations.get(shape) | translate }} @@ -71,36 +107,12 @@
    widgets.time-series-chart.threshold.symbol-size
    - +
    -
    - - {{ 'widgets.time-series-chart.threshold.label' | translate }} - -
    - - - - {{ timeSeriesThresholdLabelPositionTranslations.get(position) | translate }} - - - - - - - -
    -
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.scss index 260b199854..b65fa6ad65 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.scss @@ -28,6 +28,8 @@ flex-direction: column; gap: 16px; overflow: auto; + margin: -10px; + padding: 10px; } .tb-threshold-settings-title { font-size: 16px; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts index a93a1c0181..47e1e93095 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component.ts @@ -74,6 +74,8 @@ export class TimeSeriesChartThresholdSettingsPanelComponent implements OnInit { ngOnInit(): void { this.thresholdSettingsFormGroup = this.fb.group( { + units: [this.thresholdSettings.units, []], + decimals: [this.thresholdSettings.decimals, [Validators.min(0)]], lineColor: [this.thresholdSettings.lineColor, []], lineType: [this.thresholdSettings.lineType, []], lineWidth: [this.thresholdSettings.lineWidth, [Validators.min(0)]], @@ -130,9 +132,10 @@ export class TimeSeriesChartThresholdSettingsPanelComponent implements OnInit { } private _labelPreviewFn(): string { - const units = this.thresholdSettings.units && this.thresholdSettings.units.length ? - this.thresholdSettings.units : this.widgetConfig.units; - const decimals = isDefinedAndNotNull(this.thresholdSettings.decimals) ? this.thresholdSettings.decimals : + let units: string = this.thresholdSettingsFormGroup.get('units').value; + units = units && units.length ? units : this.widgetConfig.units; + let decimals: number = this.thresholdSettingsFormGroup.get('decimals').value; + decimals = isDefinedAndNotNull(decimals) ? decimals : (isDefinedAndNotNull(this.widgetConfig.decimals) ? this.widgetConfig.decimals : 2); return formatValue(22, decimals, units, false); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.html index 811106fc7b..2054d8a15a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.html @@ -27,11 +27,12 @@
    -
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.scss index d1f1ec6eed..40f3c5359c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-thresholds-panel.component.scss @@ -13,15 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +@import '../../../../../../../../../scss/constants'; + .tb-time-series-thresholds-panel { .tb-form-table-header-cell { &.tb-threshold-source-header { flex: 1; - min-width: 200px; + min-width: 100px; + @media #{$mat-gt-md} { + min-width: 200px; + } } &.tb-threshold-key-value-header { flex: 1; - min-width: 150px; + min-width: 100px; + @media #{$mat-gt-md} { + min-width: 150px; + } } &.tb-units-header { @@ -43,5 +52,23 @@ width: 80px; min-width: 80px; } + + &.tb-units-header, &.tb-color-header, &.tb-decimals-header { + display: none; + @media #{$mat-gt-md} { + display: block; + } + } + } + .tb-form-table-body { + .tb-time-series-threshold-row { + overflow: hidden; + } + .mat-divider { + margin-top: 8px; + @media #{$mat-gt-sm} { + display: none; + } + } } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.html index 072c637641..94831b530f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/data-key-input.component.html @@ -15,7 +15,8 @@ limitations under the License. --> - + @@ -74,6 +75,15 @@ (matChipInputTokenEnd)="addKey($event)" /> + + warning + - calculateInterval(subsTw.startTs, endTs, subsTw.aggregation.interval, subsTw.tsOffset, subsTw.timezone, timestamp); + = (subsTw: SubscriptionTimewindow, endTs: number, timestamp: number): [number, number] => { + if (subsTw.aggregation.type === AggregationType.NONE) { + return [timestamp, timestamp]; + } else { + return calculateInterval(subsTw.startTs, endTs, subsTw.aggregation.interval, subsTw.tsOffset, subsTw.timezone, timestamp); + } +}; export const calculateAggIntervalWithWidgetTimeWindow = (widgetTimeWindow: WidgetTimewindow, timestamp: number): [number, number] => diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index a164d8d3ec..3088573d18 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -38,12 +38,12 @@ import { AbstractControl, UntypedFormGroup } from '@angular/forms'; import { Observable } from 'rxjs'; import { Dashboard } from '@shared/models/dashboard.models'; import { IAliasController } from '@core/api/widget-api.models'; -import { isNotEmptyStr } from '@core/utils'; +import { isNotEmptyStr, mergeDeep } from '@core/utils'; import { WidgetConfigComponentData } from '@home/models/widget-component.models'; import { ComponentStyle, Font, TimewindowStyle } from '@shared/models/widget-settings.models'; import { NULL_UUID } from '@shared/models/id/has-uuid'; import { HasTenantId } from '@shared/models/entity.models'; -import { DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; +import { DataKeysCallbacks, DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; export enum widgetType { timeseries = 'timeseries', @@ -815,6 +815,7 @@ export interface WidgetSize { export interface IWidgetSettingsComponent { aliasController: IAliasController; + dataKeyCallbacks: DataKeysCallbacks; dashboard: Dashboard; widget: Widget; widgetConfig: WidgetConfigComponentData; @@ -832,6 +833,8 @@ export abstract class WidgetSettingsComponent extends PageComponent implements aliasController: IAliasController; + dataKeyCallbacks: DataKeysCallbacks; + dashboard: Dashboard; widget: Widget; @@ -857,7 +860,7 @@ export abstract class WidgetSettingsComponent extends PageComponent implements if (!value) { this.settingsValue = this.defaultSettings(); } else { - this.settingsValue = {...this.defaultSettings(), ...value}; + this.settingsValue = mergeDeep(this.defaultSettings(), value); } if (!this.settingsSet) { this.settingsSet = true; 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 29fbafe83c..99b120b667 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6597,6 +6597,7 @@ }, "time-series-chart": { "chart": "Chart", + "chart-style": "Chart style", "data-zoom": "Data zoom", "stack-mode": "Stack mode", "stack-mode-hint": "Stacks series on the chart. The series with the same unit would be put on top of each other.", @@ -6615,6 +6616,9 @@ "shape-pin": "Pin", "shape-arrow": "Arrow", "shape-none": "None", + "type-line": "Line", + "type-bar": "Bar", + "type-point": "Point", "threshold": { "thresholds": "Thresholds", "source": "Source", @@ -6627,6 +6631,8 @@ "threshold-settings": "Threshold settings", "remove-threshold": "Remove threshold", "threshold-value-required": "Threshold value is required.", + "key-required": "Key is required.", + "entity-key-required": "Entity key is required.", "line-appearance": "Line appearance", "line-color": "Line color", "start-symbol": "Start symbol", From bd34456baad761d583bbfa3022fa57312dcd709a Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 7 Mar 2024 11:07:08 +0200 Subject: [PATCH 311/397] UI: Improve threshold line color settings. --- .../common/chart/time-series-chart-threshold-row.component.html | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html index 473afe2608..f82a717d78 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html @@ -75,6 +75,7 @@
    From 0d27c18efb768c03839eb6348f8a2034a043ad59 Mon Sep 17 00:00:00 2001 From: Dmitriymush Date: Thu, 7 Mar 2024 11:14:59 +0200 Subject: [PATCH 312/397] UI: refactoring widgetActionTypes --- .../lib/settings/common/action/widget-action.component.ts | 3 ++- ui-ngx/src/app/shared/models/widget.models.ts | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts index b7183a5b80..6c515ad0a7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts @@ -28,6 +28,7 @@ import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@an import { WidgetAction, WidgetActionType, + widgetActionTypes, widgetActionTypeTranslationMap, widgetType } from '@shared/models/widget.models'; @@ -88,7 +89,7 @@ export class WidgetActionComponent implements ControlValueAccessor, OnInit, Vali @Input() callbacks: WidgetActionCallbacks; - widgetActionTypes = Object.keys(WidgetActionType); + widgetActionTypes = widgetActionTypes; widgetActionTypeTranslations = widgetActionTypeTranslationMap; widgetActionType = WidgetActionType; diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index 5f4ca8f7be..de875c02ae 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -553,6 +553,8 @@ export enum WidgetMobileActionType { takeScreenshot = 'takeScreenshot' } +export const widgetActionTypes = Object.keys(WidgetActionType); + export const widgetActionTypeTranslationMap = new Map( [ [ WidgetActionType.openDashboardState, 'widget-action.open-dashboard-state' ], From ef385640ff7d2c921dfb56d06d86ed92fd41a412 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 7 Mar 2024 14:21:01 +0200 Subject: [PATCH 313/397] UI: Implement no aggregated data bar width strategies --- ...e-series-chart-basic-config.component.html | 27 +++++++++++ ...ime-series-chart-basic-config.component.ts | 35 ++++++++++++-- .../lib/chart/time-series-chart-bar.models.ts | 30 ++++++++++-- .../lib/chart/time-series-chart.models.ts | 37 ++++++++++++++- .../widget/lib/chart/time-series-chart.ts | 13 ++++-- ...eries-chart-widget-settings.component.html | 27 +++++++++++ ...-series-chart-widget-settings.component.ts | 46 +++++++++++++++++-- .../components/toggle-select.component.ts | 2 +- .../assets/locale/locale.constant-en_US.json | 5 ++ 9 files changed, 204 insertions(+), 18 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html index ac6c07290c..5b14146d0f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html @@ -114,6 +114,33 @@ axisType="xAxis">
    +
    +
    +
    widgets.time-series-chart.no-aggregation-bar-width-strategy
    + + + {{ timeSeriesChartNoAggregationBarWidthStrategyTranslations.get(strategy) | translate }} + + +
    +
    +
    widgets.time-series-chart.bar-group-interval-width
    + + + ms + +
    +
    +
    widgets.time-series-chart.separate-bar-width
    + + + ms + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts index a2d29269d3..79aa52fdb6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts @@ -45,7 +45,12 @@ import { TimeSeriesChartWidgetSettings } from '@home/components/widget/lib/chart/time-series-chart-widget.models'; import { EChartsTooltipTrigger } from '@home/components/widget/lib/chart/echarts-widget.models'; -import { TimeSeriesChartType } from '@home/components/widget/lib/chart/time-series-chart.models'; +import { + timeSeriesChartNoAggregationBarWidthStrategies, + TimeSeriesChartNoAggregationBarWidthStrategy, + timeSeriesChartNoAggregationBarWidthStrategyTranslations, + TimeSeriesChartType +} from '@home/components/widget/lib/chart/time-series-chart.models'; @Component({ selector: 'tb-time-series-chart-basic-config', @@ -71,13 +76,19 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon legendPositionTranslationMap = legendPositionTranslationMap; + TimeSeriesChartNoAggregationBarWidthStrategy = TimeSeriesChartNoAggregationBarWidthStrategy; + + timeSeriesChartNoAggregationBarWidthStrategies = timeSeriesChartNoAggregationBarWidthStrategies; + + timeSeriesChartNoAggregationBarWidthStrategyTranslations = timeSeriesChartNoAggregationBarWidthStrategyTranslations; + timeSeriesChartWidgetConfigForm: UntypedFormGroup; tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); tooltipDatePreviewFn = this._tooltipDatePreviewFn.bind(this); - chartType = TimeSeriesChartType.default; + chartType: TimeSeriesChartType = TimeSeriesChartType.default; constructor(protected store: Store, protected widgetConfigComponent: WidgetConfigComponent, @@ -129,6 +140,12 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon yAxis: [settings.yAxis, []], xAxis: [settings.xAxis, []], + noAggregationBarWidthSettings: this.fb.group({ + strategy: [settings.noAggregationBarWidthSettings.strategy, []], + groupIntervalWidth: [settings.noAggregationBarWidthSettings.groupIntervalWidth, [Validators.min(100)]], + separateBarWidth: [settings.noAggregationBarWidthSettings.separateBarWidth, [Validators.min(100)]], + }), + showLegend: [settings.showLegend, []], legendLabelFont: [settings.legendLabelFont, []], legendLabelColor: [settings.legendLabelColor, []], @@ -181,6 +198,8 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon this.widgetConfig.config.settings.yAxis = config.yAxis; this.widgetConfig.config.settings.xAxis = config.xAxis; + this.widgetConfig.config.settings.noAggregationBarWidthSettings = config.noAggregationBarWidthSettings; + this.widgetConfig.config.settings.showLegend = config.showLegend; this.widgetConfig.config.settings.legendLabelFont = config.legendLabelFont; this.widgetConfig.config.settings.legendLabelColor = config.legendLabelColor; @@ -208,7 +227,7 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon } protected validatorTriggers(): string[] { - return ['showTitle', 'showIcon', 'showLegend', 'showTooltip', 'tooltipShowDate']; + return ['showTitle', 'showIcon', 'showLegend', 'showTooltip', 'tooltipShowDate', 'noAggregationBarWidthSettings.strategy']; } protected updateValidators(emitEvent: boolean, trigger?: string) { @@ -217,6 +236,8 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon const showLegend: boolean = this.timeSeriesChartWidgetConfigForm.get('showLegend').value; const showTooltip: boolean = this.timeSeriesChartWidgetConfigForm.get('showTooltip').value; const tooltipShowDate: boolean = this.timeSeriesChartWidgetConfigForm.get('tooltipShowDate').value; + const noAggregationBarWidthSettingsStrategy: TimeSeriesChartNoAggregationBarWidthStrategy = + this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('strategy').value; if (showTitle) { this.timeSeriesChartWidgetConfigForm.get('title').enable(); @@ -245,6 +266,14 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon this.timeSeriesChartWidgetConfigForm.get('iconColor').disable(); } + if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.group) { + this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').enable(); + this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('separateBarWidth').disable(); + } else if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate) { + this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').disable(); + this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('separateBarWidth').enable(); + } + if (showLegend) { this.timeSeriesChartWidgetConfigForm.get('legendLabelFont').enable(); this.timeSeriesChartWidgetConfigForm.get('legendLabelColor').enable(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts index 4bf89a4cde..e5dfd6944e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts @@ -17,7 +17,11 @@ import { LinearGradientObject } from 'zrender/lib/graphic/LinearGradient'; import { Interval, IntervalMath } from '@shared/models/time/time.models'; import { LabelFormatterCallback, SeriesLabelOption } from 'echarts/types/src/util/types'; -import { TimeSeriesChartDataItem } from '@home/components/widget/lib/chart/time-series-chart.models'; +import { + TimeSeriesChartDataItem, + TimeSeriesChartNoAggregationBarWidthSettings, + TimeSeriesChartNoAggregationBarWidthStrategy +} from '@home/components/widget/lib/chart/time-series-chart.models'; import { CustomSeriesRenderItemParams } from 'echarts'; import { CustomSeriesRenderItemAPI, CustomSeriesRenderItemReturn } from 'echarts/types/dist/shared'; import { isNumeric } from '@core/utils'; @@ -33,6 +37,8 @@ export interface BarVisualSettings { export interface BarRenderContext { barsCount?: number; barIndex?: number; + noAggregation: boolean; + noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings; timeInterval?: Interval; visualSettings?: BarVisualSettings; labelOption?: SeriesLabelOption; @@ -44,19 +50,35 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C renderCtx: BarRenderContext): CustomSeriesRenderItemReturn => { const time = api.value(0) as number; let start = api.value(2) as number; - const end = api.value(3) as number; + let end = api.value(3) as number; let interval = end - start; const ts = start ? start : time; + + const noAggregationGroup = renderCtx.noAggregation && + renderCtx.noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group; + const separateBar = renderCtx.noAggregation && + renderCtx.noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate; + + if (renderCtx.noAggregation) { + if (noAggregationGroup) { + interval = renderCtx.noAggregationBarWidthSettings.groupIntervalWidth; + } else { + interval = renderCtx.noAggregationBarWidthSettings.separateBarWidth; + } + start = time - interval / 2; + end = time + interval / 2; + } if (!start || !end || !interval) { interval = IntervalMath.numberValue(renderCtx.timeInterval); start = time - interval / 2; } + const gap = 0.3; - const barInterval = interval / (renderCtx.barsCount + gap * (renderCtx.barsCount + 3)); + const barInterval = separateBar ? interval : interval / (renderCtx.barsCount + gap * (renderCtx.barsCount + 3)); const intervalGap = barInterval * gap * 2; const barGap = barInterval * gap; const value = api.value(1); - const startTime = start + intervalGap + (barInterval + barGap) * renderCtx.barIndex; + const startTime = separateBar ? start : start + intervalGap + (barInterval + barGap) * renderCtx.barIndex; const delta = barInterval; let offset = 0; if (renderCtx.currentStackItems?.length) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index ad2083902c..6aac959cbe 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -376,6 +376,27 @@ export const timeSeriesChartThresholdDefaultSettings: TimeSeriesChartThreshold = labelColor: timeSeriesChartColorScheme['threshold.label'].light }; +export enum TimeSeriesChartNoAggregationBarWidthStrategy { + group = 'group', + separate = 'separate' +} + +export const timeSeriesChartNoAggregationBarWidthStrategies = + Object.keys(TimeSeriesChartNoAggregationBarWidthStrategy) as TimeSeriesChartNoAggregationBarWidthStrategy[]; + +export const timeSeriesChartNoAggregationBarWidthStrategyTranslations = new Map( + [ + [TimeSeriesChartNoAggregationBarWidthStrategy.group, 'widgets.time-series-chart.no-aggregation-bar-width-strategy-group'], + [TimeSeriesChartNoAggregationBarWidthStrategy.separate, 'widgets.time-series-chart.no-aggregation-bar-width-strategy-separate'] + ] +); + +export interface TimeSeriesChartNoAggregationBarWidthSettings { + strategy: TimeSeriesChartNoAggregationBarWidthStrategy; + groupIntervalWidth?: number; + separateBarWidth?: number; +} + export interface TimeSeriesChartSettings extends EChartsTooltipWidgetSettings { thresholds: TimeSeriesChartThreshold[]; darkMode: boolean; @@ -383,6 +404,7 @@ export interface TimeSeriesChartSettings extends EChartsTooltipWidgetSettings { stack: boolean; yAxis: TimeSeriesChartYAxisSettings; xAxis: TimeSeriesChartAxisSettings; + noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings; } export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { @@ -450,6 +472,11 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { showSplitLines: true, splitLinesColor: timeSeriesChartColorScheme['axis.splitLine'].light }, + noAggregationBarWidthSettings: { + strategy: TimeSeriesChartNoAggregationBarWidthStrategy.group, + groupIntervalWidth: 1000, + separateBarWidth: 1000 + }, showTooltip: true, tooltipTrigger: EChartsTooltipTrigger.axis, tooltipValueFont: { @@ -730,9 +757,12 @@ export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartAxisSetting export const generateChartData = (dataItems: TimeSeriesChartDataItem[], thresholdItems: TimeSeriesChartThresholdItem[], timeInterval: Interval, + noAggregation: boolean, + noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings, stack: boolean, darkMode: boolean): Array => { - let series = generateChartSeries(dataItems, timeInterval, stack, darkMode); + let series = generateChartSeries(dataItems, timeInterval, + noAggregation, noAggregationBarWidthSettings, stack, darkMode); if (thresholdItems.length) { const thresholds = generateChartThresholds(thresholdItems, darkMode); series = series.concat(thresholds); @@ -844,6 +874,8 @@ const createThresholdData = (val: string | number, item: TimeSeriesChartThreshol const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], timeInterval: Interval, + noAggregation: boolean, + noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings, stack: boolean, darkMode: boolean): Array => { const series: Array = []; @@ -863,8 +895,9 @@ const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], for (const item of enabledDataItems) { if (item.dataKey.settings.type === TimeSeriesChartSeriesType.bar) { if (!item.barRenderContext) { - item.barRenderContext = {}; + item.barRenderContext = {noAggregation, noAggregationBarWidthSettings}; } + item.barRenderContext.noAggregation = noAggregation; item.barRenderContext.barsCount = barsCount; item.barRenderContext.barIndex = stack ? barGroups.indexOf(item.yAxisIndex) : barDataItems.indexOf(item); item.barRenderContext.timeInterval = timeInterval; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 4b9bc3ba84..e5d4cb8f46 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -88,6 +88,10 @@ export class TbTimeSeriesChart { }; } + private get noAggregation(): boolean { + return this.ctx.defaultSubscription.timeWindowConfig?.aggregation?.type === AggregationType.NONE; + } + private readonly shapeResize$: ResizeObserver; private dataItems: TimeSeriesChartDataItem[] = []; @@ -153,7 +157,7 @@ export class TbTimeSeriesChart { this.timeSeriesChartOptions.xAxis[0].min = this.ctx.defaultSubscription.timeWindow.minTime; this.timeSeriesChartOptions.xAxis[0].max = this.ctx.defaultSubscription.timeWindow.maxTime; this.timeSeriesChartOptions.xAxis[0].tbTimeWindow = this.ctx.defaultSubscription.timeWindow; - if (this.ctx.defaultSubscription.timeWindowConfig?.aggregation?.type === AggregationType.NONE) { + if (this.noAggregation) { this.timeSeriesChartOptions.tooltip[0].axisPointer.type = 'line'; } else { this.timeSeriesChartOptions.tooltip[0].axisPointer.type = 'shadow'; @@ -414,7 +418,6 @@ export class TbTimeSeriesChart { this.timeSeriesChart = echarts.init(this.chartElement, null, { renderer: 'canvas' }); - const noAggregation = this.ctx.defaultSubscription.timeWindowConfig?.aggregation?.type === AggregationType.NONE; this.timeSeriesChartOptions = { darkMode: this.darkMode, backgroundColor: 'transparent', @@ -423,7 +426,7 @@ export class TbTimeSeriesChart { confine: true, appendToBody: true, axisPointer: { - type: noAggregation ? 'line' : 'shadow' + type: this.noAggregation ? 'line' : 'shadow' }, formatter: (params: CallbackDataParams[]) => this.settings.showTooltip ? echartsTooltipFormatter(this.renderer, this.tooltipDateFormat, @@ -488,7 +491,9 @@ export class TbTimeSeriesChart { private updateSeries(): Array { return generateChartData(this.dataItems, this.thresholdItems, - this.ctx.timeWindow.interval, this.settings.stack, this.darkMode); + this.ctx.timeWindow.interval, + this.noAggregation, + this.settings.noAggregationBarWidthSettings, this.settings.stack, this.darkMode); } private updateAxes() { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html index 2d8294987e..f3a9a610c3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html @@ -48,6 +48,33 @@ axisType="xAxis">
    +
    +
    +
    widgets.time-series-chart.no-aggregation-bar-width-strategy
    + + + {{ timeSeriesChartNoAggregationBarWidthStrategyTranslations.get(strategy) | translate }} + + +
    +
    +
    widgets.time-series-chart.bar-group-interval-width
    + + + ms + +
    +
    +
    widgets.time-series-chart.separate-bar-width
    + + + ms + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts index 0321d07ba8..a520933f1b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts @@ -22,10 +22,10 @@ import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models'; -import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { formatValue, mergeDeep } from '@core/utils'; +import { formatValue, isDefinedAndNotNull, mergeDeep } from '@core/utils'; import { DateFormatProcessor, DateFormatSettings } from '@shared/models/widget-settings.models'; import { barChartWithLabelsDefaultSettings @@ -34,6 +34,12 @@ import { EChartsTooltipTrigger } from '../../chart/echarts-widget.models'; import { timeSeriesChartWidgetDefaultSettings, TimeSeriesChartWidgetSettings } from '@home/components/widget/lib/chart/time-series-chart-widget.models'; +import { + timeSeriesChartNoAggregationBarWidthStrategies, + TimeSeriesChartNoAggregationBarWidthStrategy, + timeSeriesChartNoAggregationBarWidthStrategyTranslations, TimeSeriesChartType +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { WidgetConfigComponentData } from '@home/models/widget-component.models'; @Component({ selector: 'tb-time-series-chart-widget-settings', @@ -51,18 +57,28 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon } } + TimeSeriesChartType = TimeSeriesChartType; + EChartsTooltipTrigger = EChartsTooltipTrigger; legendPositions = legendPositions; legendPositionTranslationMap = legendPositionTranslationMap; + TimeSeriesChartNoAggregationBarWidthStrategy = TimeSeriesChartNoAggregationBarWidthStrategy; + + timeSeriesChartNoAggregationBarWidthStrategies = timeSeriesChartNoAggregationBarWidthStrategies; + + timeSeriesChartNoAggregationBarWidthStrategyTranslations = timeSeriesChartNoAggregationBarWidthStrategyTranslations; + timeSeriesChartWidgetSettingsForm: UntypedFormGroup; tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); tooltipDatePreviewFn = this._tooltipDatePreviewFn.bind(this); + chartType: TimeSeriesChartType = TimeSeriesChartType.default; + constructor(protected store: Store, private $injector: Injector, private fb: UntypedFormBuilder) { @@ -73,6 +89,13 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon return this.timeSeriesChartWidgetSettingsForm; } + protected onWidgetConfigSet(widgetConfig: WidgetConfigComponentData) { + const params = widgetConfig.typeParameters as any; + if (isDefinedAndNotNull(params.chartType)) { + this.chartType = params.chartType; + } + } + protected defaultSettings(): WidgetSettings { return mergeDeep({} as TimeSeriesChartWidgetSettings, timeSeriesChartWidgetDefaultSettings); } @@ -88,6 +111,12 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon yAxis: [settings.yAxis, []], xAxis: [settings.xAxis, []], + noAggregationBarWidthSettings: this.fb.group({ + strategy: [settings.noAggregationBarWidthSettings.strategy, []], + groupIntervalWidth: [settings.noAggregationBarWidthSettings.groupIntervalWidth, [Validators.min(100)]], + separateBarWidth: [settings.noAggregationBarWidthSettings.separateBarWidth, [Validators.min(100)]], + }), + showLegend: [settings.showLegend, []], legendLabelFont: [settings.legendLabelFont, []], legendLabelColor: [settings.legendLabelColor, []], @@ -111,13 +140,23 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon } protected validatorTriggers(): string[] { - return ['showLegend', 'showTooltip', 'tooltipShowDate']; + return ['showLegend', 'showTooltip', 'tooltipShowDate', 'noAggregationBarWidthSettings.strategy']; } protected updateValidators(emitEvent: boolean) { const showLegend: boolean = this.timeSeriesChartWidgetSettingsForm.get('showLegend').value; const showTooltip: boolean = this.timeSeriesChartWidgetSettingsForm.get('showTooltip').value; const tooltipShowDate: boolean = this.timeSeriesChartWidgetSettingsForm.get('tooltipShowDate').value; + const noAggregationBarWidthSettingsStrategy: TimeSeriesChartNoAggregationBarWidthStrategy = + this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('strategy').value; + + if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.group) { + this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').enable(); + this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('separateBarWidth').disable(); + } else if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate) { + this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').disable(); + this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('separateBarWidth').enable(); + } if (showLegend) { this.timeSeriesChartWidgetSettingsForm.get('legendLabelFont').enable(); @@ -170,5 +209,4 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon processor.update(Date.now()); return processor.formatted; } - } diff --git a/ui-ngx/src/app/shared/components/toggle-select.component.ts b/ui-ngx/src/app/shared/components/toggle-select.component.ts index 9be788c08d..484ea19b2e 100644 --- a/ui-ngx/src/app/shared/components/toggle-select.component.ts +++ b/ui-ngx/src/app/shared/components/toggle-select.component.ts @@ -43,7 +43,7 @@ export class ToggleSelectComponent extends _ToggleBase implements ControlValueAc disabled: boolean; @Input() - selectMediaBreakpoint; + selectMediaBreakpoint: string; @Input() appearance: ToggleHeaderAppearance = 'stroked'; 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 4a58bf239c..b32cfb7d38 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6626,6 +6626,11 @@ "type-line": "Line", "type-bar": "Bar", "type-point": "Point", + "no-aggregation-bar-width-strategy": "Bar width strategy for non-aggregated data", + "no-aggregation-bar-width-strategy-group": "Group", + "no-aggregation-bar-width-strategy-separate": "Separate", + "bar-group-interval-width": "Bar group interval width", + "separate-bar-width": "Separate bar width", "threshold": { "thresholds": "Thresholds", "source": "Source", From 2e216242f2ac63ef9a6ee2f8c9420f18df9bfe8a Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 7 Mar 2024 14:44:20 +0200 Subject: [PATCH 314/397] clone repo if tmp directory was deleted --- .../sync/vc/DefaultGitRepositoryService.java | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java index 24d23c60a1..8bbc9defa2 100644 --- a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java +++ b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java @@ -157,7 +157,7 @@ public class DefaultGitRepositoryService implements GitRepositoryService { @Override public void fetch(TenantId tenantId) throws GitAPIException { - var repository = repositories.get(tenantId); + var repository = checkRepository(tenantId); if (repository != null) { log.debug("[{}] Fetching tenant repository.", tenantId); repository.fetch(); @@ -195,8 +195,17 @@ public class DefaultGitRepositoryService implements GitRepositoryService { } private GitRepository checkRepository(TenantId tenantId) { - return Optional.ofNullable(repositories.get(tenantId)) + GitRepository gitRepository = Optional.ofNullable(repositories.get(tenantId)) .orElseThrow(() -> new IllegalStateException("Repository is not initialized")); + + if (!Files.exists(Path.of(gitRepository.getDirectory()))) { + try { + return cloneRepository(tenantId, gitRepository.getSettings()); + } catch (Exception e) { + throw new IllegalStateException("Repository is not initialized"); + } + } + return gitRepository; } @Override @@ -229,17 +238,7 @@ public class DefaultGitRepositoryService implements GitRepositoryService { testRepository(tenantId, settings); clearRepository(tenantId); - log.debug("[{}] Init tenant repository started.", tenantId); - Path repositoryDirectory = Path.of(repositoriesFolder, tenantId.getId().toString()); - GitRepository repository; - if (Files.exists(repositoryDirectory)) { - FileUtils.forceDelete(repositoryDirectory.toFile()); - } - - Files.createDirectories(repositoryDirectory); - repository = GitRepository.clone(settings, repositoryDirectory.toFile()); - repositories.put(tenantId, repository); - log.debug("[{}] Init tenant repository completed.", tenantId); + cloneRepository(tenantId, settings); } @Override @@ -276,4 +275,18 @@ public class DefaultGitRepositoryService implements GitRepositoryService { String entityId = StringUtils.substringBetween(path, "/", ".json"); return EntityIdFactory.getByTypeAndUuid(entityType, entityId); } + + private GitRepository cloneRepository(TenantId tenantId, RepositorySettings settings) throws Exception { + log.debug("[{}] Init tenant repository started.", tenantId); + Path repositoryDirectory = Path.of(repositoriesFolder, tenantId.getId().toString()); + + if (Files.exists(repositoryDirectory)) { + FileUtils.forceDelete(repositoryDirectory.toFile()); + } + Files.createDirectories(repositoryDirectory); + GitRepository repository = GitRepository.clone(settings, repositoryDirectory.toFile()); + repositories.put(tenantId, repository); + log.debug("[{}] Init tenant repository completed.", tenantId); + return repository; + } } From 04ff4bd9ae15bcddd9fdf411c7258391f2c9cb10 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 7 Mar 2024 15:38:27 +0200 Subject: [PATCH 315/397] refactored handleError method: status code and message are being retrieved from exception --- .../ThingsboardErrorResponseHandler.java | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java index f843a8ec6f..e773e5ffd6 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -16,6 +16,7 @@ package org.thingsboard.server.exception; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -50,9 +51,11 @@ import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.swing.text.html.Option; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import static javax.servlet.RequestDispatcher.ERROR_EXCEPTION; @@ -102,22 +105,13 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand @RequestMapping("/error") public ResponseEntity handleError(HttpServletRequest request) { - Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); - - if (status != null) { - int statusCode = Integer.parseInt(status.toString()); - if(statusCode == HttpStatus.NOT_FOUND.value()) { - return new ResponseEntity<>(ThingsboardErrorResponse.of(PATH_NOT_FOUND_ERROR_DESCRIPTION, ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND), HttpStatus.NOT_FOUND); - } - } - String errorMessage; - Throwable throwable = (Throwable) request.getAttribute(ERROR_EXCEPTION); - if (throwable != null) { - errorMessage = throwable.getMessage(); - } else { - errorMessage = GENERAL_ERROR_DESCRIPTION; - } - return new ResponseEntity<>(ThingsboardErrorResponse.of(errorMessage, ThingsboardErrorCode.GENERAL, HttpStatus.INTERNAL_SERVER_ERROR), HttpStatus.INTERNAL_SERVER_ERROR); + HttpStatus httpStatus = Optional.ofNullable(request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE)) + .map(status -> HttpStatus.resolve(Integer.parseInt(status.toString()))) + .orElse(HttpStatus.INTERNAL_SERVER_ERROR); + String errorMessage = Optional.ofNullable(request.getAttribute(ERROR_EXCEPTION)) + .map(e -> (ExceptionUtils.getMessage((Throwable) e))) + .orElse(httpStatus.getReasonPhrase()); + return new ResponseEntity<>(ThingsboardErrorResponse.of(errorMessage, statusToErrorCode(httpStatus), httpStatus), httpStatus); } @Override From 658f6679bc073304c13a53589495b2082ad16e53 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 7 Mar 2024 15:41:14 +0200 Subject: [PATCH 316/397] improved error logging --- .../service/sync/vc/DefaultGitRepositoryService.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java index 8bbc9defa2..6b6812b8ef 100644 --- a/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java +++ b/common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/DefaultGitRepositoryService.java @@ -158,11 +158,9 @@ public class DefaultGitRepositoryService implements GitRepositoryService { @Override public void fetch(TenantId tenantId) throws GitAPIException { var repository = checkRepository(tenantId); - if (repository != null) { - log.debug("[{}] Fetching tenant repository.", tenantId); - repository.fetch(); - log.debug("[{}] Fetched tenant repository.", tenantId); - } + log.debug("[{}] Fetching tenant repository.", tenantId); + repository.fetch(); + log.debug("[{}] Fetched tenant repository.", tenantId); } @Override @@ -202,7 +200,7 @@ public class DefaultGitRepositoryService implements GitRepositoryService { try { return cloneRepository(tenantId, gitRepository.getSettings()); } catch (Exception e) { - throw new IllegalStateException("Repository is not initialized"); + throw new IllegalStateException("Could not initialize the repository: " + e.getMessage(), e); } } return gitRepository; From 9fca9e235fbaa2a7f992638a286c20fe7d48a8a2 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 7 Mar 2024 16:32:30 +0200 Subject: [PATCH 317/397] deleted redundant const --- .../server/exception/ThingsboardErrorResponseHandler.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java index e773e5ffd6..2e572ce8c4 100644 --- a/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java +++ b/application/src/main/java/org/thingsboard/server/exception/ThingsboardErrorResponseHandler.java @@ -51,7 +51,6 @@ import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.swing.text.html.Option; import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -64,9 +63,6 @@ import static javax.servlet.RequestDispatcher.ERROR_EXCEPTION; @RestControllerAdvice public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHandler implements AccessDeniedHandler, ErrorController { - public static final String PATH_NOT_FOUND_ERROR_DESCRIPTION = "Path is not found."; - public static final String GENERAL_ERROR_DESCRIPTION = "Something went wrong!"; - private static final Map statusToErrorCodeMap = new HashMap<>(); static { statusToErrorCodeMap.put(HttpStatus.BAD_REQUEST, ThingsboardErrorCode.BAD_REQUEST_PARAMS); From 51b70f9618c938bcf13251e693db666aec5abd92 Mon Sep 17 00:00:00 2001 From: kalytka Date: Thu, 7 Mar 2024 16:53:29 +0200 Subject: [PATCH 318/397] Improve Api Usage dashboard --- ui-ngx/src/assets/dashboard/api_usage.json | 12725 ++++++++++------ .../assets/locale/locale.constant-en_US.json | 3 + 2 files changed, 7867 insertions(+), 4861 deletions(-) diff --git a/ui-ngx/src/assets/dashboard/api_usage.json b/ui-ngx/src/assets/dashboard/api_usage.json index b1cea42249..5618494261 100644 --- a/ui-ngx/src/assets/dashboard/api_usage.json +++ b/ui-ngx/src/assets/dashboard/api_usage.json @@ -1,4926 +1,7929 @@ { - "title": "Api Usage", - "image": null, - "mobileHide": false, - "mobileOrder": null, - "configuration": { - "description": "", - "widgets": { - "fd6df872-2ddf-0921-3929-2e7f55062fad": { - "type": "latest", - "sizeX": 7.5, - "sizeY": 3, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "jsExecutionApiState", - "type": "timeseries", - "label": "jsApiState", - "color": "#2196f3", - "settings": {}, - "_hash": 0.8830669138660703, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value : 'ENABLED';", - "aggregationType": "NONE" - }, - { - "name": "jsExecutionLimit", - "type": "timeseries", - "label": "jsLimit", - "color": "#4caf50", - "settings": {}, - "_hash": 0.5463603803546802, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null, - "aggregationType": "NONE" - }, - { - "name": "jsExecutionCount", - "type": "timeseries", - "label": "jsCount", - "color": "#f44336", - "settings": {}, - "_hash": 0.5564241862015964, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null, - "aggregationType": "NONE" + "title": "Api Usage", + "image": null, + "mobileHide": false, + "mobileOrder": null, + "configuration": { + "description": "", + "widgets": { + "a669cf86-e715-efa4-dd9a-b839abf499e9": { + "type": "timeseries", + "sizeX": 24, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "dataKeys": [ + { + "name": "ruleEngineException", + "type": "timeseries", + "label": "Rule Chain", + "color": "#2196f3", + "settings": { + "useCellStyleFunction": false, + "useCellContentFunction": true, + "cellContentFunction": "return JSON.parse(value).ruleChainName;" + }, + "_hash": 0.9954481282345906 + }, + { + "name": "ruleEngineException", + "type": "timeseries", + "label": "Rule Node", + "color": "#4caf50", + "settings": { + "useCellStyleFunction": false, + "useCellContentFunction": true, + "cellContentFunction": "return JSON.parse(value).ruleNodeName;" + }, + "_hash": 0.18580357036589978 + }, + { + "name": "ruleEngineException", + "type": "timeseries", + "label": "Latest Error", + "color": "#f44336", + "settings": { + "useCellStyleFunction": false, + "useCellContentFunction": true, + "cellContentFunction": "return JSON.parse(value).message;" + }, + "_hash": 0.7255162989552142 + } + ], + "entityAliasId": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f" + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 2592000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgb(255, 255, 255)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "8px", + "settings": { + "showTimestamp": true, + "displayPagination": true, + "defaultPageSize": 10 + }, + "title": "{i18n:api-usage.exceptions}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "useDashboardTimewindow": false, + "showLegend": false, + "widgetStyle": {}, + "actions": {}, + "showTitleIcon": false, + "titleIcon": null, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "displayTimewindow": true, + "widgetCss": "", + "pageSize": 1024, + "noDataDisplayMessage": "" }, - { - "name": "jsExecutionApiState", - "type": "timeseries", - "label": "cardId", - "color": "#607d8b", - "settings": {}, - "_hash": 0.051659774305067296, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return (Math.random()*100000).toFixed(0);" + "id": "a669cf86-e715-efa4-dd9a-b839abf499e9", + "typeFullFqn": "system.cards.timeseries_table" + }, + "aab68ab5-8e40-8694-c55c-8eb1c89b88fb": { + "typeFullFqn": "system.cards.markdown_card", + "type": "latest", + "sizeX": 5, + "sizeY": 3.5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "transportMsgLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "transportMsgCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;\n", + "aggregationType": "NONE" + }, + { + "name": "transportDataPointsLimit", + "type": "timeseries", + "label": "pointsLimit", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.22082255831864894, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "transportDataPointsCount", + "type": "timeseries", + "label": "pointsCount", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.6340356364819146, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "transportApiState", + "type": "timeseries", + "label": "title", + "color": "#3f51b5", + "settings": {}, + "_hash": 0.6894070537030252, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.transport}\";" + }, + { + "name": "transportApiState", + "type": "timeseries", + "label": "apiStatus", + "color": "#3f51b5", + "settings": {}, + "_hash": 0.430957831457494, + "aggregationType": "NONE", + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value.toLowerCase() : 'enabled';" + }, + { + "name": "transportApiState", + "type": "timeseries", + "label": "unit", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.662147926074595, + "aggregationType": "NONE", + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return '{i18n:api-usage.messages}';" + }, + { + "name": "transportApiState", + "type": "timeseries", + "label": "pointsUnit", + "color": "#3f51b5", + "settings": {}, + "_hash": 0.44620898738917947, + "aggregationType": "NONE", + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return '{i18n:api-usage.data-points}';" + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "displayValue": "", + "selectedTab": 0, + "realtime": { + "realtimeType": 1, + "interval": 1000, + "timewindowMs": 60000, + "quickInterval": "CURRENT_DAY" + }, + "history": { + "historyType": 0, + "interval": 1000, + "timewindowMs": 60000, + "fixedTimewindow": { + "startTimeMs": 1708518962586, + "endTimeMs": 1708605362586 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "AVG", + "limit": 25000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "useMarkdownTextFunction": true, + "markdownTextPattern": "", + "markdownTextFunction": "function toShortNumber(number) {\n const rounder = Math.pow(10, 1);\n const powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n let key = '';\n for (const power of powers) {\n const reduced = number / power.value;\n for (const power of powers) {\n let reduced = number / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = power.key;\n break;\n }\n }\n }\n \n return number + key;\n}\n\nfunction calculateBarValues(count, limit) {\n let apiUsageBar = '0%';\n let apiUsagePercent = '';\n let apiUsageValue = `${toShortNumber(count)} / ∞`;\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n apiUsageBar = `${percent}%`\n apiUsagePercent = `${percent.toFixed(2)}%`;\n apiUsageValue = `${toShortNumber(count)} / ${toShortNumber(limit)}`;\n }\n \n return [apiUsageBar, apiUsagePercent, apiUsageValue]\n}\n\nconst [apiUsageBar, apiUsagePercent, apiUsageValue] = calculateBarValues(data[0].count, data[0].limit);\nconst [apiUsageBar2, apiUsagePercent2, apiUsageValue2] = calculateBarValues(data[0].pointsCount, data[0].pointsLimit);\n\n\nreturn `
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n `${data[0].title}` +\n '
    ' +\n `
    ${data[0].apiStatus.toUpperCase()}
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n `
    ${data[0].unit}
    ` +\n '
    ' +\n `
    ` +\n '
    ' +\n '
    ' +\n `
    ${apiUsagePercent}
    ` +\n '
    ' +\n `
    ${apiUsageValue}
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n `
    ${data[0].pointsUnit}
    ` +\n '
    ' +\n `
    ` +\n '
    ' +\n '
    ' +\n `
    ${apiUsagePercent2}
    ` +\n '
    ' +\n `
    ${apiUsageValue2}
    ` +\n '
    ' +\n '
    ' + \n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n '' +\n '
    '+\n '' +\n '
    ' +\n '
    '\n", + "applyDefaultMarkdownStyle": false, + "markdownCss": "\n" + }, + "title": "Transport", + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": {}, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "showLegend": false, + "useDashboardTimewindow": true, + "displayTimewindow": true, + "widgetCss": "", + "pageSize": 1024, + "noDataDisplayMessage": "", + "actions": { + "elementClick": [ + { + "name": "transport_details", + "icon": "insert_chart", + "useShowWidgetActionFunction": null, + "showWidgetActionFunction": "return true;", + "type": "openDashboardState", + "targetDashboardStateId": "transport", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "openInSeparateDialog": false, + "openInPopover": false, + "id": "a60e09be-1bea-dfc3-6abb-f87e73256899" + } + ] + } }, - { - "name": "jsExecutionApiState", - "type": "timeseries", - "label": "title", - "color": "#9c27b0", - "settings": {}, - "_hash": 0.7673280949238444, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.scripts}\";", - "aggregationType": "NONE" + "row": 0, + "col": 0, + "id": "aab68ab5-8e40-8694-c55c-8eb1c89b88fb" + }, + "a84fa70a-ddfa-3b24-9aa4-cf9ce91f919a": { + "typeFullFqn": "system.cards.markdown_card", + "type": "latest", + "sizeX": 5, + "sizeY": 3.5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "ruleEngineApiState", + "type": "timeseries", + "label": "apiStatus", + "color": "#2196f3", + "settings": {}, + "_hash": 0.8830669138660703, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value : 'enabled';", + "aggregationType": "NONE" + }, + { + "name": "ruleEngineExecutionLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "ruleEngineExecutionCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "ruleEngineApiState", + "type": "timeseries", + "label": "title", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.3551317421302518, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.rule-engine}\";" + }, + { + "name": "ruleEngineApiState", + "type": "timeseries", + "label": "unit", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.5100381746798048, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.executions}\";" + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "displayValue": "", + "selectedTab": 0, + "realtime": { + "realtimeType": 1, + "interval": 1000, + "timewindowMs": 60000, + "quickInterval": "CURRENT_DAY" + }, + "history": { + "historyType": 0, + "interval": 1000, + "timewindowMs": 60000, + "fixedTimewindow": { + "startTimeMs": 1708518962586, + "endTimeMs": 1708605362586 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "AVG", + "limit": 25000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "useMarkdownTextFunction": true, + "markdownTextPattern": "", + "markdownTextFunction": "function toShortNumber(number) {\n const rounder = Math.pow(10, 1);\n const powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n let key = '';\n for (const power of powers) {\n let reduced = number / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = power.key;\n break;\n }\n }\n \n return number + key;\n}\n\nfunction calculateBarValues(count, limit) {\n let apiUsageBar = '0%';\n let apiUsagePercent = '';\n let apiUsageValue = `${toShortNumber(count)} / ∞`;\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n apiUsageBar = `${percent}%`\n apiUsagePercent = `${percent.toFixed(2)}%`;\n apiUsageValue = `${toShortNumber(count)} / ${toShortNumber(limit)}`;\n }\n \n return [apiUsageBar, apiUsagePercent, apiUsageValue]\n}\n\nconst [apiUsageBar, apiUsagePercent, apiUsageValue] = calculateBarValues(data[0].count, data[0].limit);\n\n\nreturn `
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ${title}
    ' +\n `
    ${data[0].apiStatus.toUpperCase()}
    ` +\n '
    ' +\n '
    ' +\n `
    ${data[0].unit}
    ` +\n '
    ' +\n `
    ` +\n '
    ' +\n '
    ' +\n `
    ${apiUsagePercent}
    ` +\n '
    ' +\n `
    ${apiUsageValue}
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n '' +\n '
    '+\n '' +\n '' +\n '
    ' +\n '
    '\n", + "applyDefaultMarkdownStyle": false, + "markdownCss": "\n" + }, + "title": "Rule Engine execution", + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": {}, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "showLegend": false, + "useDashboardTimewindow": true, + "displayTimewindow": true, + "widgetCss": "", + "pageSize": 1024, + "noDataDisplayMessage": "", + "actions": { + "elementClick": [ + { + "name": "rule_engine_execution_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "rule_engine_execution", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "3c30248f-0cd8-fb97-a917-bc1e09984a79" + }, + { + "name": "rule_engine_statistics_details", + "icon": "show_chart", + "type": "openDashboardState", + "targetDashboardStateId": "rule_engine_statistics", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "04e4565a-9e24-23df-f376-f2ec70a8165f" + } + ] + } }, - { - "name": "jsExecutionApiState", - "type": "timeseries", - "label": "jsUnit", - "color": "#8bc34a", - "settings": {}, - "_hash": 0.7926918686567068, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.javascript}\";", - "aggregationType": "NONE" + "row": 0, + "col": 0, + "id": "a84fa70a-ddfa-3b24-9aa4-cf9ce91f919a" + }, + "d70d26d4-e22d-4ca9-9ea7-f9c87c093321": { + "typeFullFqn": "system.cards.markdown_card", + "type": "latest", + "sizeX": 5, + "sizeY": 3.5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "jsExecutionApiState", + "type": "timeseries", + "label": "jsApiState", + "color": "#2196f3", + "settings": {}, + "_hash": 0.8830669138660703, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value : 'ENABLED';", + "aggregationType": "NONE" + }, + { + "name": "jsExecutionLimit", + "type": "timeseries", + "label": "jsLimit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "jsExecutionCount", + "type": "timeseries", + "label": "jsCount", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "jsExecutionApiState", + "type": "timeseries", + "label": "title", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.7673280949238444, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.scripts}\";", + "aggregationType": "NONE" + }, + { + "name": "jsExecutionApiState", + "type": "timeseries", + "label": "jsUnit", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.7926918686567068, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.javascript}\";", + "aggregationType": "NONE" + }, + { + "name": "tbelExecutionApiState", + "type": "timeseries", + "label": "tbelApiState", + "color": "#3f51b5", + "settings": {}, + "_hash": 0.2002981454581909, + "aggregationType": "NONE", + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value : 'ENABLED';" + }, + { + "name": "tbelExecutionLimit", + "type": "timeseries", + "label": "tbelLimit", + "color": "#ffeb3b", + "settings": {}, + "_hash": 0.5039854873031677, + "aggregationType": "NONE", + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;" + }, + { + "name": "tbelExecutionCount", + "type": "timeseries", + "label": "tbelCount", + "color": "#e91e63", + "settings": {}, + "_hash": 0.9506731992087107, + "aggregationType": "NONE", + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;" + }, + { + "name": "tbelExecutionApiState", + "type": "timeseries", + "label": "tbelUnit", + "color": "#ffeb3b", + "settings": {}, + "_hash": 0.3673530683177082, + "aggregationType": "NONE", + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.tbel}\";" + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "displayValue": "", + "selectedTab": 0, + "realtime": { + "realtimeType": 1, + "interval": 1000, + "timewindowMs": 60000, + "quickInterval": "CURRENT_DAY" + }, + "history": { + "historyType": 0, + "interval": 1000, + "timewindowMs": 60000, + "fixedTimewindow": { + "startTimeMs": 1708518962586, + "endTimeMs": 1708605362586 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "AVG", + "limit": 25000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "useMarkdownTextFunction": true, + "markdownTextPattern": "", + "markdownTextFunction": "function toShortNumber(number) {\n const rounder = Math.pow(10, 1);\n const powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n let key = '';\n for (const power of powers) {\n const reduced = number / power.value;\n for (const power of powers) {\n let reduced = number / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = power.key;\n break;\n }\n }\n }\n \n return number + key;\n}\n\nfunction calculateBarValues(count, limit) {\n let apiUsageBar = '0%';\n let apiUsagePercent = '';\n let apiUsageValue = `${toShortNumber(count)} / ∞`;\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n apiUsageBar = `${percent}%`\n apiUsagePercent = `${percent.toFixed(2)}%`;\n apiUsageValue = `${toShortNumber(count)} / ${toShortNumber(limit)}`;\n }\n \n return [apiUsageBar, apiUsagePercent, apiUsageValue]\n}\n\nconst [jsUsageBar, jsUsagePercent, jsUsageValue] = calculateBarValues(data[0].jsCount, data[0].jsLimit);\nconst [tbelUsageBar, tbelUsagePercent, tbelUsageValue] = calculateBarValues(data[0].tbelCount, data[0].tbelLimit);\n\nconst jsApiState = data[0].jsApiState;\nconst tbelApiState = data[0].tbelApiState;\nlet currentState;\nif (jsApiState === 'DISABLED' || tbelApiState === 'DISABLED') {\n currentState = 'DISABLED';\n} else if (jsApiState === 'WARNING' || tbelApiState === 'WARNING') {\n currentState = 'WARNING';\n} else {\n currentState = 'ENABLED';\n}\nconst cardClass = currentState.toLowerCase()\n\nreturn `
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n `${data[0].title}` +\n '
    ' +\n `
    ${currentState}
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n `
    ${data[0].jsUnit}
    ` +\n '
    ' +\n `
    ` +\n '
    ' +\n '
    ' +\n `
    ${jsUsagePercent}
    ` +\n '
    ' +\n `
    ${jsUsageValue}
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n `
    ${data[0].tbelUnit}
    ` +\n '
    ' +\n `
    ` +\n '
    ' +\n '
    ' +\n `
    ${tbelUsagePercent}
    ` +\n '
    ' +\n `
    ${tbelUsageValue}
    ` +\n '
    ' +\n '
    ' + \n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n '' +\n '
    '+\n '' +\n '
    ' +\n '
    '\n", + "applyDefaultMarkdownStyle": false, + "markdownCss": "\n" + }, + "title": "JavaScript functions", + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": {}, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "showLegend": false, + "useDashboardTimewindow": true, + "displayTimewindow": true, + "widgetCss": "", + "pageSize": 1024, + "noDataDisplayMessage": "", + "actions": { + "elementClick": [ + { + "name": "script_functions_details", + "icon": "insert_chart", + "useShowWidgetActionFunction": null, + "showWidgetActionFunction": "return true;", + "type": "openDashboardState", + "targetDashboardStateId": "script_functions", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "openInSeparateDialog": false, + "openInPopover": false, + "id": "d4961bea-84de-e1af-e50f-666b98d34cd5" + } + ] + } }, - { - "name": "tbelExecutionApiState", - "type": "timeseries", - "label": "tbelApiState", - "color": "#3f51b5", - "settings": {}, - "_hash": 0.2002981454581909, - "aggregationType": "NONE", - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value : 'ENABLED';" + "row": 0, + "col": 0, + "id": "d70d26d4-e22d-4ca9-9ea7-f9c87c093321" + }, + "4d3ea95c-3188-9872-1817-2f989c7729e0": { + "typeFullFqn": "system.cards.markdown_card", + "type": "latest", + "sizeX": 5, + "sizeY": 3.5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "storageDataPointsLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "storageDataPointsCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "dbApiState", + "type": "timeseries", + "label": "apiStatus", + "color": "#ffc107", + "settings": {}, + "_hash": 0.8737107059960671, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value : 'enabled';", + "aggregationType": "NONE" + }, + { + "name": "dbApiState", + "type": "timeseries", + "label": "title", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.6301889725474652, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.telemetry}\";" + }, + { + "name": "dbApiState", + "type": "timeseries", + "label": "unit", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.0027742924142306613, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.data-points-storage-days}\";" + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "displayValue": "", + "selectedTab": 0, + "realtime": { + "realtimeType": 1, + "interval": 1000, + "timewindowMs": 60000, + "quickInterval": "CURRENT_DAY" + }, + "history": { + "historyType": 0, + "interval": 1000, + "timewindowMs": 60000, + "fixedTimewindow": { + "startTimeMs": 1708518962586, + "endTimeMs": 1708605362586 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "AVG", + "limit": 25000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "useMarkdownTextFunction": true, + "markdownTextPattern": "", + "markdownTextFunction": "function toShortNumber(number) {\n const rounder = Math.pow(10, 1);\n const powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n let key = '';\n for (const power of powers) {\n let reduced = number / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = power.key;\n break;\n }\n }\n \n return number + key;\n}\n\nfunction calculateBarValues(count, limit) {\n let apiUsageBar = '0%';\n let apiUsagePercent = '';\n let apiUsageValue = `${toShortNumber(count)} / ∞`;\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n apiUsageBar = `${percent}%`\n apiUsagePercent = `${percent.toFixed(2)}%`;\n apiUsageValue = `${toShortNumber(count)} / ${toShortNumber(limit)}`;\n }\n \n return [apiUsageBar, apiUsagePercent, apiUsageValue]\n}\n\nconst [apiUsageBar, apiUsagePercent, apiUsageValue] = calculateBarValues(data[0].count, data[0].limit);\n\n\nreturn `
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ${title}
    ' +\n `
    ${data[0].apiStatus.toUpperCase()}
    ` +\n '
    ' +\n '
    ' +\n `
    ${data[0].unit}
    ` +\n '
    ' +\n `
    ` +\n '
    ' +\n '
    ' +\n `
    ${apiUsagePercent}
    ` +\n '
    ' +\n `
    ${apiUsageValue}
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n '' +\n '
    '+\n '' +\n '
    ' +\n '
    '\n", + "applyDefaultMarkdownStyle": false, + "markdownCss": "\n" + }, + "title": "Telemetry persistence", + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": {}, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "showLegend": false, + "useDashboardTimewindow": true, + "displayTimewindow": true, + "widgetCss": "", + "pageSize": 1024, + "noDataDisplayMessage": "", + "actions": { + "elementClick": [ + { + "name": "telemetry_persistence_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "telemetry_persistence", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "6248831c-5b3f-8879-8548-afcf43f10610" + } + ] + } }, - { - "name": "tbelExecutionLimit", - "type": "timeseries", - "label": "tbelLimit", - "color": "#ffeb3b", - "settings": {}, - "_hash": 0.5039854873031677, - "aggregationType": "NONE", - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "row": 0, + "col": 0, + "id": "4d3ea95c-3188-9872-1817-2f989c7729e0" + }, + "2d0d6ff6-cd59-51d4-b916-38e22cdd0702": { + "typeFullFqn": "system.cards.markdown_card", + "type": "latest", + "sizeX": 5, + "sizeY": 3.5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "createdAlarmsLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "createdAlarmsCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "alarmApiState", + "type": "timeseries", + "label": "apiStatus", + "color": "#ffc107", + "settings": {}, + "_hash": 0.8737107059960671, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value : 'enabled';", + "aggregationType": "NONE" + }, + { + "name": "alarmApiState", + "type": "timeseries", + "label": "title", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.43439375716502227, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.alarm}\";" + }, + { + "name": "alarmApiState", + "type": "timeseries", + "label": "unit", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.9964061963495883, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.alarms-created}\";" + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "displayValue": "", + "selectedTab": 0, + "realtime": { + "realtimeType": 1, + "interval": 1000, + "timewindowMs": 60000, + "quickInterval": "CURRENT_DAY" + }, + "history": { + "historyType": 0, + "interval": 1000, + "timewindowMs": 60000, + "fixedTimewindow": { + "startTimeMs": 1708518962586, + "endTimeMs": 1708605362586 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "AVG", + "limit": 25000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "useMarkdownTextFunction": true, + "markdownTextPattern": "", + "markdownTextFunction": "function toShortNumber(number) {\n const rounder = Math.pow(10, 1);\n const powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n let key = '';\n for (const power of powers) {\n let reduced = number / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = power.key;\n break;\n }\n }\n \n return number + key;\n}\n\nfunction calculateBarValues(count, limit) {\n let apiUsageBar = '0%';\n let apiUsagePercent = '';\n let apiUsageValue = `${toShortNumber(count)} / ∞`;\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n apiUsageBar = `${percent}%`\n apiUsagePercent = `${percent.toFixed(2)}%`;\n apiUsageValue = `${toShortNumber(count)} / ${toShortNumber(limit)}`;\n }\n \n return [apiUsageBar, apiUsagePercent, apiUsageValue]\n}\n\nconst [apiUsageBar, apiUsagePercent, apiUsageValue] = calculateBarValues(data[0].count, data[0].limit);\n\n\nreturn `
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ${title}
    ' +\n `
    ${data[0].apiStatus.toUpperCase()}
    ` +\n '
    ' +\n '
    ' +\n `
    ${data[0].unit}
    ` +\n '
    ' +\n `
    ` +\n '
    ' +\n '
    ' +\n `
    ${apiUsagePercent}
    ` +\n '
    ' +\n `
    ${apiUsageValue}
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n '' +\n '
    '+\n '' +\n '
    ' +\n '
    '\n", + "applyDefaultMarkdownStyle": false, + "markdownCss": "\n" + }, + "title": "Alarm created", + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": {}, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "showLegend": false, + "useDashboardTimewindow": true, + "displayTimewindow": true, + "widgetCss": "", + "pageSize": 1024, + "noDataDisplayMessage": "", + "actions": { + "elementClick": [ + { + "name": "email_messages_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "alarms_created", + "setEntityId": false, + "stateEntityParamName": null, + "openInSeparateDialog": null, + "dialogTitle": null, + "dialogHideDashboardToolbar": true, + "dialogWidth": null, + "dialogHeight": null, + "openRightLayout": false, + "id": "946ba769-84ac-1507-6baa-94701de8967b" + } + ] + } }, - { - "name": "tbelExecutionCount", - "type": "timeseries", - "label": "tbelCount", - "color": "#e91e63", - "settings": {}, - "_hash": 0.9506731992087107, - "aggregationType": "NONE", - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "row": 0, + "col": 0, + "id": "2d0d6ff6-cd59-51d4-b916-38e22cdd0702" + }, + "120573cc-e246-eb49-7d80-68e5d3b3c0cc": { + "typeFullFqn": "system.cards.markdown_card", + "type": "latest", + "sizeX": 5, + "sizeY": 3.5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "emailApiState", + "type": "timeseries", + "label": "apiState", + "color": "#2196f3", + "settings": {}, + "_hash": 0.8830669138660703, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "emailLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "emailCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "smsApiState", + "type": "timeseries", + "label": "apiStatePoint", + "color": "#e91e63", + "settings": {}, + "_hash": 0.2969682764607864, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "smsLimit", + "type": "timeseries", + "label": "pointsLimit", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.22082255831864894, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "smsCount", + "type": "timeseries", + "label": "pointsCount", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.6340356364819146, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value !== '' ? parseInt(value, 10) : 0;", + "aggregationType": "NONE" + }, + { + "name": "notificationApiState", + "type": "timeseries", + "label": "title", + "color": "#3f51b5", + "settings": {}, + "_hash": 0.6894070537030252, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"{i18n:api-usage.notifications}\";", + "aggregationType": "NONE" + }, + { + "name": "notificationApiState", + "type": "timeseries", + "label": "unit", + "color": "#3f51b5", + "settings": {}, + "_hash": 0.0005447336528170421, + "aggregationType": "NONE", + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return '{i18n:api-usage.email}';" + }, + { + "name": "notificationApiState", + "type": "timeseries", + "label": "pointsUnit", + "color": "#e91e63", + "settings": {}, + "_hash": 0.12117146988088967, + "aggregationType": "NONE", + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return '{i18n:api-usage.sms}';" + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "displayValue": "", + "selectedTab": 0, + "realtime": { + "realtimeType": 1, + "interval": 1000, + "timewindowMs": 60000, + "quickInterval": "CURRENT_DAY" + }, + "history": { + "historyType": 0, + "interval": 1000, + "timewindowMs": 60000, + "fixedTimewindow": { + "startTimeMs": 1708518962586, + "endTimeMs": 1708605362586 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "AVG", + "limit": 25000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "useMarkdownTextFunction": true, + "markdownTextPattern": "", + "markdownTextFunction": "function toShortNumber(number) {\n const rounder = Math.pow(10, 1);\n const powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n ];\n let key = '';\n for (const power of powers) {\n const reduced = number / power.value;\n for (const power of powers) {\n let reduced = number / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n number = reduced;\n key = power.key;\n break;\n }\n }\n }\n \n return number + key;\n}\n\nfunction calculateBarValues(count, limit) {\n let apiUsageBar = '0%';\n let apiUsagePercent = '';\n let apiUsageValue = `${toShortNumber(count)} / ∞`;\n if (Number.isFinite(limit) && limit > 0) {\n var percent = Math.min(100, ((count / limit) * 100));\n apiUsageBar = `${percent}%`\n apiUsagePercent = `${percent.toFixed(2)}%`;\n apiUsageValue = `${toShortNumber(count)} / ${toShortNumber(limit)}`;\n }\n \n return [apiUsageBar, apiUsagePercent, apiUsageValue]\n}\n\nconst [apiUsageBar, apiUsagePercent, apiUsageValue] = calculateBarValues(data[0].count, data[0].limit);\nconst [apiUsageBar2, apiUsagePercent2, apiUsageValue2] = calculateBarValues(data[0].pointsCount, data[0].pointsLimit);\n\nconst apiState = data[0].apiState;\nconst apiStatePoint = data[0].apiStatePoint;\nlet currentState;\nif (apiState === 'DISABLED' || apiStatePoint === 'DISABLED') {\n currentState = 'DISABLED';\n} else if (apiState === 'WARNING' || apiStatePoint === 'WARNING') {\n currentState = 'WARNING';\n} else {\n currentState = 'ENABLED';\n}\n\n\n\nreturn `
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n `${data[0].title}` +\n '
    ' +\n `
    ${currentState}
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n `
    ${data[0].unit}
    ` +\n '
    ' +\n `
    ` +\n '
    ' +\n '
    ' +\n `
    ${apiUsagePercent}
    ` +\n '
    ' +\n `
    ${apiUsageValue}
    ` +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n `
    ${data[0].pointsUnit}
    ` +\n '
    ' +\n `
    ` +\n '
    ' +\n '
    ' +\n `
    ${apiUsagePercent2}
    ` +\n '
    ' +\n `
    ${apiUsageValue2}
    ` +\n '
    ' +\n '
    ' + \n '
    ' +\n '
    ' +\n '
    ' +\n '
    ' +\n '' +\n '
    '+\n '' +\n '
    ' +\n '
    '\n", + "applyDefaultMarkdownStyle": false, + "markdownCss": "\n" + }, + "title": "Notifications (Email/SMS)", + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": {}, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "showLegend": false, + "useDashboardTimewindow": true, + "displayTimewindow": true, + "widgetCss": "", + "pageSize": 1024, + "noDataDisplayMessage": "", + "actions": { + "elementClick": [ + { + "name": "transport_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "notifications", + "setEntityId": false, + "stateEntityParamName": null, + "openInSeparateDialog": null, + "dialogTitle": null, + "dialogHideDashboardToolbar": true, + "dialogWidth": null, + "dialogHeight": null, + "openRightLayout": false, + "id": "46b7cefe-e1f2-67c1-4055-3a214520f869" + } + ] + } }, - { - "name": "tbelExecutionApiState", - "type": "timeseries", - "label": "tbelUnit", - "color": "#ffeb3b", - "settings": {}, - "_hash": 0.3673530683177082, - "aggregationType": "NONE", - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.tbel}\";" - } - ] - } - ], - "timewindow": { - "displayValue": "", - "selectedTab": 0, - "realtime": { - "realtimeType": 1, - "interval": 1000, - "timewindowMs": 60000, - "quickInterval": "CURRENT_DAY" - }, - "history": { - "historyType": 0, - "interval": 1000, - "timewindowMs": 60000, - "fixedTimewindow": { - "startTimeMs": 1694083375825, - "endTimeMs": 1694169775825 - }, - "quickInterval": "CURRENT_DAY" + "row": 0, + "col": 0, + "id": "120573cc-e246-eb49-7d80-68e5d3b3c0cc" }, - "aggregation": { - "type": "AVG", - "limit": 25000 - } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "#666666", - "padding": "0", - "settings": { - "cardHtml": "
    \n \n \n
    \n
    \n
    \n
    ${title}
    \n
    \n
    \n
    \n
    \n
    \n
    ${jsUnit}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    ${tbelUnit}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    ", - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 6px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} " - }, - "title": "JavaScript functions", - "dropShadow": true, - "enableFullscreen": false, - "widgetStyle": { - "cursor": "default" - }, - "titleStyle": { - "fontSize": "20px", - "fontWeight": 400 - }, - "useDashboardTimewindow": true, - "showLegend": false, - "actions": { - "elementClick": [ - { - "name": "script_functions_details", - "icon": "insert_chart", - "useShowWidgetActionFunction": null, - "showWidgetActionFunction": "return true;", - "type": "openDashboardState", - "targetDashboardStateId": "script_functions", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "openInSeparateDialog": false, - "openInPopover": false, - "id": "d4961bea-84de-e1af-e50f-666b98d34cd5" - } - ] - }, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "displayTimewindow": true - }, - "row": 0, - "col": 0, - "id": "fd6df872-2ddf-0921-3929-2e7f55062fad", - "typeFullFqn": "system.cards.html_value_card" - }, - "7e235874-461b-e7c2-2fdd-d8762a020773": { - "type": "latest", - "sizeX": 7.5, - "sizeY": 3, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "dbApiState", - "type": "timeseries", - "label": "apiState", - "color": "#2196f3", - "settings": {}, - "_hash": 0.8830669138660703, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value : 'ENABLED';" - }, - { - "name": "storageDataPointsLimit", - "type": "timeseries", - "label": "limit", - "color": "#4caf50", - "settings": {}, - "_hash": 0.5463603803546802, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "storageDataPointsCount", - "type": "timeseries", - "label": "count", - "color": "#f44336", - "settings": {}, - "_hash": 0.5564241862015964, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "dbApiState", - "type": "timeseries", - "label": "apiStateClass", - "color": "#ffc107", - "settings": {}, - "_hash": 0.8737107059960671, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value.toLowerCase() : 'enabled';" - }, - { - "name": "dbApiState", - "type": "timeseries", - "label": "cardId", - "color": "#607d8b", - "settings": {}, - "_hash": 0.051659774305067296, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return (Math.random()*100000).toFixed(0);" - }, - { - "name": "dbApiState", - "type": "timeseries", - "label": "title", - "color": "#9c27b0", - "settings": {}, - "_hash": 0.6301889725474652, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.telemetry}\";" + "63f99d90-23ab-f8c2-3290-1e693ded5a2e": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "transportMsgCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.transport-messages}", + "color": "#2196f3", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": false, + "postFuncBody": null, + "aggregationType": null + }, + { + "name": "transportDataPointsCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.transport-data-points}", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.46849996721308895, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "timewindowMs": 86400000, + "quickInterval": "CURRENT_DAY", + "interval": 300000 + }, + "aggregation": { + "type": "NONE", + "limit": 50000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 2400000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.transport-hourly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": { + "headerButton": [ + { + "name": "{i18n:api-usage.view-details}", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "transport", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "6ef12f6a-0266-25cf-6ca5-5dcb772252c6" + } + ] + }, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "dbApiState", - "type": "timeseries", - "label": "unit", - "color": "#8bc34a", - "settings": {}, - "_hash": 0.0027742924142306613, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.data-points-storage-days}\";" - } - ] - } - ], - "timewindow": { - "displayValue": "", - "selectedTab": 0, - "realtime": { - "realtimeType": 1, - "interval": 1000, - "timewindowMs": 60000, - "quickInterval": "CURRENT_DAY" - }, - "history": { - "historyType": 0, - "interval": 1000, - "timewindowMs": 60000, - "fixedTimewindow": { - "startTimeMs": 1694083375826, - "endTimeMs": 1694169775826 - }, - "quickInterval": "CURRENT_DAY" + "row": 0, + "col": 0, + "id": "63f99d90-23ab-f8c2-3290-1e693ded5a2e" }, - "aggregation": { - "type": "AVG", - "limit": 25000 - } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "#666666", - "padding": "0", - "settings": { - "cardHtml": "
    \n \n \n
    \n
    \n
    \n
    ${title}
    \n
    ${apiState}
    \n
    \n
    \n
    ${unit}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    ", - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n" - }, - "title": "Telemetry persistence", - "dropShadow": true, - "enableFullscreen": false, - "widgetStyle": { - "cursor": "default" - }, - "titleStyle": { - "fontSize": "20px", - "fontWeight": 400 - }, - "useDashboardTimewindow": true, - "showLegend": false, - "actions": { - "elementClick": [ - { - "name": "telemetry_persistence_details", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "telemetry_persistence", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "id": "6248831c-5b3f-8879-8548-afcf43f10610" - } - ] - }, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "7e235874-461b-e7c2-2fdd-d8762a020773", - "typeFullFqn": "system.cards.html_value_card" - }, - "08545554-a0e8-05c7-66df-6000cfeff8a4": { - "type": "latest", - "sizeX": 7.5, - "sizeY": 3, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "ruleEngineApiState", - "type": "timeseries", - "label": "apiState", - "color": "#2196f3", - "settings": {}, - "_hash": 0.8830669138660703, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value : 'ENABLED';" - }, - { - "name": "ruleEngineExecutionLimit", - "type": "timeseries", - "label": "limit", - "color": "#4caf50", - "settings": {}, - "_hash": 0.5463603803546802, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "ruleEngineExecutionCount", - "type": "timeseries", - "label": "count", - "color": "#f44336", - "settings": {}, - "_hash": 0.5564241862015964, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "a2b7e906-2d8a-41a8-99a6-409531bfa743": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "ruleEngineExecutionCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.rule-engine-executions}", + "color": "#ab00ff", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "bar", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "emptyCircle", + "pointSize": 4, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null, + "aggregationType": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "timewindowMs": 86400000, + "quickInterval": "CURRENT_YEAR", + "interval": 7200000 + }, + "aggregation": { + "type": "NONE", + "limit": 50000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 2400000, + "separateBarWidth": 2400000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.rule-engine-hourly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": { + "headerButton": [ + { + "name": "{i18n:api-usage.view-statistics}", + "icon": "show_chart", + "type": "openDashboardState", + "targetDashboardStateId": "rule_engine_statistics", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "f9f08190-9ed9-d802-5b7a-c57ff84b5648" + }, + { + "name": "{i18n:api-usage.view-details}", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "rule_engine_execution", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "1aec196b-44ba-ddf4-c4dc-c3f60c1eb6fc" + } + ] + }, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "ruleEngineApiState", - "type": "timeseries", - "label": "apiStateClass", - "color": "#ffc107", - "settings": {}, - "_hash": 0.8737107059960671, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value.toLowerCase() : 'enabled';" + "row": 0, + "col": 0, + "id": "a2b7e906-2d8a-41a8-99a6-409531bfa743" + }, + "ca996b66-ab7e-f977-152c-98e4ebf2a901": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "jsExecutionCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.javascript-executions}", + "color": "#ff9900", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "bar", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "emptyCircle", + "pointSize": 4, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null, + "aggregationType": null + }, + { + "name": "tbelExecutionCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.tbel-executions}", + "color": "#4caf50", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "bar", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "emptyCircle", + "pointSize": 4, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.6818645685001823, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "timewindowMs": 86400000, + "quickInterval": "CURRENT_DAY", + "interval": 300000 + }, + "aggregation": { + "type": "NONE", + "limit": 50000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 2400000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.scripts-hourly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": { + "headerButton": [ + { + "name": "{i18n:api-usage.view-details}", + "icon": "insert_chart", + "useShowWidgetActionFunction": null, + "showWidgetActionFunction": "return true;", + "type": "openDashboardState", + "targetDashboardStateId": "script_functions", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "openInSeparateDialog": false, + "openInPopover": false, + "id": "4687d3f6-8800-a3b6-26e5-0d33f3b828a9" + } + ] + }, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "ruleEngineApiState", - "type": "timeseries", - "label": "cardId", - "color": "#607d8b", - "settings": {}, - "_hash": 0.051659774305067296, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return (Math.random()*100000).toFixed(0);" + "row": 0, + "col": 0, + "id": "ca996b66-ab7e-f977-152c-98e4ebf2a901" + }, + "a3c2f1bb-7d3a-f11c-7b3d-28cd84fdfe34": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "storageDataPointsCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.data-points-storage-days}", + "color": "#1039ee", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "bar", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "emptyCircle", + "pointSize": 4, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null, + "aggregationType": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "timewindowMs": 86400000, + "quickInterval": "CURRENT_DAY", + "interval": 300000 + }, + "aggregation": { + "type": "NONE", + "limit": 50000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 2400000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.telemetry-persistence-hourly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": { + "headerButton": [ + { + "name": "{i18n:api-usage.view-details}", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "telemetry_persistence", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "16707efb-e572-bd02-c219-55fc1b0f672a" + } + ] + }, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "ruleEngineApiState", - "type": "timeseries", - "label": "title", - "color": "#9c27b0", - "settings": {}, - "_hash": 0.3551317421302518, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.rule-engine}\";" + "row": 0, + "col": 0, + "id": "a3c2f1bb-7d3a-f11c-7b3d-28cd84fdfe34" + }, + "5cebd4f1-ff6e-62f9-025c-8e7583c3d66a": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "createdAlarmsCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.alarms-created}", + "color": "#d35a00", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "bar", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "emptyCircle", + "pointSize": 4, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null, + "aggregationType": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "timewindowMs": 86400000, + "quickInterval": "CURRENT_DAY", + "interval": 300000 + }, + "aggregation": { + "type": "NONE", + "limit": 50000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 2400000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.alarms-created-hourly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": { + "headerButton": [ + { + "name": "{i18n:api-usage.view-details}", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "alarms_created", + "setEntityId": false, + "stateEntityParamName": null, + "openInSeparateDialog": null, + "dialogTitle": null, + "dialogHideDashboardToolbar": true, + "dialogWidth": null, + "dialogHeight": null, + "openRightLayout": false, + "id": "371882f9-ea23-3abc-fca8-9449c5dfdd6b" + } + ] + }, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "ruleEngineApiState", - "type": "timeseries", - "label": "unit", - "color": "#8bc34a", - "settings": {}, - "_hash": 0.5100381746798048, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.executions}\";" - } - ] - } - ], - "timewindow": { - "displayValue": "", - "selectedTab": 0, - "realtime": { - "realtimeType": 1, - "interval": 1000, - "timewindowMs": 60000, - "quickInterval": "CURRENT_DAY" + "row": 0, + "col": 0, + "id": "5cebd4f1-ff6e-62f9-025c-8e7583c3d66a" }, - "history": { - "historyType": 0, - "interval": 1000, - "timewindowMs": 60000, - "fixedTimewindow": { - "startTimeMs": 1694083375826, - "endTimeMs": 1694169775826 - }, - "quickInterval": "CURRENT_DAY" + "bc0c8840-a9b5-5583-de7b-9e9450f5d8fe": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "emailCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.email-messages}", + "color": "#4caf50", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "bar", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "emptyCircle", + "pointSize": 4, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.1348755140779876, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null, + "aggregationType": null + }, + { + "name": "smsCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.sms-messages}", + "color": "#f36021", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "bar", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "emptyCircle", + "pointSize": 4, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null, + "aggregationType": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "timewindowMs": 86400000, + "quickInterval": "CURRENT_DAY", + "interval": 300000 + }, + "aggregation": { + "type": "NONE", + "limit": 50000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 2400000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.notifications-hourly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": { + "headerButton": [ + { + "name": "{i18n:api-usage.view-details}", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "notifications", + "setEntityId": false, + "stateEntityParamName": null, + "openInSeparateDialog": null, + "dialogTitle": null, + "dialogHideDashboardToolbar": true, + "dialogWidth": null, + "dialogHeight": null, + "openRightLayout": false, + "id": "49aefac0-ec5e-d6f3-f39c-8744759f4b19" + } + ] + }, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "bc0c8840-a9b5-5583-de7b-9e9450f5d8fe" }, - "aggregation": { - "type": "AVG", - "limit": 25000 - } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "#666666", - "padding": "0", - "settings": { - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n", - "cardHtml": "
    \n \n \n
    \n
    \n
    \n
    ${title}
    \n
    ${apiState}
    \n
    \n
    \n
    ${unit}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n \n \n
    \n
    " - }, - "title": "Rule Engine execution", - "dropShadow": true, - "enableFullscreen": false, - "widgetStyle": { - "cursor": "default" - }, - "titleStyle": { - "fontSize": "20px", - "fontWeight": 400 - }, - "useDashboardTimewindow": true, - "showLegend": false, - "actions": { - "elementClick": [ - { - "name": "rule_engine_execution_details", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "rule_engine_execution", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "id": "3c30248f-0cd8-fb97-a917-bc1e09984a79" - }, - { - "name": "rule_engine_statistics_details", - "icon": "show_chart", - "type": "openDashboardState", - "targetDashboardStateId": "rule_engine_statistics", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "id": "04e4565a-9e24-23df-f376-f2ec70a8165f" - } - ] - }, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "08545554-a0e8-05c7-66df-6000cfeff8a4", - "typeFullFqn": "system.cards.html_value_card" - }, - "a245c67e-53ec-d299-fa89-69fe2062ccb2": { - "type": "latest", - "sizeX": 7.5, - "sizeY": 3, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "transportApiState", - "type": "timeseries", - "label": "apiState", - "color": "#2196f3", - "settings": {}, - "_hash": 0.8830669138660703, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value : 'ENABLED';" + "0b091dc3-eec3-847e-d0ad-fdf12d474e7a": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "transportMsgCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.transport-messages}", + "color": "#2196f3", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "transportDataPointsCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.transport-data-points}", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.46849996721308895, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000, + "fixedTimewindow": { + "startTimeMs": 1709729389667, + "endTimeMs": 1709815789667 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "SUM", + "limit": 25000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.transport-daily-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "transportMsgLimit", - "type": "timeseries", - "label": "limit", - "color": "#4caf50", - "settings": {}, - "_hash": 0.5463603803546802, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "row": 0, + "col": 0, + "id": "0b091dc3-eec3-847e-d0ad-fdf12d474e7a" + }, + "536d7104-49f8-fde6-5827-61b8419f15ec": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "transportMsgCount", + "type": "timeseries", + "label": "{i18n:api-usage.transport-messages}", + "color": "#2196f3", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null, + "aggregationType": null + }, + { + "name": "transportDataPointsCount", + "type": "timeseries", + "label": "{i18n:api-usage.transport-data-points}", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.46849996721308895, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null, + "aggregationType": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 86400000, + "fixedTimewindow": { + "startTimeMs": 1709729389667, + "endTimeMs": 1709815789667 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.transport-daily-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "transportMsgCount", - "type": "timeseries", - "label": "count", - "color": "#f44336", - "settings": {}, - "_hash": 0.5564241862015964, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "row": 0, + "col": 0, + "id": "536d7104-49f8-fde6-5827-61b8419f15ec" + }, + "c77e417c-ad9d-8e23-3ea1-c75edd653bc0": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "ruleEngineExecutionCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.rule-engine-executions}", + "color": "#ab00ff", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000, + "fixedTimewindow": { + "startTimeMs": 1709729900300, + "endTimeMs": 1709816300300 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "SUM", + "limit": 25000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.rule-engine-daily-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "transportApiState", - "type": "timeseries", - "label": "apiStateClass", - "color": "#ffc107", - "settings": {}, - "_hash": 0.8737107059960671, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value.toLowerCase() : 'enabled';" + "row": 0, + "col": 0, + "id": "c77e417c-ad9d-8e23-3ea1-c75edd653bc0" + }, + "870904d2-d2e1-a1b9-ce56-b03fd47259b5": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "ruleEngineExecutionCount", + "type": "timeseries", + "label": "{i18n:api-usage.rule-engine-executions}", + "color": "#ab00ff", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 900000000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.rule-engine-monthly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "transportApiState", - "type": "timeseries", - "label": "cardId", - "color": "#607d8b", - "settings": {}, - "_hash": 0.051659774305067296, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return (Math.random()*100000).toFixed(0);" + "row": 0, + "col": 0, + "id": "870904d2-d2e1-a1b9-ce56-b03fd47259b5" + }, + "c66e5060-57fd-11e7-6616-65b82c294ac2": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "jsExecutionCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.javascript-executions}", + "color": "#ff9900", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "tbelExecutionCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.tbel-executions}", + "color": "#4caf50", + "settings": { + "type": "bar" + }, + "_hash": 0.5212969314724616, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.scripts-daily-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "transportDataPointsLimit", - "type": "timeseries", - "label": "pointsLimit", - "color": "#9c27b0", - "settings": {}, - "_hash": 0.22082255831864894, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "row": 0, + "col": 0, + "id": "c66e5060-57fd-11e7-6616-65b82c294ac2" + }, + "d0e8603e-5d2e-9287-e2c6-8ccbe9c66806": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "jsExecutionCount", + "type": "timeseries", + "label": "{i18n:api-usage.javascript-executions}", + "color": "#ff9900", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "tbelExecutionCount", + "type": "timeseries", + "label": "{i18n:api-usage.tbel-executions}", + "color": "#4caf50", + "settings": { + "type": "bar" + }, + "_hash": 0.49748239768082403, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 900000000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.scripts-monthly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "transportDataPointsCount", - "type": "timeseries", - "label": "pointsCount", - "color": "#8bc34a", - "settings": {}, - "_hash": 0.6340356364819146, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "row": 0, + "col": 0, + "id": "d0e8603e-5d2e-9287-e2c6-8ccbe9c66806" + }, + "7f4100d2-41be-4954-d353-1d45000dbbbb": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "storageDataPointsCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.data-points-storage-days}", + "color": "#1039ee", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.telemetry-persistence-daily-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "transportApiState", - "type": "timeseries", - "label": "title", - "color": "#3f51b5", - "settings": {}, - "_hash": 0.6894070537030252, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.transport}\";" - } - ] - } - ], - "timewindow": { - "displayValue": "", - "selectedTab": 0, - "realtime": { - "realtimeType": 1, - "interval": 1000, - "timewindowMs": 60000, - "quickInterval": "CURRENT_DAY" + "row": 0, + "col": 0, + "id": "7f4100d2-41be-4954-d353-1d45000dbbbb" }, - "history": { - "historyType": 0, - "interval": 1000, - "timewindowMs": 60000, - "fixedTimewindow": { - "startTimeMs": 1694083375826, - "endTimeMs": 1694169775826 - }, - "quickInterval": "CURRENT_DAY" + "226ef8c9-8488-3664-21ac-0b6217336202": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "storageDataPointsCount", + "type": "timeseries", + "label": "{i18n:api-usage.data-points-storage-days}", + "color": "#1039ee", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 900000000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.telemetry-persistence-monthly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "226ef8c9-8488-3664-21ac-0b6217336202" }, - "aggregation": { - "type": "AVG", - "limit": 25000 - } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "#666666", - "padding": "0", - "settings": { - "cardHtml": "
    \n \n \n
    \n
    \n
    \n
    \n ${title}\n
    \n
    ${apiState}
    \n
    \n
    \n
    \n
    \n
    {i18n:api-usage.messages}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    {i18n:api-usage.data-points}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    ", - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 6px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n" - }, - "title": "Transport", - "dropShadow": true, - "enableFullscreen": false, - "widgetStyle": { - "cursor": "default" - }, - "titleStyle": { - "fontSize": "20px", - "fontWeight": 400 - }, - "useDashboardTimewindow": true, - "showLegend": false, - "actions": { - "elementClick": [ - { - "name": "transport_details", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "transport", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "id": "46b7cefe-e1f2-67c1-4055-3a214520f869" - } - ] - }, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "a245c67e-53ec-d299-fa89-69fe2062ccb2", - "typeFullFqn": "system.cards.html_value_card" - }, - "a151ae60-0326-6116-d818-9070dda8e9c7": { - "type": "latest", - "sizeX": 7.5, - "sizeY": 3, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "alarmApiState", - "type": "timeseries", - "label": "apiState", - "color": "#2196f3", - "settings": {}, - "_hash": 0.8830669138660703, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value : 'ENABLED';" + "bef6c27b-9fe7-ee92-40d9-9696c501a1f9": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "createdAlarmsCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.alarms-created}", + "color": "#d35a00", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.alarms-created-daily-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "createdAlarmsLimit", - "type": "timeseries", - "label": "limit", - "color": "#4caf50", - "settings": {}, - "_hash": 0.5463603803546802, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "row": 0, + "col": 0, + "id": "bef6c27b-9fe7-ee92-40d9-9696c501a1f9" + }, + "52305cf8-2258-5745-a0e7-41a171594bb3": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "createdAlarmsCount", + "type": "timeseries", + "label": "{i18n:api-usage.alarms-created}", + "color": "#d35a00", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 900000000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.alarms-created-monthly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "createdAlarmsCount", - "type": "timeseries", - "label": "count", - "color": "#f44336", - "settings": {}, - "_hash": 0.5564241862015964, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "row": 0, + "col": 0, + "id": "52305cf8-2258-5745-a0e7-41a171594bb3" + }, + "36fdf999-ca22-9a4c-269d-3f004d792792": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "emailCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.email-messages}", + "color": "#d35a00", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.email-messages-daily-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "alarmApiState", - "type": "timeseries", - "label": "apiStateClass", - "color": "#ffc107", - "settings": {}, - "_hash": 0.8737107059960671, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return value ? value.toLowerCase() : 'enabled';" + "row": 0, + "col": 0, + "id": "36fdf999-ca22-9a4c-269d-3f004d792792" + }, + "9a191755-499d-535e-86c5-061102729c02": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "smsCountHourly", + "type": "timeseries", + "label": "{i18n:api-usage.sms-messages}", + "color": "#f36021", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.sms-messages-daily-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "alarmApiState", - "type": "timeseries", - "label": "cardId", - "color": "#607d8b", - "settings": {}, - "_hash": 0.051659774305067296, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return (Math.random()*100000).toFixed(0);" + "row": 0, + "col": 0, + "id": "9a191755-499d-535e-86c5-061102729c02" + }, + "4b266318-8357-33ef-ca5a-74cbf90e014f": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "emailCount", + "type": "timeseries", + "label": "{i18n:api-usage.email-messages}", + "color": "#d35a00", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 900000000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.email-messages-monthly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "alarmApiState", - "type": "timeseries", - "label": "title", - "color": "#9c27b0", - "settings": {}, - "_hash": 0.43439375716502227, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.alarm}\";" + "row": 0, + "col": 0, + "id": "4b266318-8357-33ef-ca5a-74cbf90e014f" + }, + "5aa33b0b-3bd5-7fe7-ee72-f564c2ca79d8": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "smsCount", + "type": "timeseries", + "label": "{i18n:api-usage.sms-messages}", + "color": "#f36021", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + }, + "type": "bar" + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 900000000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.sms-messages-monthly-activity}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - { - "name": "alarmApiState", - "type": "timeseries", - "label": "unit", - "color": "#8bc34a", - "settings": {}, - "_hash": 0.9964061963495883, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.alarms-created}\";" - } - ] - } - ], - "timewindow": { - "displayValue": "", - "selectedTab": 0, - "realtime": { - "realtimeType": 1, - "interval": 1000, - "timewindowMs": 60000, - "quickInterval": "CURRENT_DAY" + "row": 0, + "col": 0, + "id": "5aa33b0b-3bd5-7fe7-ee72-f564c2ca79d8" }, - "history": { - "historyType": 0, - "interval": 1000, - "timewindowMs": 60000, - "fixedTimewindow": { - "startTimeMs": 1694083375826, - "endTimeMs": 1694169775826 - }, - "quickInterval": "CURRENT_DAY" + "fa938580-33db-f1b3-fafc-bc3e3784ad57": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "entityAliasId": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f", + "dataKeys": [ + { + "name": "successfulMsgs", + "type": "timeseries", + "label": "{i18n:api-usage.successful}", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.15490750967648736, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "failedMsgs", + "type": "timeseries", + "label": "{i18n:api-usage.permanent-failures}", + "color": "#ef5350", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.4186621166514697 + }, + { + "name": "tmpFailed", + "type": "timeseries", + "label": "{i18n:api-usage.processing-failures}", + "color": "#ffc107", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.49891007198715376 + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 3600000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 10000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "position": "bottom", + "sortDataKeys": false, + "showMin": true, + "showMax": true, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.queue-stats}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "fa938580-33db-f1b3-fafc-bc3e3784ad57" }, - "aggregation": { - "type": "AVG", - "limit": 25000 + "2ee89893-4e38-5331-95b7-3fd4f310c5a7": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "entityAliasId": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f", + "dataKeys": [ + { + "name": "timeoutMsgs", + "type": "timeseries", + "label": "{i18n:api-usage.permanent-timeouts}", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.565222981550328 + }, + { + "name": "tmpTimeout", + "type": "timeseries", + "label": "{i18n:api-usage.processing-timeouts}", + "color": "#9c27b0", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.2679547062508352 + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 3600000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 10000 + } + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupIntervalWidth": 1800000, + "separateBarWidth": 1000 + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "position": "bottom", + "sortDataKeys": false, + "showMin": true, + "showMax": true, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "{i18n:api-usage.processing-failures-and-timeouts}", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "2ee89893-4e38-5331-95b7-3fd4f310c5a7" } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "#666666", - "padding": "0", - "settings": { - "cardHtml": "
    \n \n \n
    \n
    \n
    \n
    ${title}
    \n
    ${apiState}
    \n
    \n
    \n
    ${unit}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    ", - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n" - }, - "title": "Alarm created", - "dropShadow": true, - "enableFullscreen": false, - "widgetStyle": { - "cursor": "default" - }, - "titleStyle": { - "fontSize": "20px", - "fontWeight": 400 - }, - "useDashboardTimewindow": true, - "showLegend": false, - "actions": { - "elementClick": [ - { - "name": "email_messages_details", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "alarms_created", - "setEntityId": false, - "stateEntityParamName": null, - "openInSeparateDialog": null, - "dialogTitle": null, - "dialogHideDashboardToolbar": true, - "dialogWidth": null, - "dialogHeight": null, - "openRightLayout": false, - "id": "946ba769-84ac-1507-6baa-94701de8967b" - } - ] - }, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" }, - "row": 0, - "col": 0, - "id": "a151ae60-0326-6116-d818-9070dda8e9c7", - "typeFullFqn": "system.cards.html_value_card" - }, - "68e16e98-0420-f72c-4848-41dedffd3904": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "ruleEngineExecutionCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.rule-engine-executions}", - "color": "#ab00ff", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true + "states": { + "default": { + "name": "{i18n:api-usage.api-usage}", + "root": true, + "layouts": { + "main": { + "widgets": { + "aab68ab5-8e40-8694-c55c-8eb1c89b88fb": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 0 + }, + "a84fa70a-ddfa-3b24-9aa4-cf9ce91f919a": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 4 + }, + "d70d26d4-e22d-4ca9-9ea7-f9c87c093321": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 8 + }, + "4d3ea95c-3188-9872-1817-2f989c7729e0": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 12 + }, + "2d0d6ff6-cd59-51d4-b916-38e22cdd0702": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 16 + }, + "120573cc-e246-eb49-7d80-68e5d3b3c0cc": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 20 + }, + "63f99d90-23ab-f8c2-3290-1e693ded5a2e": { + "sizeX": 8, + "sizeY": 4, + "row": 2, + "col": 0 + }, + "a2b7e906-2d8a-41a8-99a6-409531bfa743": { + "sizeX": 8, + "sizeY": 4, + "row": 2, + "col": 8 + }, + "ca996b66-ab7e-f977-152c-98e4ebf2a901": { + "sizeX": 8, + "sizeY": 4, + "row": 2, + "col": 16 + }, + "a3c2f1bb-7d3a-f11c-7b3d-28cd84fdfe34": { + "sizeX": 8, + "sizeY": 4, + "row": 6, + "col": 0 + }, + "5cebd4f1-ff6e-62f9-025c-8e7583c3d66a": { + "sizeX": 8, + "sizeY": 4, + "row": 6, + "col": 8 + }, + "bc0c8840-a9b5-5583-de7b-9e9450f5d8fe": { + "sizeX": 8, + "sizeY": 4, + "row": 6, + "col": 16 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 5, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70, + "outerMargin": true + } } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 0, - "realtime": { - "timewindowMs": 86400000, - "interval": 3600000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", - "min": 0, - "tickDecimals": 0 - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 2400000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.rule-engine-hourly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": { - "headerButton": [ - { - "name": "{i18n:api-usage.view-statistics}", - "icon": "show_chart", - "type": "openDashboardState", - "targetDashboardStateId": "rule_engine_statistics", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "id": "f9f08190-9ed9-d802-5b7a-c57ff84b5648" - }, - { - "name": "{i18n:api-usage.view-details}", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "rule_engine_execution", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "id": "1aec196b-44ba-ddf4-c4dc-c3f60c1eb6fc" - } - ] - }, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "68e16e98-0420-f72c-4848-41dedffd3904", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "2aa6b499-6e27-b315-6833-89c4d58485ce": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "transportMsgCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.transport-messages}", - "color": "#2196f3", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "transportDataPointsCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.transport-data-points}", - "color": "#4caf50", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true + "transport": { + "name": "{i18n:api-usage.transport}", + "root": false, + "layouts": { + "main": { + "widgets": { + "0b091dc3-eec3-847e-d0ad-fdf12d474e7a": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "536d7104-49f8-fde6-5827-61b8419f15ec": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70, + "outerMargin": true + } } - }, - "_hash": 0.46849996721308895, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 0, - "realtime": { - "timewindowMs": 86400000, - "interval": 3600000 }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" + "rule_engine_execution": { + "name": "{i18n:api-usage.rule-engine-executions}", + "root": false, + "layouts": { + "main": { + "widgets": { + "c77e417c-ad9d-8e23-3ea1-c75edd653bc0": { + "sizeX": 25, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "870904d2-d2e1-a1b9-ce56-b03fd47259b5": { + "sizeX": 25, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70, + "outerMargin": true + } + } + } }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", - "min": 0, - "tickDecimals": 0 + "telemetry_persistence": { + "name": "{i18n:api-usage.telemetry-persistence}", + "root": false, + "layouts": { + "main": { + "widgets": { + "7f4100d2-41be-4954-d353-1d45000dbbbb": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "226ef8c9-8488-3664-21ac-0b6217336202": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70, + "outerMargin": true + } + } + } }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 + "rule_engine_statistics": { + "name": "{i18n:api-usage.rule-engine-statistics}", + "root": false, + "layouts": { + "main": { + "widgets": { + "a669cf86-e715-efa4-dd9a-b839abf499e9": { + "sizeX": 24, + "sizeY": 5, + "row": 7, + "col": 0 + }, + "fa938580-33db-f1b3-fafc-bc3e3784ad57": { + "sizeX": 12, + "sizeY": 7, + "row": 0, + "col": 0 + }, + "2ee89893-4e38-5331-95b7-3fd4f310c5a7": { + "sizeX": 12, + "sizeY": 7, + "row": 0, + "col": 12 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70, + "outerMargin": true + } + } + } }, - "stack": true, - "tooltipIndividual": false, - "defaultBarWidth": 2400000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true + "notifications": { + "name": "{i18n:api-usage.notifications-email-sms}", + "root": false, + "layouts": { + "main": { + "widgets": { + "36fdf999-ca22-9a4c-269d-3f004d792792": { + "sizeX": 12, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "9a191755-499d-535e-86c5-061102729c02": { + "sizeX": 12, + "sizeY": 6, + "row": 0, + "col": 12 + }, + "4b266318-8357-33ef-ca5a-74cbf90e014f": { + "sizeX": 12, + "sizeY": 6, + "row": 6, + "col": 0 + }, + "5aa33b0b-3bd5-7fe7-ee72-f564c2ca79d8": { + "sizeX": 12, + "sizeY": 6, + "row": 6, + "col": 12 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70, + "outerMargin": true + } + } + } }, - "tooltipCumulative": false, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.transport-hourly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": { - "headerButton": [ - { - "name": "{i18n:api-usage.view-details}", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "transport", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "id": "6ef12f6a-0266-25cf-6ca5-5dcb772252c6" - } - ] - }, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "2aa6b499-6e27-b315-6833-89c4d58485ce", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "d890cea3-fba0-6474-9a21-fa780230dc62": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "jsExecutionCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.javascript-executions}", - "color": "#ff9900", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true + "alarms_created": { + "name": "{i18n:api-usage.alarms-created}", + "root": false, + "layouts": { + "main": { + "widgets": { + "bef6c27b-9fe7-ee92-40d9-9696c501a1f9": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "52305cf8-2258-5745-a0e7-41a171594bb3": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70, + "outerMargin": true + } } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "tbelExecutionCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.tbel-executions}", - "color": "#4caf50", - "settings": {}, - "_hash": 0.6818645685001823, - "aggregationType": null, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 0, - "realtime": { - "timewindowMs": 86400000, - "interval": 3600000 }, - "aggregation": { - "type": "NONE", - "limit": 1000 + "script_functions": { + "name": "{i18n:api-usage.scripts}", + "root": false, + "layouts": { + "main": { + "widgets": { + "c66e5060-57fd-11e7-6616-65b82c294ac2": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "d0e8603e-5d2e-9287-e2c6-8ccbe9c66806": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70, + "outerMargin": true + } + } + } } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "stack": false, - "enableSelection": true, - "fontSize": 10, - "fontColor": "#545454", - "showTooltip": true, - "tooltipIndividual": false, - "tooltipCumulative": false, - "hideZeros": false, - "grid": { - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1, - "color": "#545454", - "backgroundColor": null, - "tickColor": "#DDDDDD" - }, - "xaxis": { - "title": null, - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "min": 0, - "max": null, - "title": null, - "showLabels": true, - "color": "#545454", - "tickSize": null, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "defaultBarWidth": 2400000, - "barAlignment": "left", - "comparisonEnabled": false, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - }, - "customLegendEnabled": false - }, - "title": "{i18n:api-usage.scripts-hourly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": { - "headerButton": [ - { - "name": "{i18n:api-usage.view-details}", - "icon": "insert_chart", - "useShowWidgetActionFunction": null, - "showWidgetActionFunction": "return true;", - "type": "openDashboardState", - "targetDashboardStateId": "script_functions", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "openInSeparateDialog": false, - "openInPopover": false, - "id": "4687d3f6-8800-a3b6-26e5-0d33f3b828a9" - } - ] - }, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "widgetCss": "", - "pageSize": 1024, - "noDataDisplayMessage": "", - "configMode": "advanced" }, - "row": 0, - "col": 0, - "id": "d890cea3-fba0-6474-9a21-fa780230dc62", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "84b6cfa5-1449-e0f2-3560-f810d2dd7ead": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "storageDataPointsCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.data-points-storage-days}", - "color": "#1039ee", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null + "entityAliases": { + "40193437-33ac-3172-eefd-0b08eb849062": { + "id": "40193437-33ac-3172-eefd-0b08eb849062", + "alias": "Api usage state", + "filter": { + "type": "apiUsageState", + "resolveMultiple": false + } + }, + "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f": { + "id": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f", + "alias": "TbServiceQueues", + "filter": { + "type": "assetType", + "resolveMultiple": true, + "assetNameFilter": "", + "assetTypes": [ + "TbServiceQueue" + ] } - ] } - ], - "timewindow": { + }, + "filters": {}, + "timewindow": { "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, "hideAggregation": false, "hideAggInterval": false, + "hideTimezone": false, "selectedTab": 0, "realtime": { - "timewindowMs": 86400000, - "interval": 3600000 + "realtimeType": 0, + "timewindowMs": 86400000, + "quickInterval": "CURRENT_DAY", + "interval": 3600000 }, "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", - "min": 0, - "tickDecimals": 0 - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 2400000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.telemetry-persistence-hourly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": { - "headerButton": [ - { - "name": "{i18n:api-usage.view-details}", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "telemetry_persistence", - "setEntityId": false, - "stateEntityParamName": null, - "openRightLayout": false, - "id": "16707efb-e572-bd02-c219-55fc1b0f672a" - } - ] - }, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "84b6cfa5-1449-e0f2-3560-f810d2dd7ead", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "d296b566-a000-7402-ae9d-c815381c5435": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "createdAlarmsCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.alarms-created}", - "color": "#d35a00", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 0, - "realtime": { - "timewindowMs": 86400000, - "interval": 3600000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", - "min": 0, - "tickDecimals": 0 - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 2400000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.alarms-created-hourly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": { - "headerButton": [ - { - "name": "{i18n:api-usage.view-details}", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "alarms_created", - "setEntityId": false, - "stateEntityParamName": null, - "openInSeparateDialog": null, - "dialogTitle": null, - "dialogHideDashboardToolbar": true, - "dialogWidth": null, - "dialogHeight": null, - "openRightLayout": false, - "id": "371882f9-ea23-3abc-fca8-9449c5dfdd6b" - } - ] - }, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "d296b566-a000-7402-ae9d-c815381c5435", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "00a02464-9509-911b-3b5e-21fb37629822": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "emailCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.email-messages}", - "color": "#4caf50", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.1348755140779876, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "smsCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.sms-messages}", - "color": "#f36021", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 0, - "realtime": { - "timewindowMs": 86400000, - "interval": 3600000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", - "min": 0, - "tickDecimals": 0 - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 2400000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.notifications-hourly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": { - "headerButton": [ - { - "name": "{i18n:api-usage.view-details}", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "notifications", - "setEntityId": false, - "stateEntityParamName": null, - "openInSeparateDialog": null, - "dialogTitle": null, - "dialogHideDashboardToolbar": true, - "dialogWidth": null, - "dialogHeight": null, - "openRightLayout": false, - "id": "49aefac0-ec5e-d6f3-f39c-8744759f4b19" - } - ] - }, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "00a02464-9509-911b-3b5e-21fb37629822", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "74199074-7873-6c6a-2a51-3fc614769f03": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "ruleEngineExecutionCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.rule-engine-executions}", - "color": "#ab00ff", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 86400000 - }, - "aggregation": { - "type": "SUM", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", - "min": 0, - "tickDecimals": 0 - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 1800000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.rule-engine-daily-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "74199074-7873-6c6a-2a51-3fc614769f03", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "00006bc3-8a8d-b55e-ed39-e318f1bcd090": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "ruleEngineExecutionCount", - "type": "timeseries", - "label": "{i18n:api-usage.rule-engine-executions}", - "color": "#ab00ff", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 31536000000, - "interval": 1000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", - "min": 0, - "tickDecimals": 0 - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 900000000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.rule-engine-monthly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "00006bc3-8a8d-b55e-ed39-e318f1bcd090", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "5f5ca59c-e507-5301-5910-7ad8cd34df40": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "jsExecutionCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.javascript-executions}", - "color": "#ff9900", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "tbelExecutionCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.tbel-executions}", - "color": "#4caf50", - "settings": {}, - "_hash": 0.5212969314724616, - "aggregationType": null, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 86400000 - }, - "aggregation": { - "type": "SUM", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 1800000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.scripts-daily-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "widgetCss": "", - "pageSize": 1024, - "noDataDisplayMessage": "" - }, - "row": 0, - "col": 0, - "id": "5f5ca59c-e507-5301-5910-7ad8cd34df40", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "ada32ee9-44ed-48d1-c368-fd0c94b7607f": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "jsExecutionCount", - "type": "timeseries", - "label": "{i18n:api-usage.javascript-executions}", - "color": "#ff9900", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "tbelExecutionCount", - "type": "timeseries", - "label": "{i18n:api-usage.tbel-executions}", - "color": "#4caf50", - "settings": {}, - "_hash": 0.49748239768082403, - "aggregationType": null, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 31536000000, - "interval": 1000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 900000000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.scripts-monthly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "widgetCss": "", - "pageSize": 1024, - "noDataDisplayMessage": "" - }, - "row": 0, - "col": 0, - "id": "ada32ee9-44ed-48d1-c368-fd0c94b7607f", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "98bae68b-0f35-72f2-a428-9b06889f1554": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "transportMsgCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.transport-messages}", - "color": "#2196f3", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "transportDataPointsCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.transport-data-points}", - "color": "#4caf50", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.46849996721308895, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 86400000 - }, - "aggregation": { - "type": "SUM", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", - "min": 0, - "tickDecimals": 0 - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": true, - "tooltipIndividual": false, - "defaultBarWidth": 1800000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "tooltipCumulative": false, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.transport-daily-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "98bae68b-0f35-72f2-a428-9b06889f1554", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "e61e5477-5a09-cc25-966b-f613d81da833": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "transportMsgCount", - "type": "timeseries", - "label": "{i18n:api-usage.transport-messages}", - "color": "#2196f3", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "transportDataPointsCount", - "type": "timeseries", - "label": "{i18n:api-usage.transport-data-points}", - "color": "#4caf50", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.46849996721308895, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 31536000000, - "interval": 2592000000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", - "min": 0, - "tickDecimals": 0 - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": true, - "tooltipIndividual": false, - "defaultBarWidth": 900000000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "tooltipCumulative": false, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.transport-monthly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "e61e5477-5a09-cc25-966b-f613d81da833", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "85fe0738-5326-f069-ab3f-30594bde5fed": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "storageDataPointsCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.data-points-storage-days}", - "color": "#1039ee", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 86400000 - }, - "aggregation": { - "type": "SUM", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 1800000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.telemetry-persistence-daily-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "85fe0738-5326-f069-ab3f-30594bde5fed", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "eaeb381a-437e-f6e9-60c9-6bc8826fdd44": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "storageDataPointsCount", - "type": "timeseries", - "label": "{i18n:api-usage.data-points-storage-days}", - "color": "#1039ee", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 31536000000, - "interval": 1000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 900000000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.telemetry-persistence-monthly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "eaeb381a-437e-f6e9-60c9-6bc8826fdd44", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "4b798823-b97d-9d6a-59dc-fcafd897fc23": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "createdAlarmsCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.alarms-created}", - "color": "#d35a00", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 86400000 - }, - "aggregation": { - "type": "SUM", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 1800000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.alarms-created-daily-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "4b798823-b97d-9d6a-59dc-fcafd897fc23", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "6a981580-7490-19dd-f937-b64cbf67a982": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "createdAlarmsCount", - "type": "timeseries", - "label": "{i18n:api-usage.alarms-created}", - "color": "#d35a00", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 31536000000, - "interval": 1000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 900000000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.alarms-created-monthly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "6a981580-7490-19dd-f937-b64cbf67a982", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "7302df65-1b0c-579e-bbdb-145126ae3392": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "smsCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.sms-messages}", - "color": "#f36021", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 86400000 - }, - "aggregation": { - "type": "SUM", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 1800000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.sms-messages-daily-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "7302df65-1b0c-579e-bbdb-145126ae3392", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "fdb385e7-14fe-fc9f-ebdc-b400f26fc66b": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "smsCount", - "type": "timeseries", - "label": "{i18n:api-usage.sms-messages}", - "color": "#f36021", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 31536000000, - "interval": 1000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 900000000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.sms-messages-monthly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "fdb385e7-14fe-fc9f-ebdc-b400f26fc66b", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "2408ad30-163e-8221-08e1-a82b638be564": { - "type": "timeseries", - "sizeX": 12, - "sizeY": 7, - "config": { - "datasources": [ - { - "type": "entity", - "dataKeys": [ - { - "name": "successfulMsgs", - "type": "timeseries", - "label": "{i18n:api-usage.successful}", - "color": "#4caf50", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.15490750967648736 - }, - { - "name": "failedMsgs", - "type": "timeseries", - "label": "{i18n:api-usage.permanent-failures}", - "color": "#ef5350", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.4186621166514697 - }, - { - "name": "tmpFailed", - "type": "timeseries", - "label": "{i18n:api-usage.processing-failures}", - "color": "#ffc107", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.49891007198715376 - } - ], - "entityAliasId": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f" - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 0, - "realtime": { - "timewindowMs": 3600000, - "interval": 1000 - }, - "aggregation": { - "type": "NONE", - "limit": 10000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "showMin": true, - "showMax": true, - "showAvg": false, - "showTotal": true - } - }, - "title": "Queue Stats", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "mobileHeight": null, - "showTitleIcon": false, - "titleIcon": null, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "widgetStyle": {}, - "useDashboardTimewindow": false, - "displayTimewindow": true, - "actions": {} - }, - "id": "2408ad30-163e-8221-08e1-a82b638be564", - "typeFullFqn": "system.charts.basic_timeseries" - }, - "e43dcfe1-b970-6a11-ce0e-5769f3eb5e88": { - "type": "timeseries", - "sizeX": 12, - "sizeY": 7, - "config": { - "datasources": [ - { - "type": "entity", - "dataKeys": [ - { - "name": "timeoutMsgs", - "type": "timeseries", - "label": "{i18n:api-usage.permanent-timeouts}", - "color": "#4caf50", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.565222981550328 - }, - { - "name": "tmpTimeout", - "type": "timeseries", - "label": "{i18n:api-usage.processing-timeouts}", - "color": "#9c27b0", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.2679547062508352 - } - ], - "entityAliasId": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f" - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 0, - "realtime": { - "timewindowMs": 3600000, - "interval": 1000 - }, - "aggregation": { - "type": "NONE", - "limit": 10000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "showMin": true, - "showMax": true, - "showAvg": false, - "showTotal": true - } - }, - "title": "Processing Failures and Timeouts", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "mobileHeight": null, - "showTitleIcon": false, - "titleIcon": null, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "widgetStyle": {}, - "useDashboardTimewindow": false, - "displayTimewindow": true, - "actions": {} - }, - "id": "e43dcfe1-b970-6a11-ce0e-5769f3eb5e88", - "typeFullFqn": "system.charts.basic_timeseries" - }, - "a669cf86-e715-efa4-dd9a-b839abf499e9": { - "type": "timeseries", - "sizeX": 24, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "dataKeys": [ - { - "name": "ruleEngineException", - "type": "timeseries", - "label": "Rule Chain", - "color": "#2196f3", - "settings": { - "useCellStyleFunction": false, - "useCellContentFunction": true, - "cellContentFunction": "return JSON.parse(value).ruleChainName;" - }, - "_hash": 0.9954481282345906 - }, - { - "name": "ruleEngineException", - "type": "timeseries", - "label": "Rule Node", - "color": "#4caf50", - "settings": { - "useCellStyleFunction": false, - "useCellContentFunction": true, - "cellContentFunction": "return JSON.parse(value).ruleNodeName;" - }, - "_hash": 0.18580357036589978 - }, - { - "name": "ruleEngineException", - "type": "timeseries", - "label": "Latest Error", - "color": "#f44336", - "settings": { - "useCellStyleFunction": false, - "useCellContentFunction": true, - "cellContentFunction": "return JSON.parse(value).message;" - }, - "_hash": 0.7255162989552142 - } - ], - "entityAliasId": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f" - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 0, - "realtime": { - "timewindowMs": 2592000000, - "interval": 1000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "rgb(255, 255, 255)", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "showTimestamp": true, - "displayPagination": true, - "defaultPageSize": 10 - }, - "title": "Exceptions", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "useDashboardTimewindow": false, - "showLegend": false, - "widgetStyle": {}, - "actions": {}, - "showTitleIcon": false, - "titleIcon": null, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "displayTimewindow": true - }, - "id": "a669cf86-e715-efa4-dd9a-b839abf499e9", - "typeFullFqn": "system.cards.timeseries_table" - }, - "292eaded-4775-36f7-c896-98d57bdda936": { - "type": "latest", - "sizeX": 7.5, - "sizeY": 3, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "emailApiState", - "type": "timeseries", - "label": "apiState", - "color": "#2196f3", - "settings": {}, - "_hash": 0.8830669138660703, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "emailLimit", - "type": "timeseries", - "label": "limit", - "color": "#4caf50", - "settings": {}, - "_hash": 0.5463603803546802, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "emailCount", - "type": "timeseries", - "label": "count", - "color": "#f44336", - "settings": {}, - "_hash": 0.5564241862015964, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "transportApiState", - "type": "timeseries", - "label": "cardId", - "color": "#607d8b", - "settings": {}, - "_hash": 0.051659774305067296, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return (Math.random()*100000).toFixed(0);" - }, - { - "name": "smsApiState", - "type": "timeseries", - "label": "apiStatePoint", - "color": "#e91e63", - "settings": {}, - "_hash": 0.2969682764607864, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "smsLimit", - "type": "timeseries", - "label": "pointsLimit", - "color": "#9c27b0", - "settings": {}, - "_hash": 0.22082255831864894, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "smsCount", - "type": "timeseries", - "label": "pointsCount", - "color": "#8bc34a", - "settings": {}, - "_hash": 0.6340356364819146, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "transportApiState", - "type": "timeseries", - "label": "title", - "color": "#3f51b5", - "settings": {}, - "_hash": 0.6894070537030252, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": true, - "postFuncBody": "return \"{i18n:api-usage.notifications}\";" - } - ] - } - ], - "timewindow": { - "displayValue": "", - "selectedTab": 0, - "realtime": { - "realtimeType": 1, - "interval": 1000, - "timewindowMs": 60000, - "quickInterval": "CURRENT_DAY" - }, - "history": { - "historyType": 0, - "interval": 1000, - "timewindowMs": 60000, - "fixedTimewindow": { - "startTimeMs": 1694083375827, - "endTimeMs": 1694169775827 - }, - "quickInterval": "CURRENT_DAY" - }, - "aggregation": { - "type": "AVG", - "limit": 25000 - } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "#666666", - "padding": "0", - "settings": { - "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 6px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n", - "cardHtml": "
    \n \n \n
    \n
    \n
    \n
    \n ${title}\n
    \n
    \n
    \n
    \n
    \n
    \n
    {i18n:api-usage.email}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    {i18n:api-usage.sms}
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n
    " - }, - "title": "Notifications (Email/SMS)", - "dropShadow": true, - "enableFullscreen": false, - "widgetStyle": { - "cursor": "default" - }, - "titleStyle": { - "fontSize": "20px", - "fontWeight": 400 - }, - "useDashboardTimewindow": true, - "showLegend": false, - "actions": { - "elementClick": [ - { - "name": "transport_details", - "icon": "insert_chart", - "type": "openDashboardState", - "targetDashboardStateId": "notifications", - "setEntityId": false, - "stateEntityParamName": null, - "openInSeparateDialog": null, - "dialogTitle": null, - "dialogHideDashboardToolbar": true, - "dialogWidth": null, - "dialogHeight": null, - "openRightLayout": false, - "id": "46b7cefe-e1f2-67c1-4055-3a214520f869" - } - ] - }, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "292eaded-4775-36f7-c896-98d57bdda936", - "typeFullFqn": "system.cards.html_value_card" - }, - "b3571a36-2106-1122-7d58-0d38bbb0e9c8": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "emailCountHourly", - "type": "timeseries", - "label": "{i18n:api-usage.email-messages}", - "color": "#d35a00", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 86400000 - }, - "aggregation": { - "type": "SUM", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 1800000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.email-messages-daily-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" - }, - "row": 0, - "col": 0, - "id": "b3571a36-2106-1122-7d58-0d38bbb0e9c8", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, - "aa875b7f-e7c8-7529-1ae7-f456211b59cc": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", - "filterId": null, - "dataKeys": [ - { - "name": "emailCount", - "type": "timeseries", - "label": "{i18n:api-usage.email-messages}", - "color": "#d35a00", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": false, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.0661644137210089, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ] - } - ], - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 31536000000, - "interval": 1000 - }, - "aggregation": { - "type": "NONE", - "limit": 1000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454", - "min": 0, - "tickDecimals": 0, - "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 + "type": "NONE", + "limit": 50000 }, - "stack": false, - "tooltipIndividual": false, - "defaultBarWidth": 900000000, - "barAlignment": "left", - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": true - } - }, - "title": "{i18n:api-usage.email-messages-monthly-activity}", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": {}, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "" + "timezone": null }, - "row": 0, - "col": 0, - "id": "aa875b7f-e7c8-7529-1ae7-f456211b59cc", - "typeFullFqn": "system.charts.timeseries_bars_flot" - } - }, - "states": { - "default": { - "name": "{i18n:api-usage.api-usage}", - "root": true, - "layouts": { - "main": { - "widgets": { - "fd6df872-2ddf-0921-3929-2e7f55062fad": { - "sizeX": 4, - "sizeY": 2, - "row": 0, - "col": 8, - "mobileHeight": 3 - }, - "7e235874-461b-e7c2-2fdd-d8762a020773": { - "sizeX": 4, - "sizeY": 2, - "row": 0, - "col": 12, - "mobileHeight": 3 - }, - "08545554-a0e8-05c7-66df-6000cfeff8a4": { - "sizeX": 4, - "sizeY": 2, - "row": 0, - "col": 4, - "mobileHeight": 3 - }, - "a245c67e-53ec-d299-fa89-69fe2062ccb2": { - "sizeX": 4, - "sizeY": 2, - "row": 0, - "col": 0, - "mobileHeight": 3 - }, - "a151ae60-0326-6116-d818-9070dda8e9c7": { - "sizeX": 4, - "sizeY": 2, - "row": 0, - "col": 16, - "mobileHeight": 3 - }, - "292eaded-4775-36f7-c896-98d57bdda936": { - "sizeX": 4, - "sizeY": 2, - "row": 0, - "col": 20, - "mobileHeight": 3 - }, - "68e16e98-0420-f72c-4848-41dedffd3904": { - "sizeX": 8, - "sizeY": 4, - "row": 2, - "col": 8 - }, - "2aa6b499-6e27-b315-6833-89c4d58485ce": { - "sizeX": 8, - "sizeY": 4, - "row": 2, - "col": 0 - }, - "d890cea3-fba0-6474-9a21-fa780230dc62": { - "sizeX": 8, - "sizeY": 4, - "row": 2, - "col": 16 - }, - "84b6cfa5-1449-e0f2-3560-f810d2dd7ead": { - "sizeX": 8, - "sizeY": 4, - "row": 6, - "col": 0 - }, - "d296b566-a000-7402-ae9d-c815381c5435": { - "sizeX": 8, - "sizeY": 4, - "row": 6, - "col": 8 - }, - "00a02464-9509-911b-3b5e-21fb37629822": { - "sizeX": 8, - "sizeY": 4, - "row": 6, - "col": 16 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margin": 5, - "backgroundSizeMode": "100%", - "autoFillHeight": true, - "backgroundImageUrl": null, - "mobileAutoFillHeight": false, - "mobileRowHeight": 70, - "outerMargin": true - } - } - } - }, - "transport": { - "name": "{i18n:api-usage.transport}", - "root": false, - "layouts": { - "main": { - "widgets": { - "98bae68b-0f35-72f2-a428-9b06889f1554": { - "sizeX": 24, - "sizeY": 6, - "row": 0, - "col": 0 - }, - "e61e5477-5a09-cc25-966b-f613d81da833": { - "sizeX": 24, - "sizeY": 6, - "row": 6, - "col": 0 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margin": 10, - "backgroundSizeMode": "100%", - "autoFillHeight": true, - "backgroundImageUrl": null, - "mobileAutoFillHeight": false, - "mobileRowHeight": 70, - "outerMargin": true - } - } - } - }, - "rule_engine_execution": { - "name": "{i18n:api-usage.rule-engine-executions}", - "root": false, - "layouts": { - "main": { - "widgets": { - "74199074-7873-6c6a-2a51-3fc614769f03": { - "sizeX": 24, - "sizeY": 6, - "row": 0, - "col": 0 - }, - "00006bc3-8a8d-b55e-ed39-e318f1bcd090": { - "sizeX": 24, - "sizeY": 6, - "row": 6, - "col": 0 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margin": 10, - "backgroundSizeMode": "100%", - "autoFillHeight": true, - "backgroundImageUrl": null, - "mobileAutoFillHeight": false, - "mobileRowHeight": 70, - "outerMargin": true - } - } + "settings": { + "stateControllerId": "entity", + "showTitle": false, + "showDashboardsSelect": false, + "showEntitiesSelect": false, + "showDashboardTimewindow": false, + "showDashboardExport": false, + "toolbarAlwaysOpen": true, + "titleColor": "rgba(0,0,0,0.870588)", + "showFilters": false, + "showDashboardLogo": false, + "dashboardLogoUrl": null, + "hideToolbar": false, + "showUpdateDashboardImage": false, + "dashboardCss": ".tb-time-series-chart-panel {\n padding: 13px;\n}\n\n.tb-time-series-chart-panel {\n gap: 0; \n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n\n.card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n.card .unit {\n color: #666666;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} " } - }, - "telemetry_persistence": { - "name": "{i18n:api-usage.telemetry-persistence}", - "root": false, - "layouts": { - "main": { - "widgets": { - "85fe0738-5326-f069-ab3f-30594bde5fed": { - "sizeX": 24, - "sizeY": 6, - "row": 0, - "col": 0 - }, - "eaeb381a-437e-f6e9-60c9-6bc8826fdd44": { - "sizeX": 24, - "sizeY": 6, - "row": 6, - "col": 0 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margin": 10, - "backgroundSizeMode": "100%", - "autoFillHeight": true, - "backgroundImageUrl": null, - "mobileAutoFillHeight": false, - "mobileRowHeight": 70, - "outerMargin": true - } - } - } - }, - "rule_engine_statistics": { - "name": "{i18n:api-usage.rule-engine-statistics}", - "root": false, - "layouts": { - "main": { - "widgets": { - "2408ad30-163e-8221-08e1-a82b638be564": { - "sizeX": 12, - "sizeY": 7, - "mobileHeight": null, - "row": 0, - "col": 0 - }, - "e43dcfe1-b970-6a11-ce0e-5769f3eb5e88": { - "sizeX": 12, - "sizeY": 7, - "mobileHeight": null, - "row": 0, - "col": 12 - }, - "a669cf86-e715-efa4-dd9a-b839abf499e9": { - "sizeX": 24, - "sizeY": 5, - "row": 7, - "col": 0 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margin": 10, - "backgroundSizeMode": "100%", - "autoFillHeight": true, - "backgroundImageUrl": null, - "mobileAutoFillHeight": false, - "mobileRowHeight": 70, - "outerMargin": true - } - } - } - }, - "notifications": { - "name": "{i18n:api-usage.notifications-email-sms}", - "root": false, - "layouts": { - "main": { - "widgets": { - "7302df65-1b0c-579e-bbdb-145126ae3392": { - "sizeX": 12, - "sizeY": 6, - "row": 0, - "col": 12 - }, - "fdb385e7-14fe-fc9f-ebdc-b400f26fc66b": { - "sizeX": 12, - "sizeY": 6, - "row": 6, - "col": 12 - }, - "b3571a36-2106-1122-7d58-0d38bbb0e9c8": { - "sizeX": 12, - "sizeY": 6, - "row": 0, - "col": 0 - }, - "aa875b7f-e7c8-7529-1ae7-f456211b59cc": { - "sizeX": 12, - "sizeY": 6, - "row": 6, - "col": 0 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margin": 10, - "backgroundSizeMode": "100%", - "autoFillHeight": true, - "backgroundImageUrl": null, - "mobileAutoFillHeight": false, - "mobileRowHeight": 70, - "outerMargin": true - } - } - } - }, - "alarms_created": { - "name": "{i18n:api-usage.alarms-created}", - "root": false, - "layouts": { - "main": { - "widgets": { - "4b798823-b97d-9d6a-59dc-fcafd897fc23": { - "sizeX": 24, - "sizeY": 6, - "row": 0, - "col": 0 - }, - "6a981580-7490-19dd-f937-b64cbf67a982": { - "sizeX": 24, - "sizeY": 6, - "row": 6, - "col": 0 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margin": 10, - "backgroundSizeMode": "100%", - "autoFillHeight": true, - "backgroundImageUrl": null, - "mobileAutoFillHeight": false, - "mobileRowHeight": 70, - "outerMargin": true - } - } - } - }, - "script_functions": { - "name": "{i18n:api-usage.scripts}", - "root": false, - "layouts": { - "main": { - "widgets": { - "5f5ca59c-e507-5301-5910-7ad8cd34df40": { - "sizeX": 24, - "sizeY": 6, - "row": 0, - "col": 0 - }, - "ada32ee9-44ed-48d1-c368-fd0c94b7607f": { - "sizeX": 24, - "sizeY": 6, - "row": 6, - "col": 0 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margin": 10, - "backgroundSizeMode": "100%", - "autoFillHeight": true, - "backgroundImageUrl": null, - "mobileAutoFillHeight": false, - "mobileRowHeight": 70, - "outerMargin": true - } - } - } - } - }, - "entityAliases": { - "40193437-33ac-3172-eefd-0b08eb849062": { - "id": "40193437-33ac-3172-eefd-0b08eb849062", - "alias": "Api usage state", - "filter": { - "type": "apiUsageState", - "resolveMultiple": false - } - }, - "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f": { - "id": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f", - "alias": "TbServiceQueues", - "filter": { - "type": "assetType", - "resolveMultiple": true, - "assetNameFilter": "", - "assetTypes": [ - "TbServiceQueue" - ] - } - } - }, - "filters": {}, - "timewindow": { - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "selectedTab": 0, - "realtime": { - "timewindowMs": 86400000, - "interval": 3600000 - }, - "aggregation": { - "type": "NONE", - "limit": 50000 - } }, - "settings": { - "stateControllerId": "entity", - "showTitle": false, - "showDashboardsSelect": false, - "showEntitiesSelect": false, - "showDashboardTimewindow": false, - "showDashboardExport": false, - "toolbarAlwaysOpen": true, - "titleColor": "rgba(0,0,0,0.870588)", - "showFilters": false, - "showDashboardLogo": false - } - }, - "externalId": null, - "name": "Api Usage" + "name": "Api Usage" } 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 b32cfb7d38..8b46687fa2 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -791,6 +791,9 @@ "api-usage": "API usage", "alarm": "Alarm", "alarms-created": "Alarms created", + "queue-stats": "Queue Stats", + "processing-failures-and-timeouts": "Processing Failures and Timeouts", + "exceptions": "Exceptions", "alarms-created-daily-activity": "Alarms created daily activity", "alarms-created-hourly-activity": "Alarms created hourly activity", "alarms-created-monthly-activity": "Alarms created monthly activity", From 00e8bda08b9531dda5287f35635a62477506cbce Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 7 Mar 2024 17:01:17 +0200 Subject: [PATCH 319/397] UI: Add icon to configure mobile app notification --- ...tion-template-configuration.component.html | 16 ++++++++- ...cation-template-configuration.component.ts | 33 +++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html index 54db7ece72..8297985a16 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html @@ -120,7 +120,21 @@ }} -
    +
    +
    + + {{ 'icon.icon' | translate }} + +
    + + + + +
    +
    ) { + const settings = deepClone(value); + if (isDefinedAndNotNull(settings)) { + for (const method of Object.values(NotificationDeliveryMethod)) { + if (isDefinedAndNotNull(settings[method]?.enabled)) { + delete settings[method].enabled; + } + } + } + this.templateConfigurationForm.patchValue(settings, {emitEvent: false}); } registerOnChange(fn: any): void { @@ -160,6 +168,9 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co case NotificationDeliveryMethod.WEB: form.get('additionalConfig.icon.enabled').updateValueAndValidity({onlySelf: true}); break; + case NotificationDeliveryMethod.MOBILE_APP: + form.get('additionalConfig.icon.enabled').updateValueAndValidity({onlySelf: true}); + break; } } }); @@ -225,9 +236,25 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co subject: ['', [Validators.required, Validators.maxLength(50)]], body: ['', [Validators.required, Validators.maxLength(150)]], additionalConfig: this.fb.group({ + icon: this.fb.group({ + enabled: [false], + icon: [{value: 'notifications', disabled: true}, Validators.required], + color: [{value: '#757575', disabled: true}] + }), onClick: [null] }) }); + deliveryMethodForm.get('additionalConfig.icon.enabled').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + if (value) { + deliveryMethodForm.get('additionalConfig.icon.icon').enable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.icon.color').enable({emitEvent: false}); + } else { + deliveryMethodForm.get('additionalConfig.icon.icon').disable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.icon.color').disable({emitEvent: false}); + } + }); break; case NotificationDeliveryMethod.MICROSOFT_TEAMS: deliveryMethodForm = this.fb.group({ From d39be089744ab694114130d23441f51a24097a10 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 7 Mar 2024 17:50:28 +0200 Subject: [PATCH 320/397] UI: Improve time series bar width strategy: calculate width as percentage of time window. --- ...e-series-chart-basic-config.component.html | 31 +--- ...ime-series-chart-basic-config.component.ts | 31 +--- .../lib/chart/time-series-chart-bar.models.ts | 16 +- .../lib/chart/time-series-chart.models.ts | 40 ++++- .../widget/lib/chart/time-series-chart.ts | 3 +- ...eries-chart-widget-settings.component.html | 31 +--- ...-series-chart-widget-settings.component.ts | 38 +---- ...me-series-chart-axis-settings.component.ts | 5 +- ...regation-bar-width-settings.component.html | 75 +++++++++ ...ggregation-bar-width-settings.component.ts | 147 ++++++++++++++++++ .../common/widget-settings-common.module.ts | 5 + .../assets/locale/locale.constant-en_US.json | 6 +- ui-ngx/src/form.scss | 6 +- 13 files changed, 295 insertions(+), 139 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html index 5b14146d0f..3d099c2645 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html @@ -114,33 +114,10 @@ axisType="xAxis">
    -
    -
    -
    widgets.time-series-chart.no-aggregation-bar-width-strategy
    - - - {{ timeSeriesChartNoAggregationBarWidthStrategyTranslations.get(strategy) | translate }} - - -
    -
    -
    widgets.time-series-chart.bar-group-interval-width
    - - - ms - -
    -
    -
    widgets.time-series-chart.separate-bar-width
    - - - ms - -
    -
    + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts index 79aa52fdb6..5307147b0e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts @@ -45,12 +45,7 @@ import { TimeSeriesChartWidgetSettings } from '@home/components/widget/lib/chart/time-series-chart-widget.models'; import { EChartsTooltipTrigger } from '@home/components/widget/lib/chart/echarts-widget.models'; -import { - timeSeriesChartNoAggregationBarWidthStrategies, - TimeSeriesChartNoAggregationBarWidthStrategy, - timeSeriesChartNoAggregationBarWidthStrategyTranslations, - TimeSeriesChartType -} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { TimeSeriesChartType } from '@home/components/widget/lib/chart/time-series-chart.models'; @Component({ selector: 'tb-time-series-chart-basic-config', @@ -76,12 +71,6 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon legendPositionTranslationMap = legendPositionTranslationMap; - TimeSeriesChartNoAggregationBarWidthStrategy = TimeSeriesChartNoAggregationBarWidthStrategy; - - timeSeriesChartNoAggregationBarWidthStrategies = timeSeriesChartNoAggregationBarWidthStrategies; - - timeSeriesChartNoAggregationBarWidthStrategyTranslations = timeSeriesChartNoAggregationBarWidthStrategyTranslations; - timeSeriesChartWidgetConfigForm: UntypedFormGroup; tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); @@ -140,11 +129,7 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon yAxis: [settings.yAxis, []], xAxis: [settings.xAxis, []], - noAggregationBarWidthSettings: this.fb.group({ - strategy: [settings.noAggregationBarWidthSettings.strategy, []], - groupIntervalWidth: [settings.noAggregationBarWidthSettings.groupIntervalWidth, [Validators.min(100)]], - separateBarWidth: [settings.noAggregationBarWidthSettings.separateBarWidth, [Validators.min(100)]], - }), + noAggregationBarWidthSettings: [settings.noAggregationBarWidthSettings, []], showLegend: [settings.showLegend, []], legendLabelFont: [settings.legendLabelFont, []], @@ -227,7 +212,7 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon } protected validatorTriggers(): string[] { - return ['showTitle', 'showIcon', 'showLegend', 'showTooltip', 'tooltipShowDate', 'noAggregationBarWidthSettings.strategy']; + return ['showTitle', 'showIcon', 'showLegend', 'showTooltip', 'tooltipShowDate']; } protected updateValidators(emitEvent: boolean, trigger?: string) { @@ -236,8 +221,6 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon const showLegend: boolean = this.timeSeriesChartWidgetConfigForm.get('showLegend').value; const showTooltip: boolean = this.timeSeriesChartWidgetConfigForm.get('showTooltip').value; const tooltipShowDate: boolean = this.timeSeriesChartWidgetConfigForm.get('tooltipShowDate').value; - const noAggregationBarWidthSettingsStrategy: TimeSeriesChartNoAggregationBarWidthStrategy = - this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('strategy').value; if (showTitle) { this.timeSeriesChartWidgetConfigForm.get('title').enable(); @@ -266,14 +249,6 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon this.timeSeriesChartWidgetConfigForm.get('iconColor').disable(); } - if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.group) { - this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').enable(); - this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('separateBarWidth').disable(); - } else if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate) { - this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').disable(); - this.timeSeriesChartWidgetConfigForm.get('noAggregationBarWidthSettings').get('separateBarWidth').enable(); - } - if (showLegend) { this.timeSeriesChartWidgetConfigForm.get('legendLabelFont').enable(); this.timeSeriesChartWidgetConfigForm.get('legendLabelColor').enable(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts index e5dfd6944e..bf7f6cf764 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts @@ -19,7 +19,6 @@ import { Interval, IntervalMath } from '@shared/models/time/time.models'; import { LabelFormatterCallback, SeriesLabelOption } from 'echarts/types/src/util/types'; import { TimeSeriesChartDataItem, - TimeSeriesChartNoAggregationBarWidthSettings, TimeSeriesChartNoAggregationBarWidthStrategy } from '@home/components/widget/lib/chart/time-series-chart.models'; import { CustomSeriesRenderItemParams } from 'echarts'; @@ -38,7 +37,9 @@ export interface BarRenderContext { barsCount?: number; barIndex?: number; noAggregation: boolean; - noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings; + noAggregationBarWidthStrategy: TimeSeriesChartNoAggregationBarWidthStrategy; + noAggregationWidthRelative?: boolean; + noAggregationWidth?: number; timeInterval?: Interval; visualSettings?: BarVisualSettings; labelOption?: SeriesLabelOption; @@ -54,16 +55,15 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C let interval = end - start; const ts = start ? start : time; - const noAggregationGroup = renderCtx.noAggregation && - renderCtx.noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group; const separateBar = renderCtx.noAggregation && - renderCtx.noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate; + renderCtx.noAggregationBarWidthStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate; if (renderCtx.noAggregation) { - if (noAggregationGroup) { - interval = renderCtx.noAggregationBarWidthSettings.groupIntervalWidth; + if (renderCtx.noAggregationWidthRelative) { + const scaleWidth = api.getWidth() / api.size([1,0])[0]; + interval = scaleWidth * (renderCtx.noAggregationWidth / 100); } else { - interval = renderCtx.noAggregationBarWidthSettings.separateBarWidth; + interval = renderCtx.noAggregationWidth; } start = time - interval / 2; end = time + interval / 2; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index 6aac959cbe..fa349252b7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -391,10 +391,16 @@ export const timeSeriesChartNoAggregationBarWidthStrategyTranslations = new Map< ] ); +export interface TimeSeriesChartBarWidth { + relative?: boolean; + relativeWidth?: number; + absoluteWidth?: number; +} + export interface TimeSeriesChartNoAggregationBarWidthSettings { strategy: TimeSeriesChartNoAggregationBarWidthStrategy; - groupIntervalWidth?: number; - separateBarWidth?: number; + groupWidth?: TimeSeriesChartBarWidth; + barWidth?: TimeSeriesChartBarWidth; } export interface TimeSeriesChartSettings extends EChartsTooltipWidgetSettings { @@ -474,8 +480,16 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { }, noAggregationBarWidthSettings: { strategy: TimeSeriesChartNoAggregationBarWidthStrategy.group, - groupIntervalWidth: 1000, - separateBarWidth: 1000 + groupWidth: { + relative: true, + relativeWidth: 2, + absoluteWidth: 1000 + }, + barWidth: { + relative: true, + relativeWidth: 2, + absoluteWidth: 1000 + } }, showTooltip: true, tooltipTrigger: EChartsTooltipTrigger.axis, @@ -757,12 +771,12 @@ export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartAxisSetting export const generateChartData = (dataItems: TimeSeriesChartDataItem[], thresholdItems: TimeSeriesChartThresholdItem[], timeInterval: Interval, + stack: boolean, noAggregation: boolean, noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings, - stack: boolean, darkMode: boolean): Array => { let series = generateChartSeries(dataItems, timeInterval, - noAggregation, noAggregationBarWidthSettings, stack, darkMode); + stack, noAggregation, noAggregationBarWidthSettings, darkMode); if (thresholdItems.length) { const thresholds = generateChartThresholds(thresholdItems, darkMode); series = series.concat(thresholds); @@ -874,9 +888,9 @@ const createThresholdData = (val: string | number, item: TimeSeriesChartThreshol const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], timeInterval: Interval, + stack: boolean, noAggregation: boolean, noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings, - stack: boolean, darkMode: boolean): Array => { const series: Array = []; const enabledDataItems = dataItems.filter(d => d.enabled); @@ -895,7 +909,17 @@ const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], for (const item of enabledDataItems) { if (item.dataKey.settings.type === TimeSeriesChartSeriesType.bar) { if (!item.barRenderContext) { - item.barRenderContext = {noAggregation, noAggregationBarWidthSettings}; + item.barRenderContext = {noAggregation, + noAggregationBarWidthStrategy: noAggregationBarWidthSettings.strategy}; + const targetWidth = noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group ? + noAggregationBarWidthSettings.groupWidth : noAggregationBarWidthSettings.barWidth; + if (targetWidth.relative) { + item.barRenderContext.noAggregationWidthRelative = true; + item.barRenderContext.noAggregationWidth = targetWidth.relativeWidth; + } else { + item.barRenderContext.noAggregationWidthRelative = false; + item.barRenderContext.noAggregationWidth = targetWidth.absoluteWidth; + } } item.barRenderContext.noAggregation = noAggregation; item.barRenderContext.barsCount = barsCount; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index e5d4cb8f46..6d790d5439 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -492,8 +492,9 @@ export class TbTimeSeriesChart { private updateSeries(): Array { return generateChartData(this.dataItems, this.thresholdItems, this.ctx.timeWindow.interval, + this.settings.stack, this.noAggregation, - this.settings.noAggregationBarWidthSettings, this.settings.stack, this.darkMode); + this.settings.noAggregationBarWidthSettings, this.darkMode); } private updateAxes() { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html index f3a9a610c3..a754dec0b4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html @@ -48,33 +48,10 @@ axisType="xAxis">
    -
    -
    -
    widgets.time-series-chart.no-aggregation-bar-width-strategy
    - - - {{ timeSeriesChartNoAggregationBarWidthStrategyTranslations.get(strategy) | translate }} - - -
    -
    -
    widgets.time-series-chart.bar-group-interval-width
    - - - ms - -
    -
    -
    widgets.time-series-chart.separate-bar-width
    - - - ms - -
    -
    + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts index a520933f1b..b793e8c3eb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts @@ -22,23 +22,17 @@ import { WidgetSettings, WidgetSettingsComponent } from '@shared/models/widget.models'; -import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { formatValue, isDefinedAndNotNull, mergeDeep } from '@core/utils'; import { DateFormatProcessor, DateFormatSettings } from '@shared/models/widget-settings.models'; -import { - barChartWithLabelsDefaultSettings -} from '@home/components/widget/lib/chart/bar-chart-with-labels-widget.models'; import { EChartsTooltipTrigger } from '../../chart/echarts-widget.models'; import { - timeSeriesChartWidgetDefaultSettings, TimeSeriesChartWidgetSettings + timeSeriesChartWidgetDefaultSettings, + TimeSeriesChartWidgetSettings } from '@home/components/widget/lib/chart/time-series-chart-widget.models'; -import { - timeSeriesChartNoAggregationBarWidthStrategies, - TimeSeriesChartNoAggregationBarWidthStrategy, - timeSeriesChartNoAggregationBarWidthStrategyTranslations, TimeSeriesChartType -} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { TimeSeriesChartType } from '@home/components/widget/lib/chart/time-series-chart.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models'; @Component({ @@ -65,12 +59,6 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon legendPositionTranslationMap = legendPositionTranslationMap; - TimeSeriesChartNoAggregationBarWidthStrategy = TimeSeriesChartNoAggregationBarWidthStrategy; - - timeSeriesChartNoAggregationBarWidthStrategies = timeSeriesChartNoAggregationBarWidthStrategies; - - timeSeriesChartNoAggregationBarWidthStrategyTranslations = timeSeriesChartNoAggregationBarWidthStrategyTranslations; - timeSeriesChartWidgetSettingsForm: UntypedFormGroup; tooltipValuePreviewFn = this._tooltipValuePreviewFn.bind(this); @@ -111,11 +99,7 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon yAxis: [settings.yAxis, []], xAxis: [settings.xAxis, []], - noAggregationBarWidthSettings: this.fb.group({ - strategy: [settings.noAggregationBarWidthSettings.strategy, []], - groupIntervalWidth: [settings.noAggregationBarWidthSettings.groupIntervalWidth, [Validators.min(100)]], - separateBarWidth: [settings.noAggregationBarWidthSettings.separateBarWidth, [Validators.min(100)]], - }), + noAggregationBarWidthSettings: [settings.noAggregationBarWidthSettings, []], showLegend: [settings.showLegend, []], legendLabelFont: [settings.legendLabelFont, []], @@ -140,23 +124,13 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon } protected validatorTriggers(): string[] { - return ['showLegend', 'showTooltip', 'tooltipShowDate', 'noAggregationBarWidthSettings.strategy']; + return ['showLegend', 'showTooltip', 'tooltipShowDate']; } protected updateValidators(emitEvent: boolean) { const showLegend: boolean = this.timeSeriesChartWidgetSettingsForm.get('showLegend').value; const showTooltip: boolean = this.timeSeriesChartWidgetSettingsForm.get('showTooltip').value; const tooltipShowDate: boolean = this.timeSeriesChartWidgetSettingsForm.get('tooltipShowDate').value; - const noAggregationBarWidthSettingsStrategy: TimeSeriesChartNoAggregationBarWidthStrategy = - this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('strategy').value; - - if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.group) { - this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').enable(); - this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('separateBarWidth').disable(); - } else if (noAggregationBarWidthSettingsStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate) { - this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('groupIntervalWidth').disable(); - this.timeSeriesChartWidgetSettingsForm.get('noAggregationBarWidthSettings').get('separateBarWidth').enable(); - } if (showLegend) { this.timeSeriesChartWidgetSettingsForm.get('legendLabelFont').enable(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts index 2ae330c276..ab20727bdf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts @@ -22,8 +22,6 @@ import { TimeSeriesChartAxisSettings, TimeSeriesChartYAxisSettings } from '@home/components/widget/lib/chart/time-series-chart.models'; -import { Store } from '@ngrx/store'; -import { AppState } from '@core/core.state'; import { merge } from 'rxjs'; @Component({ @@ -60,8 +58,7 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu public axisSettingsFormGroup: UntypedFormGroup; - constructor(protected store: Store, - private fb: UntypedFormBuilder) { + constructor(private fb: UntypedFormBuilder) { } ngOnInit(): void { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.html new file mode 100644 index 0000000000..239c6ea18c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.html @@ -0,0 +1,75 @@ + +
    +
    +
    widgets.time-series-chart.no-aggregation-bar-width-strategy
    + + + {{ timeSeriesChartNoAggregationBarWidthStrategyTranslations.get(strategy) | translate }} + + +
    + + + + + + + + +
    + +
    +
    {{ label }}
    +
    + + + + {{ (formGroup.get('relative').value ? + 'widgets.time-series-chart.bar-width-relative' : + 'widgets.time-series-chart.bar-width-absolute') | translate }} + + + {{ 'widgets.time-series-chart.bar-width-relative' | translate }} + + + {{ 'widgets.time-series-chart.bar-width-absolute' | translate }} + + + + + + % + + + + ms + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts new file mode 100644 index 0000000000..36d8cb917a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component.ts @@ -0,0 +1,147 @@ +/// +/// 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, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormGroup, + Validators +} from '@angular/forms'; +import { + TimeSeriesChartNoAggregationBarWidthSettings, + timeSeriesChartNoAggregationBarWidthStrategies, + TimeSeriesChartNoAggregationBarWidthStrategy, + timeSeriesChartNoAggregationBarWidthStrategyTranslations +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { merge } from 'rxjs'; + +@Component({ + selector: 'tb-time-series-no-aggregation-bar-width-settings', + templateUrl: './time-series-no-aggregation-bar-width-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesNoAggregationBarWidthSettingsComponent), + multi: true + } + ] +}) +export class TimeSeriesNoAggregationBarWidthSettingsComponent implements OnInit, ControlValueAccessor { + + TimeSeriesChartNoAggregationBarWidthStrategy = TimeSeriesChartNoAggregationBarWidthStrategy; + + timeSeriesChartNoAggregationBarWidthStrategies = timeSeriesChartNoAggregationBarWidthStrategies; + + timeSeriesChartNoAggregationBarWidthStrategyTranslations = timeSeriesChartNoAggregationBarWidthStrategyTranslations; + + @Input() + disabled: boolean; + + private modelValue: TimeSeriesChartNoAggregationBarWidthSettings; + + private propagateChange = null; + + public barWidthSettingsFormGroup: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + } + + ngOnInit(): void { + this.barWidthSettingsFormGroup = this.fb.group({ + strategy: [null, []], + groupWidth: this.fb.group({ + relative: [null, []], + relativeWidth: [null, [Validators.required, Validators.min(0.1), Validators.max(100)]], + absoluteWidth: [null, [Validators.required, Validators.min(100)]] + }), + barWidth: this.fb.group({ + relative: [null, []], + relativeWidth: [null, [Validators.required, Validators.min(0.1), Validators.max(100)]], + absoluteWidth: [null, [Validators.required, Validators.min(100)]] + }) + }); + this.barWidthSettingsFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + }); + merge(this.barWidthSettingsFormGroup.get('strategy').valueChanges, + this.barWidthSettingsFormGroup.get('groupWidth.relative').valueChanges, + this.barWidthSettingsFormGroup.get('barWidth.relative').valueChanges) + .subscribe(() => { + this.updateValidators(); + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(_fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.barWidthSettingsFormGroup.disable({emitEvent: false}); + } else { + this.barWidthSettingsFormGroup.enable({emitEvent: false}); + this.updateValidators(); + } + } + + writeValue(value: TimeSeriesChartNoAggregationBarWidthSettings): void { + this.modelValue = value; + this.barWidthSettingsFormGroup.patchValue( + value, {emitEvent: false} + ); + this.updateValidators(); + } + + private updateValidators() { + const strategy: TimeSeriesChartNoAggregationBarWidthStrategy = + this.barWidthSettingsFormGroup.get('strategy').value; + const groupWidthRelative: boolean = this.barWidthSettingsFormGroup.get('groupWidth.relative').value; + const barWidthRelative: boolean = this.barWidthSettingsFormGroup.get('barWidth.relative').value; + if (strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group) { + this.barWidthSettingsFormGroup.get('groupWidth').enable({emitEvent: false}); + this.barWidthSettingsFormGroup.get('barWidth').disable({emitEvent: false}); + if (groupWidthRelative) { + this.barWidthSettingsFormGroup.get('groupWidth').get('relativeWidth').enable({emitEvent: false}); + this.barWidthSettingsFormGroup.get('groupWidth').get('absoluteWidth').disable({emitEvent: false}); + } else { + this.barWidthSettingsFormGroup.get('groupWidth').get('relativeWidth').disable({emitEvent: false}); + this.barWidthSettingsFormGroup.get('groupWidth').get('absoluteWidth').enable({emitEvent: false}); + } + } else if (strategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate) { + this.barWidthSettingsFormGroup.get('groupWidth').disable({emitEvent: false}); + this.barWidthSettingsFormGroup.get('barWidth').enable({emitEvent: false}); + if (barWidthRelative) { + this.barWidthSettingsFormGroup.get('barWidth').get('relativeWidth').enable({emitEvent: false}); + this.barWidthSettingsFormGroup.get('barWidth').get('absoluteWidth').disable({emitEvent: false}); + } else { + this.barWidthSettingsFormGroup.get('barWidth').get('relativeWidth').disable({emitEvent: false}); + this.barWidthSettingsFormGroup.get('barWidth').get('absoluteWidth').enable({emitEvent: false}); + } + } + } + + private updateModel() { + this.modelValue = this.barWidthSettingsFormGroup.getRawValue(); + this.propagateChange(this.modelValue); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts index e741314315..b741a8e358 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts @@ -106,6 +106,9 @@ import { EntityAliasInputComponent } from '@home/components/widget/lib/settings/ import { TimeSeriesChartThresholdSettingsPanelComponent } from '@home/components/widget/lib/settings/common/chart/time-series-chart-threshold-settings-panel.component'; +import { + TimeSeriesNoAggregationBarWidthSettingsComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component'; @NgModule({ declarations: [ @@ -146,6 +149,7 @@ import { TimeSeriesChartThresholdsPanelComponent, TimeSeriesChartThresholdRowComponent, TimeSeriesChartThresholdSettingsPanelComponent, + TimeSeriesNoAggregationBarWidthSettingsComponent, DataKeyInputComponent, EntityAliasInputComponent ], @@ -192,6 +196,7 @@ import { TimeSeriesChartThresholdsPanelComponent, TimeSeriesChartThresholdRowComponent, TimeSeriesChartThresholdSettingsPanelComponent, + TimeSeriesNoAggregationBarWidthSettingsComponent, DataKeyInputComponent, EntityAliasInputComponent ], 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 b32cfb7d38..1cef32ac6b 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6629,8 +6629,10 @@ "no-aggregation-bar-width-strategy": "Bar width strategy for non-aggregated data", "no-aggregation-bar-width-strategy-group": "Group", "no-aggregation-bar-width-strategy-separate": "Separate", - "bar-group-interval-width": "Bar group interval width", - "separate-bar-width": "Separate bar width", + "bar-group-width": "Bar group width", + "bar-width": "Bar width", + "bar-width-relative": "Percentage of time window", + "bar-width-absolute": "Absolute (ms)", "threshold": { "thresholds": "Thresholds", "source": "Source", diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index dfe6667afd..e2390c795d 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -29,9 +29,11 @@ @media #{$breakpoint} { @include form-row-column; .mat-mdc-form-field, tb-unit-input { - width: auto; - &.medium-width { + &:not(.fixed-width) { width: auto; + &.medium-width { + width: auto; + } } } } From fa14a5ffdcce82676070ee25a381319a68810ce9 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 7 Mar 2024 17:55:09 +0200 Subject: [PATCH 321/397] Update widget.models.ts --- ui-ngx/src/app/shared/models/widget.models.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts index de875c02ae..c1824be6f7 100644 --- a/ui-ngx/src/app/shared/models/widget.models.ts +++ b/ui-ngx/src/app/shared/models/widget.models.ts @@ -553,7 +553,7 @@ export enum WidgetMobileActionType { takeScreenshot = 'takeScreenshot' } -export const widgetActionTypes = Object.keys(WidgetActionType); +export const widgetActionTypes = Object.keys(WidgetActionType) as WidgetActionType[]; export const widgetActionTypeTranslationMap = new Map( [ From ad9944e9f99523b8d7d0ad5066d8b8167d20206d Mon Sep 17 00:00:00 2001 From: kalytka Date: Thu, 7 Mar 2024 18:38:52 +0200 Subject: [PATCH 322/397] Refactoring --- ui-ngx/src/assets/dashboard/api_usage.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/assets/dashboard/api_usage.json b/ui-ngx/src/assets/dashboard/api_usage.json index 5618494261..00793db02c 100644 --- a/ui-ngx/src/assets/dashboard/api_usage.json +++ b/ui-ngx/src/assets/dashboard/api_usage.json @@ -2063,7 +2063,7 @@ "realtimeType": 0, "timewindowMs": 86400000, "quickInterval": "CURRENT_DAY", - "interval": 300000 + "interval": 3600000 }, "aggregation": { "type": "NONE", @@ -7922,7 +7922,7 @@ "dashboardLogoUrl": null, "hideToolbar": false, "showUpdateDashboardImage": false, - "dashboardCss": ".tb-time-series-chart-panel {\n padding: 13px;\n}\n\n.tb-time-series-chart-panel {\n gap: 0; \n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n\n.card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n.card .unit {\n color: #666666;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} " + "dashboardCss": ".tb-time-series-chart-panel {\n padding: 13px;\n}\n\n.tb-time-series-chart-content {\n gap: 0; \n}\n\n.tb-time-series-chart-panel {\n gap: 8px; \n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n\n.card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n.card .unit {\n color: #666666;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} " } }, "name": "Api Usage" From 71583c5a292b33ef73700718d1386f7cf2df7bb3 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 7 Mar 2024 17:41:51 +0100 Subject: [PATCH 323/397] TbAbstractGetAttributesNode: get latest moved to the last step because SqlTimeseriesLatestDao.findLatest() effectively do blocking DB call, so getting attr async will do the job without awaiting the latest response. --- .../rule/engine/metadata/TbAbstractGetAttributesNode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetAttributesNode.java index fab1893702..7cf144ec66 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbAbstractGetAttributesNode.java @@ -99,10 +99,10 @@ public abstract class TbAbstractGetAttributesNode>> failuresPairSet = ConcurrentHashMap.newKeySet(); var getKvEntryPairFutures = Futures.allAsList( - getLatestTelemetry(ctx, entityId, TbNodeUtils.processPatterns(config.getLatestTsKeyNames(), msg), failuresPairSet), getAttrAsync(ctx, entityId, CLIENT_SCOPE, TbNodeUtils.processPatterns(config.getClientAttributeNames(), msg), failuresPairSet), getAttrAsync(ctx, entityId, SHARED_SCOPE, TbNodeUtils.processPatterns(config.getSharedAttributeNames(), msg), failuresPairSet), - getAttrAsync(ctx, entityId, SERVER_SCOPE, TbNodeUtils.processPatterns(config.getServerAttributeNames(), msg), failuresPairSet) + getAttrAsync(ctx, entityId, SERVER_SCOPE, TbNodeUtils.processPatterns(config.getServerAttributeNames(), msg), failuresPairSet), + getLatestTelemetry(ctx, entityId, TbNodeUtils.processPatterns(config.getLatestTsKeyNames(), msg), failuresPairSet) ); withCallback(getKvEntryPairFutures, futuresList -> { var msgMetaData = msg.getMetaData().copy(); From db36fb2c476e415dae93ce44f139a4aac7c272a1 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 7 Mar 2024 18:53:31 +0200 Subject: [PATCH 324/397] UI: Improve time series chart widget layout. --- .../widget/lib/chart/time-series-chart-widget.component.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss index 9d990c50a7..7da3d8e4b5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss @@ -23,7 +23,7 @@ $maxLegendHeight: 35%; position: relative; display: flex; flex-direction: column; - gap: 16px; + gap: 8px; padding: 20px 24px 24px 24px; > div:not(.tb-time-series-chart-overlay) { z-index: 1; @@ -44,7 +44,7 @@ $maxLegendHeight: 35%; min-height: 0; display: flex; flex-direction: column; - gap: 16px; + gap: 8px; &.legend-top { flex-direction: column-reverse; } From e364d15da57c6b3b38b25f91038bee6a5ba712fc Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 7 Mar 2024 19:57:19 +0200 Subject: [PATCH 325/397] UI: Time series chart: Add Y axis ticks formatter function. --- .../lib/chart/time-series-chart.models.ts | 22 +++++++++- ...eries-chart-widget-settings.component.html | 2 + ...-series-chart-axis-settings.component.html | 41 ++++++++++++------- ...me-series-chart-axis-settings.component.ts | 18 +++++++- .../assets/locale/locale.constant-en_US.json | 1 + 5 files changed, 66 insertions(+), 18 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index fa349252b7..edfaa3692d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -25,7 +25,7 @@ import { import { ComponentStyle, Font, simpleDateFormat, textStyle } from '@shared/models/widget-settings.models'; import { XAXisOption, YAXisOption } from 'echarts/types/dist/shared'; import { CustomSeriesOption, LineSeriesOption } from 'echarts/charts'; -import { formatValue, isDefinedAndNotNull, isUndefinedOrNull, parseFunction } from '@core/utils'; +import { formatValue, isDefinedAndNotNull, isUndefined, isUndefinedOrNull, parseFunction } from '@core/utils'; import { LinearGradientObject } from 'zrender/lib/graphic/LinearGradient'; import tinycolor from 'tinycolor2'; import Axis2D from 'echarts/types/src/coord/cartesian/Axis2D'; @@ -293,6 +293,7 @@ export interface TimeSeriesChartYAxisSettings extends TimeSeriesChartAxisSetting min?: number | string; max?: number | string; intervalCalculator?: string; + ticksFormatter?: string; } export interface TimeSeriesChartThreshold { @@ -441,6 +442,7 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { lineHeight: '1' }, tickLabelColor: timeSeriesChartColorScheme['axis.tickLabel'].light, + ticksFormatter: null, showTicks: true, ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, showLine: true, @@ -647,6 +649,7 @@ export interface TimeSeriesChartYAxis { units: string; option: YAXisOption & ValueAxisBaseOption; intervalCalculator?: (axis: Axis2D) => number; + ticksFormatter?: (value: any) => string; } export const createTimeSeriesYAxis = (axisId: string, units: string, @@ -656,6 +659,10 @@ export const createTimeSeriesYAxis = (axisId: string, units: string, settings.tickLabelColor, darkMode, 'axis.tickLabel'); const yAxisNameStyle = createChartTextStyle(settings.labelFont, settings.labelColor, darkMode, 'axis.label'); + let ticksFormatter: (value: any) => string; + if (settings.ticksFormatter && settings.ticksFormatter.length) { + ticksFormatter = parseFunction(settings.ticksFormatter, ['value']); + } const yAxis: TimeSeriesChartYAxis = { id: axisId, units, @@ -699,7 +706,18 @@ export const createTimeSeriesYAxis = (axisId: string, units: string, fontWeight: yAxisTickLabelStyle.fontWeight, fontFamily: yAxisTickLabelStyle.fontFamily, fontSize: yAxisTickLabelStyle.fontSize, - formatter: (value: any) => formatValue(value, decimals, units, false) + formatter: (value: any) => { + let result: string; + if (ticksFormatter) { + try { + result = ticksFormatter(value); + } catch (_e) {} + } + if (isUndefined(result)) { + result = formatValue(value, decimals, units, false); + } + return result; + } }, splitLine: { show: settings.showSplitLines, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html index a754dec0b4..35f0d147ac 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html @@ -41,10 +41,12 @@
    widgets.time-series-chart.axis.axes
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html index b12e322b17..24f3dc0883 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html @@ -56,21 +56,32 @@
    -
    - -
    widgets.time-series-chart.axis.tick-labels
    -
    -
    - - - - +
    +
    + +
    widgets.time-series-chart.axis.tick-labels
    +
    +
    + + + + +
    +
    +
    + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts index ab20727bdf..328574d648 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts @@ -23,6 +23,8 @@ import { TimeSeriesChartYAxisSettings } from '@home/components/widget/lib/chart/time-series-chart.models'; import { merge } from 'rxjs'; +import { coerceBoolean } from '@shared/decorators/coercion'; +import { WidgetService } from '@core/http/widget.service'; @Component({ selector: 'tb-time-series-chart-axis-settings', @@ -46,19 +48,26 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu timeSeriesAxisPositionTranslations = timeSeriesAxisPositionTranslations; + functionScopeVariables = this.widgetService.getWidgetScopeVariables(); + @Input() disabled: boolean; @Input() axisType: 'xAxis' | 'yAxis' = 'xAxis'; + @Input() + @coerceBoolean() + advanced = false; + private modelValue: TimeSeriesChartAxisSettings | TimeSeriesChartYAxisSettings; private propagateChange = null; public axisSettingsFormGroup: UntypedFormGroup; - constructor(private fb: UntypedFormBuilder) { + constructor(private fb: UntypedFormBuilder, + private widgetService: WidgetService,) { } ngOnInit(): void { @@ -85,6 +94,7 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu splitLinesColor: [null, []] }); if (this.axisType === 'yAxis') { + this.axisSettingsFormGroup.addControl('ticksFormatter', this.fb.control(null, [])); this.axisSettingsFormGroup.addControl('min', this.fb.control(null, [])); this.axisSettingsFormGroup.addControl('max', this.fb.control(null, [])); } @@ -140,9 +150,15 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu if (showTickLabels) { this.axisSettingsFormGroup.get('tickLabelFont').enable({emitEvent: false}); this.axisSettingsFormGroup.get('tickLabelColor').enable({emitEvent: false}); + if (this.axisType === 'yAxis') { + this.axisSettingsFormGroup.get('ticksFormatter').enable({emitEvent: false}); + } } else { this.axisSettingsFormGroup.get('tickLabelFont').disable({emitEvent: false}); this.axisSettingsFormGroup.get('tickLabelColor').disable({emitEvent: false}); + if (this.axisType === 'yAxis') { + this.axisSettingsFormGroup.get('ticksFormatter').disable({emitEvent: false}); + } } if (showTicks) { this.axisSettingsFormGroup.get('ticksColor').enable({emitEvent: false}); 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 1cef32ac6b..216ed878b2 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6677,6 +6677,7 @@ "position-top": "Top", "position-bottom": "Bottom", "tick-labels": "Tick labels", + "ticks-formatter-function": "Ticks formatter function", "show-ticks": "Show ticks", "show-line": "Show line", "show-split-lines": "Show split lines", From c8abb9ed8eefa3b2bd9df16db1f754d014d2d0f7 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 7 Mar 2024 19:01:10 +0100 Subject: [PATCH 326/397] Validator.validateString implementation with function --- .../thingsboard/server/dao/service/Validator.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/Validator.java b/dao/src/main/java/org/thingsboard/server/dao/service/Validator.java index 77f81d639f..16454e5914 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/Validator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/Validator.java @@ -27,6 +27,7 @@ import org.thingsboard.server.dao.exception.IncorrectParameterException; import java.util.List; import java.util.UUID; +import java.util.function.Function; import java.util.regex.Pattern; public class Validator { @@ -59,6 +60,18 @@ public class Validator { } } + /* + * This method validate String string. If string is invalid than throw + * IncorrectParameterException exception + * + * @param val the value + * @param errorMessageFunction the error message function that apply value + */ + public static void validateString(String val, Function errorMessageFunction) { + if (val == null || val.isEmpty()) { + throw new IncorrectParameterException(errorMessageFunction.apply(val)); + } + } /** * This method validate long value. If value isn't positive than throw From 8c513bbf82b0c023acfa2789ee4fb012fe4dcc33 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 7 Mar 2024 19:03:14 +0100 Subject: [PATCH 327/397] BaseTimeseriesService reduce memory footprint at findLatest --- .../dao/timeseries/BaseTimeseriesService.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java index 1f77fa3c1d..8d04d1f570 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java @@ -43,6 +43,7 @@ import org.thingsboard.server.dao.entityview.EntityViewService; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.service.Validator; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -126,18 +127,22 @@ public class BaseTimeseriesService implements TimeseriesService { @Override public ListenableFuture> findLatest(TenantId tenantId, EntityId entityId, Collection keys) { validate(entityId); - List> futures = Lists.newArrayListWithExpectedSize(keys.size()); - keys.forEach(key -> Validator.validateString(key, "Incorrect key " + key)); - keys.forEach(key -> futures.add(timeseriesLatestDao.findLatest(tenantId, entityId, key))); + List> futures = new ArrayList<>(keys.size()); + keys.forEach(key -> Validator.validateString(key, k -> "Incorrect key " + k)); + for (String key : keys) { + futures.add(timeseriesLatestDao.findLatest(tenantId, entityId, key)); + } return Futures.allAsList(futures); } @Override public List findLatestSync(TenantId tenantId, EntityId entityId, Collection keys) { validate(entityId); - List latestEntries = Lists.newArrayListWithExpectedSize(keys.size()); - keys.forEach(key -> Validator.validateString(key, "Incorrect key " + key)); - keys.forEach(key -> latestEntries.add(timeseriesLatestDao.findLatestSync(tenantId, entityId, key))); + List latestEntries = new ArrayList(keys.size()); + keys.forEach(key -> Validator.validateString(key, k -> "Incorrect key " + k)); + for (String key : keys) { + latestEntries.add(timeseriesLatestDao.findLatestSync(tenantId, entityId, key)); + } return latestEntries; } From 45e9a9f642b9c5167738ba73437fbab533e49fb1 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 7 Mar 2024 20:26:59 +0100 Subject: [PATCH 328/397] Validator.validateEntityId with function added to reduce an overhead --- .../thingsboard/server/dao/service/Validator.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/Validator.java b/dao/src/main/java/org/thingsboard/server/dao/service/Validator.java index 16454e5914..b3a121baf6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/Validator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/Validator.java @@ -47,6 +47,19 @@ public class Validator { } } + /** + * This method validate EntityId entity id. If entity id is invalid than throw + * IncorrectParameterException exception + * + * @param entityId the entityId + * @param errorMessageFunction the error message for exception that apply entityId + */ + public static void validateEntityId(EntityId entityId, Function errorMessageFunction) { + if (entityId == null || entityId.getId() == null) { + throw new IncorrectParameterException(errorMessageFunction.apply(entityId)); + } + } + /** * This method validate String string. If string is invalid than throw * IncorrectParameterException exception From c97cbbefa3199c4401d191e2803310a6efb59468 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Thu, 7 Mar 2024 20:27:29 +0100 Subject: [PATCH 329/397] BaseTimeseriesService reduce memory footprint at validateEntityId --- .../server/dao/timeseries/BaseTimeseriesService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java index 8d04d1f570..50c884f86e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java @@ -286,7 +286,7 @@ public class BaseTimeseriesService implements TimeseriesService { } private static void validate(EntityId entityId) { - Validator.validateEntityId(entityId, "Incorrect entityId " + entityId); + Validator.validateEntityId(entityId, id -> "Incorrect entityId " + id); } private void validate(ReadTsKvQuery query) { From 6b482d1cb5d5f90f9d9faa31cf9e87aa3578a111 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 8 Mar 2024 11:04:50 +0200 Subject: [PATCH 330/397] UI: Improved margin and config new widgets --- ui-ngx/src/assets/dashboard/api_usage.json | 359 +++++++++++++++------ 1 file changed, 268 insertions(+), 91 deletions(-) diff --git a/ui-ngx/src/assets/dashboard/api_usage.json b/ui-ngx/src/assets/dashboard/api_usage.json index 00793db02c..d5ed8d5304 100644 --- a/ui-ngx/src/assets/dashboard/api_usage.json +++ b/ui-ngx/src/assets/dashboard/api_usage.json @@ -97,7 +97,8 @@ "displayTimewindow": true, "widgetCss": "", "pageSize": 1024, - "noDataDisplayMessage": "" + "noDataDisplayMessage": "", + "configMode": "basic" }, "id": "a669cf86-e715-efa4-dd9a-b839abf499e9", "typeFullFqn": "system.cards.timeseries_table" @@ -1368,7 +1369,7 @@ "timezone": null }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -1439,8 +1440,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 2400000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 2400000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -1505,7 +1514,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": { "headerButton": [ { @@ -1679,7 +1688,7 @@ "timezone": null }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -1750,8 +1759,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 2400000, - "separateBarWidth": 2400000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 2400000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -1816,7 +1833,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": { "headerButton": [ { @@ -2072,7 +2089,7 @@ "timezone": null }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -2143,8 +2160,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 2400000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 2400000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -2209,7 +2234,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": { "headerButton": [ { @@ -2387,7 +2412,7 @@ "timezone": null }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -2458,8 +2483,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 2400000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 2400000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -2524,7 +2557,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": { "headerButton": [ { @@ -2698,7 +2731,7 @@ "timezone": null }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -2769,8 +2802,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 2400000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 2400000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -2835,7 +2876,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": { "headerButton": [ { @@ -3086,7 +3127,7 @@ "timezone": null }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -3157,8 +3198,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 2400000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 2400000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -3223,7 +3272,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": { "headerButton": [ { @@ -3401,7 +3450,7 @@ "timezone": null }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -3470,8 +3519,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -3536,7 +3593,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -3703,7 +3760,7 @@ "timezone": null }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -3772,8 +3829,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -3838,7 +3903,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -3962,7 +4027,7 @@ "timezone": null }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -4031,8 +4096,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -4097,7 +4170,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -4212,7 +4285,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -4281,8 +4354,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 900000000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 900000000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -4347,7 +4428,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -4478,7 +4559,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -4547,8 +4628,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -4613,7 +4702,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -4744,7 +4833,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -4813,8 +4902,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 900000000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 900000000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -4994,7 +5091,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -5063,8 +5160,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -5129,7 +5234,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -5244,7 +5349,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -5313,8 +5418,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 900000000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 900000000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -5494,7 +5607,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -5563,8 +5676,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -5744,7 +5865,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -5813,8 +5934,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 900000000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 900000000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -5994,7 +6123,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -6063,8 +6192,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -6244,7 +6381,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -6313,8 +6450,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -6494,7 +6639,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -6563,8 +6708,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 900000000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 900000000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -6744,7 +6897,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -6813,8 +6966,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 900000000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 900000000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -7056,7 +7217,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -7125,8 +7286,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -7190,7 +7359,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -7331,7 +7500,7 @@ } }, "showTitle": true, - "backgroundColor": "rgba(0, 0, 0, 0)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { @@ -7400,8 +7569,16 @@ }, "noAggregationBarWidthSettings": { "strategy": "group", - "groupIntervalWidth": 1800000, - "separateBarWidth": 1000 + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, "legendLabelFont": { @@ -7465,7 +7642,7 @@ "dropShadow": true, "enableFullscreen": true, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -7602,7 +7779,7 @@ "autoFillHeight": true, "backgroundImageUrl": null, "mobileAutoFillHeight": false, - "mobileRowHeight": 70, + "mobileRowHeight": 100, "outerMargin": true } } @@ -7631,7 +7808,7 @@ "backgroundColor": "#eeeeee", "color": "rgba(0,0,0,0.870588)", "columns": 24, - "margin": 10, + "margin": 5, "backgroundSizeMode": "100%", "autoFillHeight": true, "backgroundImageUrl": null, @@ -7649,13 +7826,13 @@ "main": { "widgets": { "c77e417c-ad9d-8e23-3ea1-c75edd653bc0": { - "sizeX": 25, + "sizeX": 24, "sizeY": 6, "row": 0, "col": 0 }, "870904d2-d2e1-a1b9-ce56-b03fd47259b5": { - "sizeX": 25, + "sizeX": 24, "sizeY": 6, "row": 6, "col": 0 @@ -7665,7 +7842,7 @@ "backgroundColor": "#eeeeee", "color": "rgba(0,0,0,0.870588)", "columns": 24, - "margin": 10, + "margin": 5, "backgroundSizeMode": "100%", "autoFillHeight": true, "backgroundImageUrl": null, @@ -7699,7 +7876,7 @@ "backgroundColor": "#eeeeee", "color": "rgba(0,0,0,0.870588)", "columns": 24, - "margin": 10, + "margin": 5, "backgroundSizeMode": "100%", "autoFillHeight": true, "backgroundImageUrl": null, @@ -7739,7 +7916,7 @@ "backgroundColor": "#eeeeee", "color": "rgba(0,0,0,0.870588)", "columns": 24, - "margin": 10, + "margin": 5, "backgroundSizeMode": "100%", "autoFillHeight": true, "backgroundImageUrl": null, @@ -7785,7 +7962,7 @@ "backgroundColor": "#eeeeee", "color": "rgba(0,0,0,0.870588)", "columns": 24, - "margin": 10, + "margin": 5, "backgroundSizeMode": "100%", "autoFillHeight": true, "backgroundImageUrl": null, @@ -7819,7 +7996,7 @@ "backgroundColor": "#eeeeee", "color": "rgba(0,0,0,0.870588)", "columns": 24, - "margin": 10, + "margin": 5, "backgroundSizeMode": "100%", "autoFillHeight": true, "backgroundImageUrl": null, @@ -7853,7 +8030,7 @@ "backgroundColor": "#eeeeee", "color": "rgba(0,0,0,0.870588)", "columns": 24, - "margin": 10, + "margin": 5, "backgroundSizeMode": "100%", "autoFillHeight": true, "backgroundImageUrl": null, From c2183be6f551021a24aab2e4742261e3b8161504 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Fri, 8 Mar 2024 10:39:56 +0100 Subject: [PATCH 331/397] BaseTimeseriesService Memory footprint reduced. replaced Lists.newArrayListWithExpectedSize with new ArrayList(size) as we are always use fixed size array and never exceed the initial size. The newArrayListWithExpectedSize implementation adds some additional space to grow beyond initial size. --- .../dao/timeseries/BaseTimeseriesService.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java index 50c884f86e..cfba6786f3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/BaseTimeseriesService.java @@ -16,7 +16,6 @@ package org.thingsboard.server.dao.timeseries; import com.google.common.base.Function; -import com.google.common.collect.Lists; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; @@ -138,7 +137,7 @@ public class BaseTimeseriesService implements TimeseriesService { @Override public List findLatestSync(TenantId tenantId, EntityId entityId, Collection keys) { validate(entityId); - List latestEntries = new ArrayList(keys.size()); + List latestEntries = new ArrayList<>(keys.size()); keys.forEach(key -> Validator.validateString(key, k -> "Incorrect key " + k)); for (String key : keys) { latestEntries.add(timeseriesLatestDao.findLatestSync(tenantId, entityId, key)); @@ -170,7 +169,7 @@ public class BaseTimeseriesService implements TimeseriesService { @Override public ListenableFuture save(TenantId tenantId, EntityId entityId, TsKvEntry tsKvEntry) { validate(entityId); - List> futures = Lists.newArrayListWithExpectedSize(INSERTS_PER_ENTRY); + List> futures = new ArrayList<>(INSERTS_PER_ENTRY); saveAndRegisterFutures(tenantId, futures, entityId, tsKvEntry, 0L); return Futures.transform(Futures.allAsList(futures), SUM_ALL_INTEGERS, MoreExecutors.directExecutor()); } @@ -187,7 +186,7 @@ public class BaseTimeseriesService implements TimeseriesService { private ListenableFuture doSave(TenantId tenantId, EntityId entityId, List tsKvEntries, long ttl, boolean saveLatest) { int inserts = saveLatest ? INSERTS_PER_ENTRY : INSERTS_PER_ENTRY_WITHOUT_LATEST; - List> futures = Lists.newArrayListWithExpectedSize(tsKvEntries.size() * inserts); + List> futures = new ArrayList<>(tsKvEntries.size() * inserts); for (TsKvEntry tsKvEntry : tsKvEntries) { if (saveLatest) { saveAndRegisterFutures(tenantId, futures, entityId, tsKvEntry, ttl); @@ -200,7 +199,7 @@ public class BaseTimeseriesService implements TimeseriesService { @Override public ListenableFuture> saveLatest(TenantId tenantId, EntityId entityId, List tsKvEntries) { - List> futures = Lists.newArrayListWithExpectedSize(tsKvEntries.size()); + List> futures = new ArrayList<>(tsKvEntries.size()); for (TsKvEntry tsKvEntry : tsKvEntries) { futures.add(timeseriesLatestDao.saveLatest(tenantId, entityId, tsKvEntry)); } @@ -247,7 +246,7 @@ public class BaseTimeseriesService implements TimeseriesService { public ListenableFuture> remove(TenantId tenantId, EntityId entityId, List deleteTsKvQueries) { validate(entityId); deleteTsKvQueries.forEach(BaseTimeseriesService::validate); - List> futures = Lists.newArrayListWithExpectedSize(deleteTsKvQueries.size() * DELETES_PER_ENTRY); + List> futures = new ArrayList<>(deleteTsKvQueries.size() * DELETES_PER_ENTRY); for (DeleteTsKvQuery tsKvQuery : deleteTsKvQueries) { deleteAndRegisterFutures(tenantId, futures, entityId, tsKvQuery); } @@ -257,7 +256,7 @@ public class BaseTimeseriesService implements TimeseriesService { @Override public ListenableFuture> removeLatest(TenantId tenantId, EntityId entityId, Collection keys) { validate(entityId); - List> futures = Lists.newArrayListWithExpectedSize(keys.size()); + List> futures = new ArrayList<>(keys.size()); for (String key : keys) { DeleteTsKvQuery query = new BaseDeleteTsKvQuery(key, 0, System.currentTimeMillis(), false); futures.add(timeseriesLatestDao.removeLatest(tenantId, entityId, query)); From 59154be6c8d5936a12e839043739de674f3b79b9 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 8 Mar 2024 12:37:23 +0200 Subject: [PATCH 332/397] UI: Fixed not updated action source in widget action --- .../action/widget-action-dialog.component.ts | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts index b10085c294..2c7f94b8d5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/action/widget-action-dialog.component.ts @@ -20,11 +20,11 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { + FormBuilder, + FormControl, + FormGroup, FormGroupDirective, NgForm, - UntypedFormBuilder, - UntypedFormControl, - UntypedFormGroup, ValidatorFn, Validators } from '@angular/forms'; @@ -32,13 +32,15 @@ import { Subject } from 'rxjs'; import { Router } from '@angular/router'; import { DialogComponent } from '@app/shared/components/dialog.component'; import { + toWidgetActionDescriptor, WidgetActionCallbacks, WidgetActionDescriptorInfo, WidgetActionsData } from '@home/components/widget/action/manage-widget-actions.component.models'; import { UtilsService } from '@core/services/utils.service'; import { - actionDescriptorToAction, defaultWidgetAction, + actionDescriptorToAction, + defaultWidgetAction, WidgetActionSource, widgetType } from '@shared/models/widget.models'; @@ -65,7 +67,7 @@ export class WidgetActionDialogComponent extends DialogComponent(); - widgetActionFormGroup: UntypedFormGroup; + widgetActionFormGroup: FormGroup; isAdd: boolean; action: WidgetActionDescriptorInfo; @@ -83,7 +85,7 @@ export class WidgetActionDialogComponent extends DialogComponent, - public fb: UntypedFormBuilder) { + public fb: FormBuilder) { super(store, router, dialogRef); this.isAdd = data.isAdd; if (this.isAdd) { @@ -100,19 +102,14 @@ export class WidgetActionDialogComponent extends DialogComponent { + return (c: FormControl) => { const newName = c.value; - const valid = this.checkActionName(newName, this.widgetActionFormGroup.get('actionSourceId').value); + const valid = this.checkActionName(newName, c.parent?.get('actionSourceId').value); return !valid ? { actionNameNotUnique: true } : null; @@ -182,7 +179,7 @@ export class WidgetActionDialogComponent extends DialogComponent Date: Fri, 8 Mar 2024 15:35:36 +0200 Subject: [PATCH 333/397] UI: API usage dashboard add tick format function --- ui-ngx/src/assets/dashboard/api_usage.json | 138 +++++++++++++++------ 1 file changed, 97 insertions(+), 41 deletions(-) diff --git a/ui-ngx/src/assets/dashboard/api_usage.json b/ui-ngx/src/assets/dashboard/api_usage.json index d5ed8d5304..7d9eefd18d 100644 --- a/ui-ngx/src/assets/dashboard/api_usage.json +++ b/ui-ngx/src/assets/dashboard/api_usage.json @@ -1405,6 +1405,7 @@ "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "min": null, "max": null }, @@ -1430,7 +1431,7 @@ "weight": "400", "lineHeight": "1" }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "tickLabelColor": null, "showTicks": true, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": true, @@ -1443,7 +1444,7 @@ "groupWidth": { "relative": false, "relativeWidth": 2, - "absoluteWidth": 2400000 + "absoluteWidth": 3600000 }, "barWidth": { "relative": true, @@ -1724,6 +1725,7 @@ "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "min": null, "max": null }, @@ -1762,7 +1764,7 @@ "groupWidth": { "relative": false, "relativeWidth": 2, - "absoluteWidth": 2400000 + "absoluteWidth": 3600000 }, "barWidth": { "relative": true, @@ -2125,6 +2127,7 @@ "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "min": null, "max": null }, @@ -2163,7 +2166,7 @@ "groupWidth": { "relative": false, "relativeWidth": 2, - "absoluteWidth": 2400000 + "absoluteWidth": 3600000 }, "barWidth": { "relative": true, @@ -2448,6 +2451,7 @@ "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "min": null, "max": null }, @@ -2486,7 +2490,7 @@ "groupWidth": { "relative": false, "relativeWidth": 2, - "absoluteWidth": 2400000 + "absoluteWidth": 3600000 }, "barWidth": { "relative": true, @@ -2767,6 +2771,7 @@ "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "min": null, "max": null }, @@ -2805,7 +2810,7 @@ "groupWidth": { "relative": false, "relativeWidth": 2, - "absoluteWidth": 2400000 + "absoluteWidth": 3600000 }, "barWidth": { "relative": true, @@ -3163,6 +3168,7 @@ "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "min": null, "max": null }, @@ -3201,7 +3207,7 @@ "groupWidth": { "relative": false, "relativeWidth": 2, - "absoluteWidth": 2400000 + "absoluteWidth": 3600000 }, "barWidth": { "relative": true, @@ -3485,7 +3491,10 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -3790,12 +3799,15 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "showTicks": true, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -3830,9 +3842,9 @@ "noAggregationBarWidthSettings": { "strategy": "group", "groupWidth": { - "relative": false, - "relativeWidth": 2, - "absoluteWidth": 1800000 + "relative": true, + "relativeWidth": 6, + "absoluteWidth": 900000000 }, "barWidth": { "relative": true, @@ -4062,7 +4074,10 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -4315,12 +4330,15 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "showTicks": true, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -4355,8 +4373,8 @@ "noAggregationBarWidthSettings": { "strategy": "group", "groupWidth": { - "relative": false, - "relativeWidth": 2, + "relative": true, + "relativeWidth": 6, "absoluteWidth": 900000000 }, "barWidth": { @@ -4594,7 +4612,10 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -4863,12 +4884,15 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "showTicks": true, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -4903,14 +4927,14 @@ "noAggregationBarWidthSettings": { "strategy": "group", "groupWidth": { - "relative": false, - "relativeWidth": 2, + "relative": true, + "relativeWidth": 6, "absoluteWidth": 900000000 }, "barWidth": { - "relative": true, + "relative": false, "relativeWidth": 2, - "absoluteWidth": 1000 + "absoluteWidth": 900000000 } }, "showLegend": true, @@ -5126,7 +5150,10 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -5379,12 +5406,15 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "showTicks": true, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -5419,8 +5449,8 @@ "noAggregationBarWidthSettings": { "strategy": "group", "groupWidth": { - "relative": false, - "relativeWidth": 2, + "relative": true, + "relativeWidth": 6, "absoluteWidth": 900000000 }, "barWidth": { @@ -5642,7 +5672,10 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -5895,12 +5928,15 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "showTicks": true, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -5935,8 +5971,8 @@ "noAggregationBarWidthSettings": { "strategy": "group", "groupWidth": { - "relative": false, - "relativeWidth": 2, + "relative": true, + "relativeWidth": 6, "absoluteWidth": 900000000 }, "barWidth": { @@ -6158,7 +6194,10 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -6416,7 +6455,10 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -6669,12 +6711,15 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "showTicks": true, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -6709,8 +6754,8 @@ "noAggregationBarWidthSettings": { "strategy": "group", "groupWidth": { - "relative": false, - "relativeWidth": 2, + "relative": true, + "relativeWidth": 6, "absoluteWidth": 900000000 }, "barWidth": { @@ -6927,12 +6972,15 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", "showTicks": true, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -6967,8 +7015,8 @@ "noAggregationBarWidthSettings": { "strategy": "group", "groupWidth": { - "relative": false, - "relativeWidth": 2, + "relative": true, + "relativeWidth": 6, "absoluteWidth": 900000000 }, "barWidth": { @@ -7252,7 +7300,10 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -7308,6 +7359,7 @@ }, "legendLabelColor": "rgba(0, 0, 0, 0.76)", "legendConfig": { + "direction": "column", "position": "bottom", "sortDataKeys": false, "showMin": true, @@ -7535,7 +7587,10 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", + "min": null, + "max": null }, "xAxis": { "show": true, @@ -7591,6 +7646,7 @@ }, "legendLabelColor": "rgba(0, 0, 0, 0.76)", "legendConfig": { + "direction": "column", "position": "bottom", "sortDataKeys": false, "showMin": true, @@ -8099,7 +8155,7 @@ "dashboardLogoUrl": null, "hideToolbar": false, "showUpdateDashboardImage": false, - "dashboardCss": ".tb-time-series-chart-panel {\n padding: 13px;\n}\n\n.tb-time-series-chart-content {\n gap: 0; \n}\n\n.tb-time-series-chart-panel {\n gap: 8px; \n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n\n.card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n.card .unit {\n color: #666666;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} " + "dashboardCss": ".tb-time-series-chart-panel {\n padding: 13px;\n}\n\n.tb-time-series-chart-content {\n gap: 0; \n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n\n.card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n.card .unit {\n color: #666666;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} " } }, "name": "Api Usage" From 59d0f36697c0e7bad424670b4b8c97a7ce3f3652 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Fri, 8 Mar 2024 15:22:16 +0100 Subject: [PATCH 334/397] CachedAttributesService: replaced blocking calls and immediate futures with the true async --- .../attributes/CachedAttributesService.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java b/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java index 1666015a48..8058b0cee5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/attributes/CachedAttributesService.java @@ -113,15 +113,15 @@ public class CachedAttributesService implements AttributesService { validate(entityId, scope); Validator.validateString(attributeKey, "Incorrect attribute key " + attributeKey); - AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, attributeKey); - TbCacheValueWrapper cachedAttributeValue = cache.get(attributeCacheKey); - if (cachedAttributeValue != null) { - hitCounter.increment(); - AttributeKvEntry cachedAttributeKvEntry = cachedAttributeValue.get(); - return Futures.immediateFuture(Optional.ofNullable(cachedAttributeKvEntry)); - } else { - missCounter.increment(); - return cacheExecutor.submit(() -> { + return cacheExecutor.submit(() -> { + AttributeCacheKey attributeCacheKey = new AttributeCacheKey(scope, entityId, attributeKey); + TbCacheValueWrapper cachedAttributeValue = cache.get(attributeCacheKey); + if (cachedAttributeValue != null) { + hitCounter.increment(); + AttributeKvEntry cachedAttributeKvEntry = cachedAttributeValue.get(); + return Optional.ofNullable(cachedAttributeKvEntry); + } else { + missCounter.increment(); var cacheTransaction = cache.newTransactionForKey(attributeCacheKey); try { Optional result = attributesDao.find(tenantId, entityId, scope, attributeKey); @@ -133,8 +133,8 @@ public class CachedAttributesService implements AttributesService { log.debug("Could not find attribute from cache: [{}] [{}] [{}]", entityId, scope, attributeKey, e); throw e; } - }); - } + } + }); } @Override @@ -207,7 +207,8 @@ public class CachedAttributesService implements AttributesService { @Override public ListenableFuture> findAll(TenantId tenantId, EntityId entityId, String scope) { validate(entityId, scope); - return Futures.immediateFuture(attributesDao.findAll(tenantId, entityId, scope)); + // We can`t watch on cache because the keys are unknown. + return jpaExecutorService.submit(() -> attributesDao.findAll(tenantId, entityId, scope)); } @Override From c4b243ef10f7e5b3c6ea534f864c8f13e92e4221 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Fri, 8 Mar 2024 18:20:13 +0100 Subject: [PATCH 335/397] SqlTimeseriesLatestDao async refactoring: replaced Futures.immediateFuture() blocking call with true async using service.submit() and Futures.transformAsync() --- .../dao/sqlts/SqlTimeseriesLatestDao.java | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sqlts/SqlTimeseriesLatestDao.java b/dao/src/main/java/org/thingsboard/server/dao/sqlts/SqlTimeseriesLatestDao.java index 112daf0637..f1a58aa417 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sqlts/SqlTimeseriesLatestDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sqlts/SqlTimeseriesLatestDao.java @@ -151,12 +151,12 @@ public class SqlTimeseriesLatestDao extends BaseAbstractSqlTimeseriesDao impleme @Override public ListenableFuture> findLatestOpt(TenantId tenantId, EntityId entityId, String key) { - return Futures.immediateFuture(Optional.ofNullable(doFindLatest(entityId, key))); + return service.submit(() -> Optional.ofNullable(doFindLatest(entityId, key))); } @Override public ListenableFuture findLatest(TenantId tenantId, EntityId entityId, String key) { - return Futures.immediateFuture(getLatestTsKvEntry(entityId, key)); + return service.submit(() -> getLatestTsKvEntry(entityId, key)); } @Override @@ -221,36 +221,29 @@ public class SqlTimeseriesLatestDao extends BaseAbstractSqlTimeseriesDao impleme } protected ListenableFuture getRemoveLatestFuture(TenantId tenantId, EntityId entityId, DeleteTsKvQuery query) { - TsKvEntry latest = doFindLatest(entityId, query.getKey()); - - if (latest == null) { - return Futures.immediateFuture(new TsKvLatestRemovingResult(query.getKey(), false)); - } - - long ts = latest.getTs(); - ListenableFuture removedLatestFuture; - if (ts >= query.getStartTs() && ts < query.getEndTs()) { - TsKvLatestEntity latestEntity = new TsKvLatestEntity(); - latestEntity.setEntityId(entityId.getId()); - latestEntity.setKey(getOrSaveKeyId(query.getKey())); - removedLatestFuture = service.submit(() -> { + ListenableFuture latestFuture = service.submit(() -> doFindLatest(entityId, query.getKey())); + return Futures.transformAsync(latestFuture, latest -> { + if (latest == null) { + return Futures.immediateFuture(new TsKvLatestRemovingResult(query.getKey(), false)); + } + boolean isRemoved = false; + long ts = latest.getTs(); + if (ts >= query.getStartTs() && ts < query.getEndTs()) { + TsKvLatestEntity latestEntity = new TsKvLatestEntity(); + latestEntity.setEntityId(entityId.getId()); + latestEntity.setKey(getOrSaveKeyId(query.getKey())); tsKvLatestRepository.delete(latestEntity); - return true; - }); - } else { - removedLatestFuture = Futures.immediateFuture(false); - } - - return Futures.transformAsync(removedLatestFuture, isRemoved -> { - if (isRemoved && query.getRewriteLatestIfDeleted()) { - return getNewLatestEntryFuture(tenantId, entityId, query); + isRemoved = true; + if (query.getRewriteLatestIfDeleted()) { + return getNewLatestEntryFuture(tenantId, entityId, query); + } } return Futures.immediateFuture(new TsKvLatestRemovingResult(query.getKey(), isRemoved)); }, MoreExecutors.directExecutor()); } protected ListenableFuture> getFindAllLatestFuture(EntityId entityId) { - return Futures.immediateFuture( + return service.submit(() -> DaoUtil.convertDataList(Lists.newArrayList( searchTsKvLatestRepository.findAllByEntityId(entityId.getId())))); } From c688f516c7d7e73869211673b018f1defa4d0765 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 11 Mar 2024 15:44:56 +0200 Subject: [PATCH 336/397] UI: Multiple Y axes configuration support for time series chart. --- ...e-series-chart-basic-config.component.html | 15 +- ...ime-series-chart-basic-config.component.ts | 39 +++- .../basic/common/data-key-row.component.html | 39 ++-- .../basic/common/data-key-row.component.scss | 17 ++ .../basic/common/data-key-row.component.ts | 46 +++- .../common/data-keys-panel.component.html | 5 +- .../common/data-keys-panel.component.scss | 15 ++ .../basic/common/data-keys-panel.component.ts | 8 + .../aggregated-value-card-widget.component.ts | 30 +-- .../value-chart-card-widget.component.ts | 11 +- .../lib/chart/time-series-chart.models.ts | 216 ++++++++++++++---- .../widget/lib/chart/time-series-chart.ts | 102 +++++++-- ...e-series-chart-key-settings.component.html | 12 + ...ime-series-chart-key-settings.component.ts | 12 +- ...eries-chart-widget-settings.component.html | 15 +- ...-series-chart-widget-settings.component.ts | 37 ++- ...-series-chart-axis-settings.component.html | 18 +- ...me-series-chart-axis-settings.component.ts | 18 +- ...-series-chart-threshold-row.component.html | 28 ++- ...-series-chart-threshold-row.component.scss | 14 ++ ...me-series-chart-threshold-row.component.ts | 32 ++- ...rt-threshold-settings-panel.component.html | 10 + ...hart-threshold-settings-panel.component.ts | 6 +- ...ries-chart-thresholds-panel.component.html | 2 + ...ries-chart-thresholds-panel.component.scss | 11 + ...series-chart-thresholds-panel.component.ts | 5 +- ...e-series-chart-y-axes-panel.component.html | 63 +++++ ...e-series-chart-y-axes-panel.component.scss | 87 +++++++ ...ime-series-chart-y-axes-panel.component.ts | 180 +++++++++++++++ ...ime-series-chart-y-axis-row.component.html | 72 ++++++ ...ime-series-chart-y-axis-row.component.scss | 95 ++++++++ .../time-series-chart-y-axis-row.component.ts | 201 ++++++++++++++++ ...chart-y-axis-settings-panel.component.html | 43 ++++ ...chart-y-axis-settings-panel.component.scss | 49 ++++ ...s-chart-y-axis-settings-panel.component.ts | 66 ++++++ .../common/widget-settings-common.module.ts | 15 ++ ui-ngx/src/app/shared/models/common.ts | 19 ++ .../assets/locale/locale.constant-en_US.json | 10 +- 38 files changed, 1502 insertions(+), 161 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.ts create mode 100644 ui-ngx/src/app/shared/models/common.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html index 3d099c2645..1f62a13c4e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html @@ -25,6 +25,10 @@ forceSingleDatasource formControlName="datasources"> + + + [widgetConfig]="widgetConfig?.config" + [yAxisIds]="yAxisIds">
    widget-config.appearance
    @@ -104,11 +111,7 @@
    -
    widgets.time-series-chart.axis.axes
    - - +
    widgets.time-series-chart.axis.x-axis
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts index 5307147b0e..f9ee35da23 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts @@ -45,7 +45,11 @@ import { TimeSeriesChartWidgetSettings } from '@home/components/widget/lib/chart/time-series-chart-widget.models'; import { EChartsTooltipTrigger } from '@home/components/widget/lib/chart/echarts-widget.models'; -import { TimeSeriesChartType } from '@home/components/widget/lib/chart/time-series-chart.models'; +import { + TimeSeriesChartKeySettings, TimeSeriesChartThreshold, + TimeSeriesChartType, TimeSeriesChartYAxes, + TimeSeriesChartYAxisId +} from '@home/components/widget/lib/chart/time-series-chart.models'; @Component({ selector: 'tb-time-series-chart-basic-config', @@ -63,6 +67,11 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon } } + public get yAxisIds(): TimeSeriesChartYAxisId[] { + const yAxes: TimeSeriesChartYAxes = this.timeSeriesChartWidgetConfigForm.get('yAxes').value; + return Object.keys(yAxes); + } + TimeSeriesChartType = TimeSeriesChartType; EChartsTooltipTrigger = EChartsTooltipTrigger; @@ -86,6 +95,15 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon super(store, widgetConfigComponent); } + public yAxisRemoved(yAxisId: TimeSeriesChartYAxisId): void { + if (this.widgetConfig.config.datasources && this.widgetConfig.config.datasources.length > 1) { + for (let i = 1; i < this.widgetConfig.config.datasources.length; i++) { + const datasource = this.widgetConfig.config.datasources[i]; + this.removeYaxisId(datasource.dataKeys, yAxisId); + } + } + } + protected configForm(): UntypedFormGroup { return this.timeSeriesChartWidgetConfigForm; } @@ -109,6 +127,8 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon this.timeSeriesChartWidgetConfigForm = this.fb.group({ timewindowConfig: [getTimewindowConfig(configData.config), []], datasources: [configData.config.datasources, []], + + yAxes: [settings.yAxes, []], series: [this.getSeries(configData.config.datasources), []], thresholds: [settings.thresholds, []], @@ -126,7 +146,6 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon dataZoom: [settings.dataZoom, []], stack: [settings.stack, []], - yAxis: [settings.yAxis, []], xAxis: [settings.xAxis, []], noAggregationBarWidthSettings: [settings.noAggregationBarWidthSettings, []], @@ -180,7 +199,7 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon this.widgetConfig.config.settings.dataZoom = config.dataZoom; this.widgetConfig.config.settings.stack = config.stack; - this.widgetConfig.config.settings.yAxis = config.yAxis; + this.widgetConfig.config.settings.yAxes = config.yAxes; this.widgetConfig.config.settings.xAxis = config.xAxis; this.widgetConfig.config.settings.noAggregationBarWidthSettings = config.noAggregationBarWidthSettings; @@ -303,6 +322,20 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon } } + private removeYaxisId(series: DataKey[], yAxisId: TimeSeriesChartYAxisId): boolean { + let changed = false; + if (series) { + series.forEach(key => { + const keySettings = ((key.settings || {}) as TimeSeriesChartKeySettings); + if (keySettings.yAxisId === yAxisId) { + keySettings.yAxisId = 'default'; + changed = true; + } + }); + } + return changed; + } + private getCardButtons(config: WidgetConfig): string[] { const buttons: string[] = []; if (isUndefined(config.enableFullscreen) || config.enableFullscreen) { diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html index 3ef6891808..0c8be80bf6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/common/data-key-row.component.html @@ -38,6 +38,30 @@ +
    + + + + + {{ timeSeriesChartSeriesTypeIcons.get(keyRowFormGroup.get('timeSeriesType').value) }} + + + + {{ timeSeriesChartSeriesTypeIcons.get(type) }} + {{ timeSeriesChartSeriesTypeTranslations.get(type) | translate }} + + + +
    +
    + + + + {{ yAxis }} + + + +
    @@ -54,21 +78,6 @@
    widget-config.decimals-suffix
    -
    - - - - - {{ timeSeriesChartSeriesTypeIcons.get(keyRowFormGroup.get('timeSeriesType').value) }} - - - - {{ timeSeriesChartSeriesTypeIcons.get(type) }} - {{ timeSeriesChartSeriesTypeTranslations.get(type) | translate }} - - - -
    = { dataZoom: false, xAxis: { show: false }, - yAxis: { - show: true, - showLine: false, - showTicks: false, - showTickLabels: false, - showSplitLines: true, - min: 'dataMin', - max: 'dataMax', - intervalCalculator: - 'var scale = axis.scale; return !scale.isBlank() ? ((scale.getExtent()[1] - scale.getExtent()[0]) / 2) : undefined;' + yAxes: { + default: { + show: true, + showLine: false, + showTicks: false, + showTickLabels: false, + showSplitLines: true, + min: 'dataMin', + max: 'dataMax', + intervalCalculator: + 'var scale = axis.scale; return !scale.isBlank() ? ((scale.getExtent()[1] - scale.getExtent()[0]) / 2) : undefined;' + } }, tooltipDateInterval: false, tooltipDateFormat: simpleDateFormat('dd MMM yyyy HH:mm:ss') - } as TimeSeriesChartSettings; + }; this.lineChart = new TbTimeSeriesChart(this.ctx, settings, this.chartElement.nativeElement, this.renderer, true); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts index f5a305a247..a7981b3acf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts @@ -57,6 +57,7 @@ import { TimeSeriesChartSeriesType, TimeSeriesChartSettings } from '@home/components/widget/lib/chart/time-series-chart.models'; +import { DeepPartial } from '@shared/models/common'; const layoutHeight = 56; const valueRelativeWidth = 0.35; @@ -162,17 +163,19 @@ export class ValueChartCardWidgetComponent implements OnInit, AfterViewInit, OnD } public ngAfterViewInit() { - const settings: TimeSeriesChartSettings = { + const settings: DeepPartial = { dataZoom: false, xAxis: { show: false }, - yAxis: { - show: false + yAxes: { + default: { + show: false, + } }, tooltipDateInterval: false, tooltipDateFormat: simpleDateFormat('dd MMM yyyy HH:mm:ss') - } as TimeSeriesChartSettings; + }; this.lineChart = new TbTimeSeriesChart(this.ctx, settings, this.chartElement.nativeElement, this.renderer, false); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index edfaa3692d..9af41fa378 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -25,7 +25,15 @@ import { import { ComponentStyle, Font, simpleDateFormat, textStyle } from '@shared/models/widget-settings.models'; import { XAXisOption, YAXisOption } from 'echarts/types/dist/shared'; import { CustomSeriesOption, LineSeriesOption } from 'echarts/charts'; -import { formatValue, isDefinedAndNotNull, isUndefined, isUndefinedOrNull, parseFunction } from '@core/utils'; +import { + formatValue, + isDefinedAndNotNull, + isNumeric, + isUndefined, + isUndefinedOrNull, + mergeDeep, + parseFunction +} from '@core/utils'; import { LinearGradientObject } from 'zrender/lib/graphic/LinearGradient'; import tinycolor from 'tinycolor2'; import Axis2D from 'echarts/types/src/coord/cartesian/Axis2D'; @@ -289,13 +297,82 @@ export interface TimeSeriesChartAxisSettings { splitLinesColor: string; } +export type TimeSeriesChartYAxisId = 'default' | string; + export interface TimeSeriesChartYAxisSettings extends TimeSeriesChartAxisSettings { + id?: TimeSeriesChartYAxisId; + order?: number; + units?: string; + decimals?: number; min?: number | string; max?: number | string; intervalCalculator?: string; ticksFormatter?: string; } +export const timeSeriesChartYAxisValid = (axis: TimeSeriesChartYAxisSettings): boolean => + !(!axis.id || isUndefinedOrNull(axis.order)); + +export const timeSeriesChartYAxisValidator = (control: AbstractControl): ValidationErrors | null => { + const axis: TimeSeriesChartYAxisSettings = control.value; + if (!timeSeriesChartYAxisValid(axis)) { + return { + axis: true + }; + } + return null; +}; + +export const getNextTimeSeriesYAxisId = (axes: TimeSeriesChartYAxisSettings[]): TimeSeriesChartYAxisId => { + let id = 0; + for (const axis of axes) { + const existingId = axis.id; + if (existingId.startsWith('axis')) { + const idSuffix = existingId.substring('axis'.length); + if (isNumeric(idSuffix)) { + id = Math.max(id, Number(idSuffix)); + } + } + } + return 'axis' + (id+1); +}; + +export const defaultTimeSeriesChartYAxisSettings: TimeSeriesChartYAxisSettings = { + units: null, + decimals: 0, + show: true, + label: '', + labelFont: { + family: 'Roboto', + size: 12, + sizeUnit: 'px', + style: 'normal', + weight: '600', + lineHeight: '1' + }, + labelColor: timeSeriesChartColorScheme['axis.label'].light, + position: AxisPosition.left, + showTickLabels: true, + tickLabelFont: { + family: 'Roboto', + size: 12, + sizeUnit: 'px', + style: 'normal', + weight: '400', + lineHeight: '1' + }, + tickLabelColor: timeSeriesChartColorScheme['axis.tickLabel'].light, + ticksFormatter: null, + showTicks: true, + ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, + showLine: true, + lineColor: timeSeriesChartColorScheme['axis.line'].light, + showSplitLines: true, + splitLinesColor: timeSeriesChartColorScheme['axis.splitLine'].light +}; + +export type TimeSeriesChartYAxes = {[id: TimeSeriesChartYAxisId]: TimeSeriesChartYAxisSettings}; + export interface TimeSeriesChartThreshold { type: TimeSeriesChartThresholdType; value?: number; @@ -304,6 +381,7 @@ export interface TimeSeriesChartThreshold { entityAlias?: string; entityKey?: string; entityKeyType?: DataKeyType.attribute | DataKeyType.timeseries; + yAxisId: TimeSeriesChartYAxisId; units?: string; decimals?: number; lineColor: string; @@ -320,7 +398,7 @@ export interface TimeSeriesChartThreshold { } export const timeSeriesChartThresholdValid = (threshold: TimeSeriesChartThreshold): boolean => { - if (!threshold.type) { + if (!threshold.type || !threshold.yAxisId) { return false; } switch (threshold.type) { @@ -355,7 +433,8 @@ export const timeSeriesChartThresholdValidator = (control: AbstractControl): Val export const timeSeriesChartThresholdDefaultSettings: TimeSeriesChartThreshold = { type: TimeSeriesChartThresholdType.constant, - units: '', + yAxisId: 'default', + units: null, decimals: 0, lineColor: timeSeriesChartColorScheme['threshold.line'].light, lineType: TimeSeriesChartLineType.solid, @@ -404,13 +483,61 @@ export interface TimeSeriesChartNoAggregationBarWidthSettings { barWidth?: TimeSeriesChartBarWidth; } +export enum TimeSeriesChartAnimationEasing { + linear = 'linear', + quadraticIn = 'quadraticIn', + quadraticOut = 'quadraticOut', + quadraticInOut = 'quadraticInOut', + cubicIn = 'cubicIn', + cubicOut = 'cubicOut', + cubicInOut = 'cubicInOut', + quarticIn = 'quarticIn', + quarticOut = 'quarticOut', + quarticInOut = 'quarticInOut', + quinticIn = 'quinticIn', + quinticOut = 'quinticOut', + quinticInOut = 'quinticInOut', + sinusoidalIn = 'sinusoidalIn', + sinusoidalOut = 'sinusoidalOut', + sinusoidalInOut = 'sinusoidalInOut', + exponentialIn = 'exponentialIn', + exponentialOut = 'exponentialOut', + exponentialInOut = 'exponentialInOut', + circularIn = 'circularIn', + circularOut = 'circularOut', + circularInOut = 'circularInOut', + elasticIn = 'elasticIn', + elasticOut = 'elasticOut', + elasticInOut = 'elasticInOut', + backIn = 'backIn', + backOut = 'backOut', + backInOut = 'backInOut', + bounceIn = 'bounceIn', + bounceOut = 'bounceOut', + bounceInOut = 'bounceInOut' +} + +export const timeSeriesChartAnimationEasings = Object.keys(TimeSeriesChartAnimationEasing) as TimeSeriesChartAnimationEasing[]; + +export interface TimeSeriesChartAnimationSettings { + animation: boolean; + animationThreshold: number; + animationDuration: number; + animationEasing: TimeSeriesChartAnimationEasing; + animationDelay: number; + animationDurationUpdate: number; + animationEasingUpdate: TimeSeriesChartAnimationEasing; + animationDelayUpdate: number; +} + export interface TimeSeriesChartSettings extends EChartsTooltipWidgetSettings { thresholds: TimeSeriesChartThreshold[]; darkMode: boolean; dataZoom: boolean; stack: boolean; - yAxis: TimeSeriesChartYAxisSettings; + yAxes: TimeSeriesChartYAxes; xAxis: TimeSeriesChartAxisSettings; + animation: TimeSeriesChartAnimationSettings; noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings; } @@ -419,36 +546,10 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { darkMode: false, dataZoom: true, stack: false, - yAxis: { - show: true, - label: '', - labelFont: { - family: 'Roboto', - size: 12, - sizeUnit: 'px', - style: 'normal', - weight: '600', - lineHeight: '1' - }, - labelColor: timeSeriesChartColorScheme['axis.label'].light, - position: AxisPosition.left, - showTickLabels: true, - tickLabelFont: { - family: 'Roboto', - size: 12, - sizeUnit: 'px', - style: 'normal', - weight: '400', - lineHeight: '1' - }, - tickLabelColor: timeSeriesChartColorScheme['axis.tickLabel'].light, - ticksFormatter: null, - showTicks: true, - ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, - showLine: true, - lineColor: timeSeriesChartColorScheme['axis.line'].light, - showSplitLines: true, - splitLinesColor: timeSeriesChartColorScheme['axis.splitLine'].light + yAxes: { + default: mergeDeep({} as TimeSeriesChartYAxisSettings, + defaultTimeSeriesChartYAxisSettings, + { id: 'default', order: 0 } as TimeSeriesChartYAxisSettings) }, xAxis: { show: true, @@ -480,6 +581,16 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { showSplitLines: true, splitLinesColor: timeSeriesChartColorScheme['axis.splitLine'].light }, + animation: { + animation: true, + animationThreshold: 2000, + animationDuration: 1000, + animationEasing: TimeSeriesChartAnimationEasing.cubicOut, + animationDelay: 0, + animationDurationUpdate: 300, + animationEasingUpdate: TimeSeriesChartAnimationEasing.cubicOut, + animationDelayUpdate: 0 + }, noAggregationBarWidthSettings: { strategy: TimeSeriesChartNoAggregationBarWidthStrategy.group, groupWidth: { @@ -558,6 +669,7 @@ export interface BarSeriesSettings { } export interface TimeSeriesChartKeySettings { + yAxisId: TimeSeriesChartYAxisId; showInLegend: boolean; dataHiddenByDefault: boolean; type: TimeSeriesChartSeriesType; @@ -566,6 +678,7 @@ export interface TimeSeriesChartKeySettings { } export const timeSeriesChartKeyDefaultSettings: TimeSeriesChartKeySettings = { + yAxisId: 'default', showInLegend: true, dataHiddenByDefault: false, type: TimeSeriesChartSeriesType.line, @@ -626,6 +739,7 @@ export const timeSeriesChartKeyDefaultSettings: TimeSeriesChartKeySettings = { }; export interface TimeSeriesChartDataItem extends EChartsSeriesItem { + yAxisId: TimeSeriesChartYAxisId; yAxisIndex: number; option?: LineSeriesOption | CustomSeriesOption; barRenderContext?: BarRenderContext; @@ -635,6 +749,7 @@ type TimeSeriesChartThresholdValue = number | string | (number | string)[]; export interface TimeSeriesChartThresholdItem { id: string; + yAxisId: TimeSeriesChartYAxisId; yAxisIndex: number; latestDataKey?: DataKey; units?: string; @@ -646,14 +761,16 @@ export interface TimeSeriesChartThresholdItem { export interface TimeSeriesChartYAxis { id: string; - units: string; + decimals: number; + settings: TimeSeriesChartYAxisSettings; option: YAXisOption & ValueAxisBaseOption; intervalCalculator?: (axis: Axis2D) => number; ticksFormatter?: (value: any) => string; } -export const createTimeSeriesYAxis = (axisId: string, units: string, - decimals: number, settings: TimeSeriesChartYAxisSettings, +export const createTimeSeriesYAxis = (units: string, + decimals: number, + settings: TimeSeriesChartYAxisSettings, darkMode: boolean): TimeSeriesChartYAxis => { const yAxisTickLabelStyle = createChartTextStyle(settings.tickLabelFont, settings.tickLabelColor, darkMode, 'axis.tickLabel'); @@ -664,13 +781,14 @@ export const createTimeSeriesYAxis = (axisId: string, units: string, ticksFormatter = parseFunction(settings.ticksFormatter, ['value']); } const yAxis: TimeSeriesChartYAxis = { - id: axisId, - units, + id: settings.id, + decimals, + settings, option: { show: settings.show, type: 'value', position: settings.position, - id: axisId, + id: settings.id, offset: 0, alignTicks: true, scale: true, @@ -843,13 +961,11 @@ const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[], id: item.id, dataGroupId: item.id, yAxisIndex: item.yAxisIndex, - animation: true, data: [], tooltip: { show: false }, markLine: { - animation: true, lineStyle: { width: item.settings.lineWidth, color: prepareChartThemeColor(item.settings.lineColor, darkMode, 'threshold.line'), @@ -956,16 +1072,19 @@ const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], }; export const updateDarkMode = (options: EChartsOption, settings: TimeSeriesChartSettings, + yAxisList: TimeSeriesChartYAxis[], dataItems: TimeSeriesChartDataItem[], thresholdDataItems: TimeSeriesChartThresholdItem[], darkMode: boolean): EChartsOption => { options.darkMode = darkMode; if (Array.isArray(options.yAxis)) { - for (const yAxis of options.yAxis) { - yAxis.nameTextStyle.color = prepareChartThemeColor(settings.yAxis.labelColor, darkMode, 'axis.label'); - yAxis.axisLabel.color = prepareChartThemeColor(settings.yAxis.tickLabelColor, darkMode, 'axis.tickLabel'); - yAxis.axisLine.lineStyle.color = prepareChartThemeColor(settings.yAxis.lineColor, darkMode, 'axis.line'); - yAxis.axisTick.lineStyle.color = prepareChartThemeColor(settings.yAxis.ticksColor, darkMode, 'axis.ticks'); - yAxis.splitLine.lineStyle.color = prepareChartThemeColor(settings.yAxis.splitLinesColor, darkMode, 'axis.splitLine'); + for (let i = 0; i < options.yAxis.length; i++) { + const yAxis = options.yAxis[i]; + const yAxisSettings = yAxisList[i].settings; + yAxis.nameTextStyle.color = prepareChartThemeColor(yAxisSettings.labelColor, darkMode, 'axis.label'); + yAxis.axisLabel.color = prepareChartThemeColor(yAxisSettings.tickLabelColor, darkMode, 'axis.tickLabel'); + yAxis.axisLine.lineStyle.color = prepareChartThemeColor(yAxisSettings.lineColor, darkMode, 'axis.line'); + yAxis.axisTick.lineStyle.color = prepareChartThemeColor(yAxisSettings.ticksColor, darkMode, 'axis.ticks'); + yAxis.splitLine.lineStyle.color = prepareChartThemeColor(yAxisSettings.splitLinesColor, darkMode, 'axis.splitLine'); } } if (Array.isArray(options.xAxis)) { @@ -1032,7 +1151,6 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem, emphasis: { focus: 'series' }, - animation: true, dimensions: [ {name: 'intervalStart', type: 'number'}, {name: 'intervalEnd', type: 'number'} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 6d790d5439..abad3f79e8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -19,7 +19,7 @@ import { AxisPosition, calculateThresholdsOffset, createTimeSeriesXAxisOption, - createTimeSeriesYAxis, + createTimeSeriesYAxis, defaultTimeSeriesChartYAxisSettings, generateChartData, parseThresholdData, SeriesLabelPosition, @@ -29,11 +29,11 @@ import { TimeSeriesChartKeySettings, TimeSeriesChartSeriesType, TimeSeriesChartSettings, - TimeSeriesChartShape, + TimeSeriesChartShape, TimeSeriesChartThreshold, timeSeriesChartThresholdDefaultSettings, TimeSeriesChartThresholdItem, TimeSeriesChartThresholdType, TimeSeriesChartType, - TimeSeriesChartYAxis, + TimeSeriesChartYAxis, TimeSeriesChartYAxisId, TimeSeriesChartYAxisSettings, updateDarkMode } from '@home/components/widget/lib/chart/time-series-chart.models'; import { ResizeObserver } from '@juggle/resize-observer'; @@ -63,6 +63,7 @@ import { AggregationType } from '@shared/models/time/time.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; import { DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; +import { DeepPartial } from '@shared/models/common'; export class TbTimeSeriesChart { @@ -94,9 +95,11 @@ export class TbTimeSeriesChart { private readonly shapeResize$: ResizeObserver; + private readonly settings: TimeSeriesChartSettings; + + private yAxisList: TimeSeriesChartYAxis[] = []; private dataItems: TimeSeriesChartDataItem[] = []; private thresholdItems: TimeSeriesChartThresholdItem[] = []; - private yAxisList: TimeSeriesChartYAxis[] = []; private timeSeriesChart: ECharts; private timeSeriesChartOptions: EChartsOption; @@ -120,13 +123,16 @@ export class TbTimeSeriesChart { yMax$ = this.yMaxSubject.asObservable(); constructor(private ctx: WidgetContext, - private readonly settings: TimeSeriesChartSettings, + private readonly inputSettings: DeepPartial, private chartElement: HTMLElement, private renderer: Renderer2, private autoResize = true) { - this.settings = mergeDeep({} as TimeSeriesChartSettings, timeSeriesChartDefaultSettings, this.settings); + this.settings = mergeDeep({} as TimeSeriesChartSettings, + timeSeriesChartDefaultSettings, + this.inputSettings as TimeSeriesChartSettings); this.darkMode = this.settings.darkMode; + this.setupYAxes(); this.setupData(); this.setupThresholds(); if (this.settings.showTooltip && this.settings.tooltipShowDate) { @@ -258,7 +264,8 @@ export class TbTimeSeriesChart { if (this.darkMode !== darkMode) { this.darkMode = darkMode; if (this.timeSeriesChart) { - this.timeSeriesChartOptions = updateDarkMode(this.timeSeriesChartOptions, this.settings, this.dataItems, + this.timeSeriesChartOptions = updateDarkMode(this.timeSeriesChartOptions, + this.settings, this.yAxisList, this.dataItems, this.thresholdItems, darkMode); this.timeSeriesChart.setOption(this.timeSeriesChartOptions); } @@ -287,11 +294,16 @@ export class TbTimeSeriesChart { const units = dataKey.units && dataKey.units.length ? dataKey.units : this.ctx.units; const decimals = isDefinedAndNotNull(dataKey.decimals) ? dataKey.decimals : (isDefinedAndNotNull(this.ctx.decimals) ? this.ctx.decimals : 2); + let yAxisId = keySettings.yAxisId; + if (!Object.keys(this.settings.yAxes).includes(yAxisId)) { + yAxisId = 'default'; + } this.dataItems.push({ id: this.nextComponentId(), units, decimals, - yAxisIndex: this.getYAxis(units, decimals), + yAxisId, + yAxisIndex: this.getYAxisIndex(yAxisId), dataKey, data: namedData, enabled: !keySettings.dataHiddenByDefault @@ -303,7 +315,9 @@ export class TbTimeSeriesChart { private setupThresholds(): void { const thresholdDatasources: Datasource[] = []; - for (const threshold of this.settings.thresholds) { + for (const thresholdSettings of this.settings.thresholds) { + const threshold = mergeDeep({} as TimeSeriesChartThreshold, + timeSeriesChartThresholdDefaultSettings, thresholdSettings); let latestDataKey: DataKey = null; let entityDataKey: DataKey = null; let value = null; @@ -351,11 +365,16 @@ export class TbTimeSeriesChart { const units = threshold.units && threshold.units.length ? threshold.units : this.ctx.units; const decimals = isDefinedAndNotNull(threshold.decimals) ? threshold.decimals : (isDefinedAndNotNull(this.ctx.decimals) ? this.ctx.decimals : 2); + let yAxisId = threshold.yAxisId; + if (!Object.keys(this.settings.yAxes).includes(yAxisId)) { + yAxisId = 'default'; + } const thresholdItem: TimeSeriesChartThresholdItem = { id: this.nextComponentId(), units, decimals, - yAxisIndex: this.getYAxis(units, decimals), + yAxisId, + yAxisIndex: this.getYAxisIndex(yAxisId), value, latestDataKey, settings: threshold @@ -368,17 +387,32 @@ export class TbTimeSeriesChart { this.subscribeForEntityThresholds(thresholdDatasources); } + private setupYAxes(): void { + const yAxisSettingsList = Object.values(this.settings.yAxes); + yAxisSettingsList.sort((a1, a2) => a1.order - a2.order); + for (const yAxisSettings of yAxisSettingsList) { + const axisSettings = mergeDeep({} as TimeSeriesChartYAxisSettings, + defaultTimeSeriesChartYAxisSettings, yAxisSettings); + const units = axisSettings.units && axisSettings.units.length ? axisSettings.units : this.ctx.units; + const decimals = isDefinedAndNotNull(axisSettings.decimals) ? axisSettings.decimals : + (isDefinedAndNotNull(this.ctx.decimals) ? this.ctx.decimals : 2); + const yAxis = createTimeSeriesYAxis(units, decimals, axisSettings, this.darkMode); + this.yAxisList.push(yAxis); + } + } + + private nextComponentId(): string { return (this.componentIndexCounter++) + ''; } - private getYAxis(units: string, decimals: number): number { - let yAxisIndex = this.yAxisList.findIndex(axis => axis.units === units); + private getYAxisIndex(id: TimeSeriesChartYAxisId): number { + let yAxisIndex = this.yAxisList.findIndex(axis => axis.id === id); if (yAxisIndex === -1) { - const yAxisId = this.yAxisList.length + ''; - const yAxis = createTimeSeriesYAxis(yAxisId, units, decimals, this.settings.yAxis, this.darkMode); - this.yAxisList.push(yAxis); - yAxisIndex = this.yAxisList.length - 1; + yAxisIndex = this.yAxisList.findIndex(axis => axis.id === 'default'); + if (yAxisIndex === -1 && this.yAxisList.length) { + yAxisIndex = 0; + } } return yAxisIndex; } @@ -460,7 +494,15 @@ export class TbTimeSeriesChart { realtime: true, bottom: 10 } - ] + ], + animation: this.settings.animation.animation, + animationThreshold: this.settings.animation.animationThreshold, + animationDuration: this.settings.animation.animationDuration, + animationEasing: this.settings.animation.animationEasing, + animationDelay: this.settings.animation.animationDelay, + animationDurationUpdate: this.settings.animation.animationDurationUpdate, + animationEasingUpdate: this.settings.animation.animationEasingUpdate, + animationDelayUpdate: this.settings.animation.animationDelayUpdate }; this.timeSeriesChartOptions.xAxis[0].tbTimeWindow = this.ctx.defaultSubscription.timeWindow; @@ -588,7 +630,7 @@ export class TbTimeSeriesChart { result.offset += 5; } width = newWidth; - const showLine = !!width && this.settings.yAxis.showLine; + const showLine = !!width && yAxis.settings.showLine; if (yAxis.option.axisLine.show !== showLine) { yAxis.option.axisLine.show = showLine; result.changed = true; @@ -597,7 +639,7 @@ export class TbTimeSeriesChart { yAxis.option.offset = result.offset; result.changed = true; } - if (this.settings.yAxis.label) { + if (yAxis.settings.label) { if (!width) { if (yAxis.option.name) { yAxis.option.name = null; @@ -605,7 +647,7 @@ export class TbTimeSeriesChart { } } else { if (!yAxis.option.name) { - yAxis.option.name = this.settings.yAxis.label; + yAxis.option.name = yAxis.settings.label; result.changed = true; } const nameGap = width; @@ -613,7 +655,7 @@ export class TbTimeSeriesChart { yAxis.option.nameGap = nameGap; result.changed = true; } - const nameWidth = measureYAxisNameWidth(this.timeSeriesChart, yAxis.id, this.settings.yAxis.label); + const nameWidth = measureYAxisNameWidth(this.timeSeriesChart, yAxis.id, yAxis.settings.label); result.offset += nameWidth; } } @@ -623,15 +665,25 @@ export class TbTimeSeriesChart { } private scaleYAxis(yAxis: TimeSeriesChartYAxis): boolean { - const yAxisIndex = this.yAxisList.indexOf(yAxis); - const axisBarDataItems = this.dataItems.filter(d => d.yAxisIndex === yAxisIndex && d.enabled && + const axisBarDataItems = this.dataItems.filter(d => d.yAxisId === yAxis.id && d.enabled && d.data.length && d.dataKey.settings.type === TimeSeriesChartSeriesType.bar); return !axisBarDataItems.length; } + private yAxisEmpty(yAxis: TimeSeriesChartYAxis): boolean { + const axisDataItems = this.dataItems.filter(d => d.yAxisId === yAxis.id && d.enabled && + d.data.length); + return !axisDataItems.length; + } + private calculateYAxisInterval(axisList: TimeSeriesChartYAxis[]): boolean { let changed = false; for (const yAxis of axisList) { + const minInterval = this.yAxisEmpty(yAxis) ? undefined : (1 / Math.pow(10, yAxis.decimals)); + if (yAxis.option.minInterval !== minInterval) { + yAxis.option.minInterval = minInterval; + changed = true; + } if (yAxis.intervalCalculator) { const axis = getYAxis(this.timeSeriesChart, yAxis.id); if (axis) { @@ -649,8 +701,10 @@ export class TbTimeSeriesChart { } private minTopOffset(): number { + const showTickLabels = + !!this.yAxisList.find(yAxis => yAxis.settings.show && yAxis.settings.showTickLabels); return (this.topPointLabels) ? 20 : - ((this.settings.yAxis.show && this.settings.yAxis.showTickLabels) ? 10 : 5); + (showTickLabels ? 10 : 5); } private minBottomOffset(): number { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html index 0d470703b6..5f0fbb9e37 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.html @@ -29,6 +29,18 @@
    +
    +
    +
    widgets.time-series-chart.axis.y-axis
    + + + + {{ yAxis }} + + + +
    +
    widgets.time-series-chart.series.series-type
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts index 4da23f32e0..d1ac428396 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-key-settings.component.ts @@ -25,9 +25,10 @@ import { TimeSeriesChartKeySettings, TimeSeriesChartSeriesType, timeSeriesChartSeriesTypes, - timeSeriesChartSeriesTypeTranslations, TimeSeriesChartType, timeSeriesChartTypeTranslations + timeSeriesChartSeriesTypeTranslations, TimeSeriesChartType, timeSeriesChartTypeTranslations, TimeSeriesChartYAxisId } from '@home/components/widget/lib/chart/time-series-chart.models'; import { WidgetConfigComponentData } from '@home/models/widget-component.models'; +import { TimeSeriesChartWidgetSettings } from '@home/components/widget/lib/chart/time-series-chart-widget.models'; @Component({ selector: 'tb-time-series-chart-key-settings', @@ -50,6 +51,8 @@ export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent chartType = TimeSeriesChartType.default; + yAxisIds: TimeSeriesChartYAxisId[]; + constructor(protected store: Store, private fb: UntypedFormBuilder) { super(store); @@ -64,6 +67,8 @@ export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent if (isDefinedAndNotNull(params.chartType)) { this.chartType = params.chartType; } + const widgetSettings = (widgetConfig.config?.settings || {}) as TimeSeriesChartWidgetSettings; + this.yAxisIds = widgetSettings.yAxes ? Object.keys(widgetSettings.yAxes) : ['default']; } protected defaultSettings(): WidgetSettings { @@ -73,7 +78,12 @@ export class TimeSeriesChartKeySettingsComponent extends WidgetSettingsComponent protected onSettingsSet(settings: WidgetSettings) { const seriesSettings = settings as TimeSeriesChartKeySettings; + let yAxisId = seriesSettings.yAxisId; + if (!this.yAxisIds.includes(yAxisId)) { + yAxisId = 'default'; + } this.timeSeriesChartKeySettingsForm = this.fb.group({ + yAxisId: [yAxisId, []], showInLegend: [seriesSettings.showInLegend, []], dataHiddenByDefault: [seriesSettings.dataHiddenByDefault, []], type: [seriesSettings.type, []], diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html index 35f0d147ac..933961a7ae 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html @@ -16,12 +16,18 @@ --> + + + [widgetConfig]="widgetConfig?.config" + [yAxisIds]="yAxisIds">
    widgets.time-series-chart.chart-style
    @@ -38,12 +44,7 @@
    -
    widgets.time-series-chart.axis.axes
    - - +
    widgets.time-series-chart.axis.x-axis
    1) { + for (let i = 1; i < this.widgetConfig.config.datasources.length; i++) { + const datasource = this.widgetConfig.config.datasources[i]; + this.removeYaxisId(datasource.dataKeys, yAxisId); + } + } + } + protected settingsForm(): UntypedFormGroup { return this.timeSeriesChartWidgetSettingsForm; } @@ -91,12 +110,12 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon protected onSettingsSet(settings: WidgetSettings) { this.timeSeriesChartWidgetSettingsForm = this.fb.group({ + yAxes: [settings.yAxes, []], thresholds: [settings.thresholds, []], dataZoom: [settings.dataZoom, []], stack: [settings.stack, []], - yAxis: [settings.yAxis, []], xAxis: [settings.xAxis, []], noAggregationBarWidthSettings: [settings.noAggregationBarWidthSettings, []], @@ -173,6 +192,20 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon } } + private removeYaxisId(series: DataKey[], yAxisId: TimeSeriesChartYAxisId): boolean { + let changed = false; + if (series) { + series.forEach(key => { + const keySettings = ((key.settings || {}) as TimeSeriesChartKeySettings); + if (keySettings.yAxisId === yAxisId) { + keySettings.yAxisId = 'default'; + changed = true; + } + }); + } + return changed; + } + private _tooltipValuePreviewFn(): string { return formatValue(22, 0, '°C', false); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html index 24f3dc0883..9511baf121 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html @@ -17,13 +17,13 @@ -->
    - + - {{ axisTitle | translate }} + {{ 'widgets.time-series-chart.axis.show' | translate }} @@ -56,6 +56,18 @@
    +
    +
    widget-config.units-short
    + + +
    +
    +
    widget-config.decimals-short
    + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts index 328574d648..a88fc2e123 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts @@ -15,7 +15,13 @@ /// import { Component, forwardRef, Input, OnInit } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { + ControlValueAccessor, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormGroup, + Validators +} from '@angular/forms'; import { AxisPosition, timeSeriesAxisPositionTranslations, @@ -40,9 +46,11 @@ import { WidgetService } from '@core/http/widget.service'; }) export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValueAccessor { - settingsExpanded = false; + @Input() + @coerceBoolean() + alwaysExpanded = false; - axisTitle: string; + settingsExpanded = false; axisPositions: AxisPosition[]; @@ -72,8 +80,6 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu ngOnInit(): void { - this.axisTitle = this.axisType === 'xAxis' ? 'widgets.time-series-chart.axis.x-axis' : 'widgets.time-series-chart.axis.y-axis'; - this.axisPositions = this.axisType === 'xAxis' ? [AxisPosition.top, AxisPosition.bottom] : [AxisPosition.left, AxisPosition.right]; @@ -94,6 +100,8 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu splitLinesColor: [null, []] }); if (this.axisType === 'yAxis') { + this.axisSettingsFormGroup.addControl('units', this.fb.control(null, [])); + this.axisSettingsFormGroup.addControl('decimals', this.fb.control(null, [Validators.min(0)])); this.axisSettingsFormGroup.addControl('ticksFormatter', this.fb.control(null, [])); this.axisSettingsFormGroup.addControl('min', this.fb.control(null, [])); this.axisSettingsFormGroup.addControl('max', this.fb.control(null, [])); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html index f82a717d78..7e2c9f74c2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-threshold-row.component.html @@ -73,6 +73,15 @@ [formControl]="entityKeyFormControl">
    +
    + + + + {{ yAxis }} + + + +
    -
    - -
    + +
    +
    +
    +
    +
    + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.scss new file mode 100644 index 0000000000..52aa69f59d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.scss @@ -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 '../../../../../../../../../scss/constants'; + +.tb-y-axes-panel { + .tb-form-table-header-cell { + &.tb-axis-id-header { + width: 60px; + min-width: 60px; + } + + &.tb-label-header { + flex: 1 1 60%; + min-width: 100px; + } + + &.tb-position-header { + flex: 1; + min-width: 60px; + @media #{$mat-gt-md} { + flex: 1 1 40%; + } + } + + &.tb-units-header { + width: 80px; + min-width: 80px; + } + + &.tb-decimals-header { + width: 60px; + min-width: 60px; + } + + &.tb-min-header, &.tb-max-header { + width: 80px; + min-width: 80px; + } + + &.tb-show-header { + width: 40px; + min-width: 40px; + } + + &.tb-actions-header { + width: 80px; + min-width: 80px; + @media #{$mat-gt-md} { + width: 120px; + min-width: 120px; + } + } + + &.tb-label-header, &.tb-units-header, &.tb-decimals-header { + display: none; + @media #{$mat-gt-md} { + display: block; + } + } + + &.tb-min-header, &.tb-max-header { + display: none; + @media #{$mat-gt-xs} { + display: block; + } + } + } + + .tb-form-table-body { + tb-time-series-chart-y-axis-row { + overflow: hidden; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.ts new file mode 100644 index 0000000000..9879ffe877 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component.ts @@ -0,0 +1,180 @@ +/// +/// 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, forwardRef, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; +import { + AbstractControl, + ControlValueAccessor, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + UntypedFormArray, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, + Validator +} from '@angular/forms'; +import { + defaultTimeSeriesChartYAxisSettings, + getNextTimeSeriesYAxisId, + TimeSeriesChartYAxes, TimeSeriesChartYAxisId, + TimeSeriesChartYAxisSettings, + timeSeriesChartYAxisValid, + timeSeriesChartYAxisValidator +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { mergeDeep } from '@core/utils'; +import { CdkDragDrop } from '@angular/cdk/drag-drop'; +import { coerceBoolean } from '@shared/decorators/coercion'; + +@Component({ + selector: 'tb-time-series-chart-y-axes-panel', + templateUrl: './time-series-chart-y-axes-panel.component.html', + styleUrls: ['./time-series-chart-y-axes-panel.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartYAxesPanelComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => TimeSeriesChartYAxesPanelComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None +}) +export class TimeSeriesChartYAxesPanelComponent implements ControlValueAccessor, OnInit, Validator { + + @Input() + disabled: boolean; + + @Input() + @coerceBoolean() + advanced = false; + + @Output() + axisRemoved = new EventEmitter(); + + yAxesFormGroup: UntypedFormGroup; + + get dragEnabled(): boolean { + return this.axesFormArray().controls.length > 1; + } + + private propagateChange = (_val: any) => {}; + + constructor(private fb: UntypedFormBuilder) { + } + + ngOnInit() { + this.yAxesFormGroup = this.fb.group({ + axes: [this.fb.array([]), []] + }); + this.yAxesFormGroup.valueChanges.subscribe( + () => { + let axes: TimeSeriesChartYAxisSettings[] = this.yAxesFormGroup.get('axes').value; + for (let i = 0; i < axes.length; i++) { + axes[i].order = i; + } + if (axes) { + axes = axes.filter(axis => timeSeriesChartYAxisValid(axis)); + } + const yAxes: TimeSeriesChartYAxes = {}; + for (const axis of axes) { + yAxes[axis.id] = axis; + } + this.propagateChange(yAxes); + } + ); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.yAxesFormGroup.disable({emitEvent: false}); + } else { + this.yAxesFormGroup.enable({emitEvent: false}); + } + } + + writeValue(value: TimeSeriesChartYAxes | undefined): void { + const yAxes: TimeSeriesChartYAxes = value || {}; + if (!yAxes.default) { + yAxes.default = mergeDeep({} as TimeSeriesChartYAxisSettings, defaultTimeSeriesChartYAxisSettings, + {id: 'default', order: 0} as TimeSeriesChartYAxisSettings); + } + const yAxisSettingsList = Object.values(yAxes); + yAxisSettingsList.sort((a1, a2) => a1.order - a2.order); + this.yAxesFormGroup.setControl('axes', this.prepareAxesFormArray(yAxisSettingsList), {emitEvent: false}); + } + + public validate(c: UntypedFormControl) { + const valid = this.yAxesFormGroup.valid; + return valid ? null : { + yAxes: { + valid: false, + }, + }; + } + + axisDrop(event: CdkDragDrop) { + const axesArray = this.yAxesFormGroup.get('axes') as UntypedFormArray; + const axis = axesArray.at(event.previousIndex); + axesArray.removeAt(event.previousIndex); + axesArray.insert(event.currentIndex, axis); + } + + axesFormArray(): UntypedFormArray { + return this.yAxesFormGroup.get('axes') as UntypedFormArray; + } + + trackByAxis(index: number, axisControl: AbstractControl): any { + return axisControl; + } + + removeAxis(index: number) { + const axis = + (this.yAxesFormGroup.get('axes') as UntypedFormArray).at(index).value as TimeSeriesChartYAxisSettings; + (this.yAxesFormGroup.get('axes') as UntypedFormArray).removeAt(index); + this.axisRemoved.emit(axis.id); + } + + addAxis() { + const axis = mergeDeep({} as TimeSeriesChartYAxisSettings, + defaultTimeSeriesChartYAxisSettings); + const axes: TimeSeriesChartYAxisSettings[] = this.yAxesFormGroup.get('axes').value; + axis.id = getNextTimeSeriesYAxisId(axes); + axis.order = axes.length; + const axesArray = this.yAxesFormGroup.get('axes') as UntypedFormArray; + const axisControl = this.fb.control(axis, [timeSeriesChartYAxisValidator]); + axesArray.push(axisControl); + } + + private prepareAxesFormArray(axes: TimeSeriesChartYAxisSettings[]): UntypedFormArray { + const axesControls: Array = []; + axes.forEach((axis) => { + axesControls.push(this.fb.control(axis, [timeSeriesChartYAxisValidator])); + }); + return this.fb.array(axesControls); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.html new file mode 100644 index 0000000000..0b1907033f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.html @@ -0,0 +1,72 @@ + +
    +
    + {{ modelValue.id }} +
    + + + + + + + + {{ timeSeriesAxisPositionTranslations.get(position) | translate }} + + + +
    + + + +
    +
    + + + +
    +
    + + +
    +
    + + + +
    +
    + +
    + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.scss new file mode 100644 index 0000000000..12db0d9228 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.scss @@ -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 '../../../../../../../../../scss/constants'; + +.tb-form-table-row.tb-axis-row { + + .tb-axis-id-field { + color: rgba(0, 0, 0, 0.76); + font-weight: 500; + font-size: 14px; + line-height: 20px; + letter-spacing: 0.2px; + width: 60px; + min-width: 60px; + } + + .tb-label-field { + flex: 1 1 60%; + min-width: 100px; + } + + .tb-position-field { + flex: 1; + min-width: 60px; + @media #{$mat-gt-md} { + flex: 1 1 40%; + } + } + + .tb-units-field, .tb-decimals-field, .tb-min-field, .tb-max-field { + display: flex; + flex-direction: row; + place-content: center; + align-items: center; + } + + .tb-units-field { + width: 80px; + min-width: 80px; + } + + .tb-decimals-field { + width: 60px; + min-width: 60px; + } + + .tb-min-field, .tb-max-field { + width: 80px; + min-width: 80px; + } + + .tb-show-field { + width: 40px; + min-width: 40px; + } + + .tb-label-field { + display: none; + @media #{$mat-gt-md} { + display: block; + } + } + + .tb-units-field, .tb-decimals-field { + display: none; + @media #{$mat-gt-md} { + display: flex; + } + } + + .tb-min-field, .tb-max-field { + display: none; + @media #{$mat-gt-xs} { + display: flex; + } + } + + .tb-remove-button { + width: 40px; + min-width: 40px; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.ts new file mode 100644 index 0000000000..a4824fd51e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component.ts @@ -0,0 +1,201 @@ +/// +/// 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 { + ChangeDetectorRef, + Component, + EventEmitter, + forwardRef, + Input, + OnInit, + Output, + Renderer2, + ViewContainerRef, + ViewEncapsulation +} from '@angular/core'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { + AxisPosition, + timeSeriesAxisPositionTranslations, + TimeSeriesChartYAxisSettings +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { MatButton } from '@angular/material/button'; +import { TbPopoverService } from '@shared/components/popover.service'; +import { coerceBoolean } from '@shared/decorators/coercion'; +import { + TimeSeriesChartYAxisSettingsPanelComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component'; +import { deepClone } from '@core/utils'; + +@Component({ + selector: 'tb-time-series-chart-y-axis-row', + templateUrl: './time-series-chart-y-axis-row.component.html', + styleUrls: ['./time-series-chart-y-axis-row.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartYAxisRowComponent), + multi: true + } + ], + encapsulation: ViewEncapsulation.None +}) +export class TimeSeriesChartYAxisRowComponent implements ControlValueAccessor, OnInit { + + axisPositions = [AxisPosition.left, AxisPosition.right]; + + timeSeriesAxisPositionTranslations = timeSeriesAxisPositionTranslations; + + @Input() + disabled: boolean; + + @Input() + @coerceBoolean() + advanced = false; + + @Output() + axisRemoved = new EventEmitter(); + + axisFormGroup: UntypedFormGroup; + + modelValue: TimeSeriesChartYAxisSettings; + + private propagateChange = (_val: any) => {}; + + constructor(private fb: UntypedFormBuilder, + private popoverService: TbPopoverService, + private renderer: Renderer2, + private viewContainerRef: ViewContainerRef, + private cd: ChangeDetectorRef) { + } + + ngOnInit() { + this.axisFormGroup = this.fb.group({ + label: [null, []], + position: [null, []], + units: [null, []], + decimals: [null, []], + min: [null, []], + max: [null, []], + show: [null, []] + }); + this.axisFormGroup.valueChanges.subscribe( + () => this.updateModel() + ); + this.axisFormGroup.get('show').valueChanges.subscribe(() => { + this.updateValidators(); + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(_fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.axisFormGroup.disable({emitEvent: false}); + } else { + this.axisFormGroup.enable({emitEvent: false}); + this.updateValidators(); + } + } + + writeValue(value: TimeSeriesChartYAxisSettings): void { + this.modelValue = value; + this.axisFormGroup.patchValue( + { + label: value.label, + position: value.position, + units: value.units, + decimals: value.decimals, + min: value.min, + max: value.max, + show: value.show, + }, {emitEvent: false} + ); + this.updateValidators(); + this.cd.markForCheck(); + } + + editAxis($event: Event, matButton: MatButton) { + if ($event) { + $event.stopPropagation(); + } + const trigger = matButton._elementRef.nativeElement; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const ctx: any = { + yAxisSettings: deepClone(this.modelValue), + advanced: this.advanced + }; + const yAxisSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, TimeSeriesChartYAxisSettingsPanelComponent, ['leftOnly', 'leftTopOnly', 'leftBottomOnly'], true, null, + ctx, + {}, + {}, {}, true); + yAxisSettingsPanelPopover.tbComponentRef.instance.popover = yAxisSettingsPanelPopover; + yAxisSettingsPanelPopover.tbComponentRef.instance.yAxisSettingsApplied.subscribe((yAxisSettings) => { + yAxisSettingsPanelPopover.hide(); + this.modelValue = {...this.modelValue, ...yAxisSettings}; + this.axisFormGroup.patchValue( + { + label: this.modelValue.label, + position: this.modelValue.position, + units: this.modelValue.units, + decimals: this.modelValue.decimals, + min: this.modelValue.min, + max: this.modelValue.max, + show: this.modelValue.show + }, + {emitEvent: false}); + this.updateValidators(); + this.propagateChange(this.modelValue); + }); + } + } + + private updateValidators() { + const show: boolean = this.axisFormGroup.get('show').value; + if (show) { + this.axisFormGroup.get('label').enable({emitEvent: false}); + this.axisFormGroup.get('position').enable({emitEvent: false}); + this.axisFormGroup.get('units').enable({emitEvent: false}); + this.axisFormGroup.get('decimals').enable({emitEvent: false}); + } else { + this.axisFormGroup.get('label').disable({emitEvent: false}); + this.axisFormGroup.get('position').disable({emitEvent: false}); + this.axisFormGroup.get('units').disable({emitEvent: false}); + this.axisFormGroup.get('decimals').disable({emitEvent: false}); + } + } + + private updateModel() { + const value = this.axisFormGroup.value; + this.modelValue.label = value.label; + this.modelValue.position = value.position; + this.modelValue.units = value.units; + this.modelValue.decimals = value.decimals; + this.modelValue.min = value.min; + this.modelValue.max = value.max; + this.modelValue.show = value.show; + this.propagateChange(this.modelValue); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.html new file mode 100644 index 0000000000..759074b4be --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.html @@ -0,0 +1,43 @@ + +
    +
    {{ 'widgets.time-series-chart.axis.y-axis-settings' | translate }}
    +
    + + +
    +
    + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.scss new file mode 100644 index 0000000000..095c38b7f7 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.scss @@ -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 '../../../../../../../../../scss/constants'; + +.tb-y-axis-settings-panel { + width: 530px; + display: flex; + flex-direction: column; + gap: 16px; + @media #{$mat-lt-md} { + width: 90vw; + } + .tb-y-axis-settings-panel-content { + display: flex; + flex-direction: column; + gap: 16px; + overflow: auto; + margin: -10px; + padding: 10px; + } + .tb-y-axis-settings-title { + font-size: 16px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0.25px; + color: rgba(0, 0, 0, 0.87); + } + .tb-y-axis-settings-panel-buttons { + height: 40px; + display: flex; + flex-direction: row; + gap: 16px; + justify-content: flex-end; + align-items: flex-end; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.ts new file mode 100644 index 0000000000..8046aafd29 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component.ts @@ -0,0 +1,66 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; +import { TbPopoverComponent } from '@shared/components/popover.component'; +import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { TimeSeriesChartYAxisSettings } from '@home/components/widget/lib/chart/time-series-chart.models'; +import { coerceBoolean } from '@shared/decorators/coercion'; + +@Component({ + selector: 'tb-time-series-chart-y-axis-settings-panel', + templateUrl: './time-series-chart-y-axis-settings-panel.component.html', + providers: [], + styleUrls: ['./time-series-chart-y-axis-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class TimeSeriesChartYAxisSettingsPanelComponent implements OnInit { + + @Input() + yAxisSettings: TimeSeriesChartYAxisSettings; + + @Input() + @coerceBoolean() + advanced = false; + + @Input() + popover: TbPopoverComponent; + + @Output() + yAxisSettingsApplied = new EventEmitter(); + + yAxisSettingsFormGroup: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + } + + ngOnInit(): void { + this.yAxisSettingsFormGroup = this.fb.group( + { + yAxis: [this.yAxisSettings, []] + } + ); + } + + cancel() { + this.popover?.hide(); + } + + applyYAxisSettings() { + const yAxisSettings = this.yAxisSettingsFormGroup.get('yAxis').getRawValue(); + this.yAxisSettingsApplied.emit(yAxisSettings); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts index b741a8e358..714da2a0c7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts @@ -109,6 +109,15 @@ import { import { TimeSeriesNoAggregationBarWidthSettingsComponent } from '@home/components/widget/lib/settings/common/chart/time-series-no-aggregation-bar-width-settings.component'; +import { + TimeSeriesChartYAxesPanelComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-y-axes-panel.component'; +import { + TimeSeriesChartYAxisRowComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-row.component'; +import { + TimeSeriesChartYAxisSettingsPanelComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component'; @NgModule({ declarations: [ @@ -150,6 +159,9 @@ import { TimeSeriesChartThresholdRowComponent, TimeSeriesChartThresholdSettingsPanelComponent, TimeSeriesNoAggregationBarWidthSettingsComponent, + TimeSeriesChartYAxesPanelComponent, + TimeSeriesChartYAxisRowComponent, + TimeSeriesChartYAxisSettingsPanelComponent, DataKeyInputComponent, EntityAliasInputComponent ], @@ -197,6 +209,9 @@ import { TimeSeriesChartThresholdRowComponent, TimeSeriesChartThresholdSettingsPanelComponent, TimeSeriesNoAggregationBarWidthSettingsComponent, + TimeSeriesChartYAxesPanelComponent, + TimeSeriesChartYAxisRowComponent, + TimeSeriesChartYAxisSettingsPanelComponent, DataKeyInputComponent, EntityAliasInputComponent ], diff --git a/ui-ngx/src/app/shared/models/common.ts b/ui-ngx/src/app/shared/models/common.ts new file mode 100644 index 0000000000..c331cc5127 --- /dev/null +++ b/ui-ngx/src/app/shared/models/common.ts @@ -0,0 +1,19 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +export type DeepPartial = T extends object ? { + [P in keyof T]?: DeepPartial; +} : T; 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 216ed878b2..830a54f88e 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6609,6 +6609,7 @@ "stack-mode": "Stack mode", "stack-mode-hint": "Stacks series on the chart. The series with the same unit would be put on top of each other.", "axes": "Axes", + "y-axes": "Y axes", "line-type": "Line type", "line-type-solid": "Solid", "line-type-dashed": "Dashed", @@ -6670,6 +6671,9 @@ "axes": "Axes", "x-axis": "X axis", "y-axis": "Y axis", + "y-axis-settings": "Y axis settings", + "remove-y-axis": "Remove Y axis", + "id": "Id", "label": "Label", "position": "Position", "position-left": "Left", @@ -6686,7 +6690,11 @@ "scale": "Scale", "scale-min": "min", "scale-max": "max", - "scale-auto": "Auto" + "scale-auto": "Auto", + "min": "Min", + "max": "Max", + "show": "Show", + "add-y-axis": "Add Y axis" }, "series": { "legend-settings": "Legend settings", From 7823f1533c92eba581cb0fb0484b0a0e280bac4b Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 11 Mar 2024 16:12:44 +0200 Subject: [PATCH 337/397] UI: Time series chart animation settings. --- ...e-series-chart-basic-config.component.html | 3 + ...ime-series-chart-basic-config.component.ts | 4 + ...eries-chart-widget-settings.component.html | 3 + ...-series-chart-widget-settings.component.ts | 2 + ...es-chart-animation-settings.component.html | 89 +++++++++++++ ...ries-chart-animation-settings.component.ts | 124 ++++++++++++++++++ .../common/widget-settings-common.module.ts | 5 + .../assets/locale/locale.constant-en_US.json | 10 ++ 8 files changed, 240 insertions(+) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.component.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html index 1f62a13c4e..adaeb78acb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html @@ -223,6 +223,9 @@
    + +
    widget-config.card-appearance
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts index f9ee35da23..ba4b4c6371 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts @@ -168,6 +168,8 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon tooltipBackgroundColor: [settings.tooltipBackgroundColor, []], tooltipBackgroundBlur: [settings.tooltipBackgroundBlur, []], + animation: [settings.animation, []], + background: [settings.background, []], cardButtons: [this.getCardButtons(configData.config), []], @@ -221,6 +223,8 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon this.widgetConfig.config.settings.tooltipBackgroundColor = config.tooltipBackgroundColor; this.widgetConfig.config.settings.tooltipBackgroundBlur = config.tooltipBackgroundBlur; + this.widgetConfig.config.settings.animation = config.animation; + this.widgetConfig.config.settings.background = config.background; this.setCardButtons(config.cardButtons, this.widgetConfig.config); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html index 933961a7ae..42249a67cd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html @@ -157,6 +157,9 @@
    + +
    {{ 'widgets.background.background' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts index 003b5005aa..e270b97137 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts @@ -138,6 +138,8 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon tooltipBackgroundColor: [settings.tooltipBackgroundColor, []], tooltipBackgroundBlur: [settings.tooltipBackgroundBlur, []], + animation: [settings.animation, []], + background: [settings.background, []] }); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.component.html new file mode 100644 index 0000000000..5e0ad8e2ec --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.component.html @@ -0,0 +1,89 @@ + + +
    + + + + + {{ 'widgets.time-series-chart.animation.animation' | translate }} + + + + +
    +
    {{ 'widgets.time-series-chart.animation.animation-threshold' | translate }}
    + + +
    ms
    +
    +
    +
    +
    {{ 'widgets.time-series-chart.animation.animation-duration' | translate }}
    + + +
    ms
    +
    +
    +
    +
    widgets.time-series-chart.animation.animation-easing
    + + + + {{ easing }} + + + +
    +
    +
    {{ 'widgets.time-series-chart.animation.animation-delay' | translate }}
    + + +
    ms
    +
    +
    +
    +
    {{ 'widgets.time-series-chart.animation.update-animation-duration' | translate }}
    + + +
    ms
    +
    +
    +
    +
    widgets.time-series-chart.animation.update-animation-easing
    + + + + {{ easing }} + + + +
    +
    +
    {{ 'widgets.time-series-chart.animation.update-animation-delay' | translate }}
    + + +
    ms
    +
    +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.component.ts new file mode 100644 index 0000000000..5da5aa2fe9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.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, forwardRef, Input, OnInit } from '@angular/core'; +import { + ControlValueAccessor, + NG_VALUE_ACCESSOR, + UntypedFormBuilder, + UntypedFormGroup, + Validators +} from '@angular/forms'; +import { + timeSeriesChartAnimationEasings, + TimeSeriesChartAnimationSettings +} from '@home/components/widget/lib/chart/time-series-chart.models'; +import { WidgetService } from '@core/http/widget.service'; + +@Component({ + selector: 'tb-time-series-chart-animation-settings', + templateUrl: './time-series-chart-animation-settings.component.html', + styleUrls: ['./../../widget-settings.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TimeSeriesChartAnimationSettingsComponent), + multi: true + } + ] +}) +export class TimeSeriesChartAnimationSettingsComponent implements OnInit, ControlValueAccessor { + + settingsExpanded = false; + + timeSeriesChartAnimationEasings = timeSeriesChartAnimationEasings; + + @Input() + disabled: boolean; + + private modelValue: TimeSeriesChartAnimationSettings; + + private propagateChange = null; + + public animationSettingsFormGroup: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder, + private widgetService: WidgetService,) { + } + + ngOnInit(): void { + this.animationSettingsFormGroup = this.fb.group({ + animation: [null, []], + animationThreshold: [null, [Validators.min(0)]], + animationDuration: [null, [Validators.min(0)]], + animationEasing: [null, []], + animationDelay: [null, [Validators.min(0)]], + animationDurationUpdate: [null, [Validators.min(0)]], + animationEasingUpdate: [null, []], + animationDelayUpdate: [null, [Validators.min(0)]] + }); + this.animationSettingsFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + }); + this.animationSettingsFormGroup.get('animation').valueChanges + .subscribe(() => { + this.updateValidators(); + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(_fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.animationSettingsFormGroup.disable({emitEvent: false}); + } else { + this.animationSettingsFormGroup.enable({emitEvent: false}); + this.updateValidators(); + } + } + + writeValue(value: TimeSeriesChartAnimationSettings): void { + this.modelValue = value; + this.animationSettingsFormGroup.patchValue( + value, {emitEvent: false} + ); + this.updateValidators(); + this.animationSettingsFormGroup.get('animation').valueChanges.subscribe((animation) => { + this.settingsExpanded = animation; + }); + } + + private updateValidators() { + const animation: boolean = this.animationSettingsFormGroup.get('animation').value; + if (animation) { + this.animationSettingsFormGroup.enable({emitEvent: false}); + } else { + this.animationSettingsFormGroup.disable({emitEvent: false}); + this.animationSettingsFormGroup.get('animation').enable({emitEvent: false}); + } + } + + private updateModel() { + this.modelValue = this.animationSettingsFormGroup.getRawValue(); + this.propagateChange(this.modelValue); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts index 714da2a0c7..b80b20f402 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts @@ -118,6 +118,9 @@ import { import { TimeSeriesChartYAxisSettingsPanelComponent } from '@home/components/widget/lib/settings/common/chart/time-series-chart-y-axis-settings-panel.component'; +import { + TimeSeriesChartAnimationSettingsComponent +} from '@home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.component'; @NgModule({ declarations: [ @@ -162,6 +165,7 @@ import { TimeSeriesChartYAxesPanelComponent, TimeSeriesChartYAxisRowComponent, TimeSeriesChartYAxisSettingsPanelComponent, + TimeSeriesChartAnimationSettingsComponent, DataKeyInputComponent, EntityAliasInputComponent ], @@ -212,6 +216,7 @@ import { TimeSeriesChartYAxesPanelComponent, TimeSeriesChartYAxisRowComponent, TimeSeriesChartYAxisSettingsPanelComponent, + TimeSeriesChartAnimationSettingsComponent, DataKeyInputComponent, EntityAliasInputComponent ], 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 830a54f88e..decb97384e 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -6696,6 +6696,16 @@ "show": "Show", "add-y-axis": "Add Y axis" }, + "animation": { + "animation": "Animation", + "animation-threshold": "Animation threshold", + "animation-duration": "Animation duration", + "animation-easing": "Animation easing", + "animation-delay": "Animation delay", + "update-animation-duration": "Update animation duration", + "update-animation-easing": "Update animation easing", + "update-animation-delay": "Update animation delay" + }, "series": { "legend-settings": "Legend settings", "show-in-legend": "Show in legend", From e2a77779ad15fa1686250ad0b7fb801b950e2845 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 11 Mar 2024 17:45:09 +0200 Subject: [PATCH 338/397] UI: Update home dashboards --- .../lib/chart/time-series-chart.models.ts | 11 +- .../assets/dashboard/sys_admin_home_page.json | 1166 +++++++++++------ .../dashboard/tenant_admin_home_page.json | 976 +++++++++----- 3 files changed, 1492 insertions(+), 661 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index 9af41fa378..02cbdb2ff8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -884,7 +884,16 @@ export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartAxisSetting fontWeight: xAxisTickLabelStyle.fontWeight, fontFamily: xAxisTickLabelStyle.fontFamily, fontSize: xAxisTickLabelStyle.fontSize, - hideOverlap: true + hideOverlap: true, + /* formatter: { + year: '{yyyy}', + month: '{MMM}', + day: '{d}', + hour: '{HH}:{mm}', + minute: '{HH}:{mm}', + second: '{HH}:{mm}:{ss}', + millisecond: '{hh}:{mm}:{ss} {SSS}' + } */ }, axisLine: { show: settings.showLine, diff --git a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json index f93de01596..b308bc98d6 100644 --- a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json +++ b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json @@ -69,142 +69,6 @@ "id": "d70cc256-4c7b-ee06-9905-b8c5e546605f", "typeFullFqn": "system.cards.markdown_card" }, - "8ee72d43-678c-4e25-e9a8-7d4cfd7a5f8e": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079", - "filterId": null, - "dataKeys": [ - { - "name": "transportMsgCountHourly", - "type": "timeseries", - "label": "{i18n:widgets.transport-messages.title}", - "color": "#305680", - "settings": {}, - "_hash": 0.2880464219129071, - "aggregationType": null, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ], - "latestDataKeys": [] - } - ], - "timewindow": { - "hideInterval": false, - "hideLastInterval": false, - "hideQuickInterval": false, - "hideAggregation": true, - "hideAggInterval": false, - "hideTimezone": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 86400000, - "fixedTimewindow": { - "startTimeMs": 1680443065451, - "endTimeMs": 1680529465451 - }, - "quickInterval": "CURRENT_DAY" - }, - "aggregation": { - "type": "SUM", - "limit": 50000 - } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "0px", - "settings": { - "stack": true, - "fontSize": 10, - "fontColor": "#545454", - "showTooltip": true, - "tooltipIndividual": false, - "tooltipCumulative": false, - "hideZeros": false, - "grid": { - "verticalLines": false, - "horizontalLines": false, - "outlineWidth": 0, - "color": "#545454", - "backgroundColor": null, - "tickColor": "#DDDDDD" - }, - "xaxis": { - "title": null, - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "min": 0, - "max": null, - "title": null, - "showLabels": true, - "color": "#545454", - "tickSize": null, - "tickDecimals": 0, - "ticksFormatter": "return value % 1000 === 0 ? ((value / 1000) + 'k') : '';" - }, - "defaultBarWidth": 1800000, - "barAlignment": "left", - "comparisonEnabled": false, - "timeForComparison": "previousInterval", - "comparisonCustomIntervalValue": 7200000, - "xaxisSecond": { - "axisPosition": "top", - "title": null, - "showLabels": true - }, - "customLegendEnabled": false, - "dataKeysListForLabels": [], - "showLegend": false, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": true, - "showTotal": false, - "showLatest": false - } - }, - "title": "Transport messages", - "dropShadow": false, - "enableFullscreen": false, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": { - "padding": "0" - }, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "titleTooltip": "", - "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-widget-container > .tb-widget .flot-base {\n opacity: 0.48;\n}\n", - "pageSize": 1024, - "noDataDisplayMessage": "" - }, - "row": 0, - "col": 0, - "id": "8ee72d43-678c-4e25-e9a8-7d4cfd7a5f8e", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, "4b5e47ed-c197-a937-d727-041ba8decec2": { "type": "latest", "sizeX": 5, @@ -294,227 +158,6 @@ "id": "4b5e47ed-c197-a937-d727-041ba8decec2", "typeFullFqn": "system.cards.markdown_card" }, - "eace9148-b02a-48fe-1a95-acd9928aa8c5": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079", - "filterId": null, - "dataKeys": [ - { - "name": "cpuUsage", - "type": "timeseries", - "label": "{i18n:widgets.system-info.cpu}", - "color": "#305680", - "settings": { - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "excludeFromStacking": false, - "showLines": true, - "lineWidth": 3, - "fillLines": false, - "showPoints": false, - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showSeparateAxis": false, - "axisPosition": "left", - "comparisonSettings": { - "showValuesForComparison": true, - "comparisonValuesLabel": "", - "color": "" - }, - "thresholds": [] - }, - "_hash": 0.9347575372081658, - "aggregationType": null, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "memoryUsage", - "type": "timeseries", - "label": "{i18n:widgets.system-info.ram}", - "color": "#ac3bc9", - "settings": { - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "excludeFromStacking": false, - "showLines": true, - "lineWidth": 3, - "fillLines": false, - "showPoints": false, - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showSeparateAxis": false, - "axisPosition": "left", - "comparisonSettings": { - "showValuesForComparison": true, - "comparisonValuesLabel": "", - "color": "" - }, - "thresholds": [] - }, - "_hash": 0.31887216598848855, - "aggregationType": null, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - }, - { - "name": "discUsage", - "type": "timeseries", - "label": "{i18n:widgets.system-info.disk}", - "color": "#40d0ae", - "settings": { - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "excludeFromStacking": false, - "showLines": true, - "lineWidth": 3, - "fillLines": false, - "showPoints": false, - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showSeparateAxis": false, - "axisPosition": "left", - "comparisonSettings": { - "showValuesForComparison": true, - "comparisonValuesLabel": "", - "color": "" - }, - "thresholds": [] - }, - "_hash": 0.26499182606431004, - "aggregationType": null, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ], - "latestDataKeys": null - } - ], - "timewindow": { - "hideInterval": false, - "hideLastInterval": false, - "hideQuickInterval": false, - "hideAggregation": false, - "hideAggInterval": false, - "hideTimezone": false, - "selectedTab": 0, - "realtime": { - "realtimeType": 0, - "timewindowMs": 3600000, - "quickInterval": "CURRENT_DAY", - "interval": 10000 - }, - "aggregation": { - "type": "AVG", - "limit": 25000 - } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "stack": false, - "fontSize": 10, - "fontColor": "#545454", - "showTooltip": true, - "tooltipIndividual": false, - "tooltipCumulative": false, - "hideZeros": false, - "grid": { - "verticalLines": false, - "horizontalLines": false, - "outlineWidth": 0, - "color": "#545454", - "backgroundColor": null, - "tickColor": "#DDDDDD" - }, - "xaxis": { - "title": null, - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "min": 0, - "max": 100, - "title": null, - "showLabels": true, - "color": "#545454", - "tickSize": null, - "tickDecimals": 0, - "ticksFormatter": "" - }, - "shadowSize": 0, - "smoothLines": true, - "comparisonEnabled": false, - "timeForComparison": "previousInterval", - "comparisonCustomIntervalValue": 7200000, - "xaxisSecond": { - "axisPosition": "top", - "title": null, - "showLabels": true - }, - "customLegendEnabled": false, - "dataKeysListForLabels": [], - "showLegend": true, - "legendConfig": { - "direction": "row", - "position": "top", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": false, - "showTotal": false, - "showLatest": false - } - }, - "title": "System Info Chart", - "dropShadow": false, - "enableFullscreen": false, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "useDashboardTimewindow": false, - "showTitleIcon": false, - "titleTooltip": "", - "widgetStyle": {}, - "widgetCss": "\n.tb-legend-keys td .tb-legend-line {\n height: 5px !important;\n vertical-align: middle;\n}\n", - "pageSize": 1024, - "units": "%", - "noDataDisplayMessage": "", - "displayTimewindow": true - }, - "row": 0, - "col": 0, - "id": "eace9148-b02a-48fe-1a95-acd9928aa8c5", - "typeFullFqn": "system.charts.basic_timeseries" - }, "8acbf5df-f9fc-114d-216f-86f081aa4779": { "type": "latest", "sizeX": 5, @@ -2197,6 +1840,798 @@ "col": 0, "id": "163025d8-3ca4-dd1e-c17b-e40d8e03e8a8", "typeFullFqn": "system.cards.markdown_card" + }, + "98bce47d-76df-5fc1-f8b9-8584d73a2439": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": "", + "entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079", + "dataKeys": [ + { + "name": "transportMsgCountHourly", + "type": "timeseries", + "label": "{i18n:widgets.transport-messages.title}", + "color": "#305680", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "bar", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "emptyCircle", + "pointSize": 4, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.39181957822569946, + "decimals": 0 + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + }, + "latestDataKeys": [] + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": true, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000, + "fixedTimewindow": { + "startTimeMs": 1709807941444, + "endTimeMs": 1709894341444 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "SUM", + "limit": 25000 + }, + "timezone": null + }, + "showTitle": false, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "return value === 0 ? value : ((value / 1000) + 'k');", + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": 0, + "max": null + } + }, + "thresholds": [], + "dataZoom": false, + "stack": false, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } + }, + "showLegend": false, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "top", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": true, + "showTotal": false, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "MMMM dd, yyyy", + "lastUpdateAgo": false, + "custom": true + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": false, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "Time series chart", + "dropShadow": false, + "enableFullscreen": false, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-time-series-chart-panel {\n padding: 0;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": true, + "iconSize": "24px", + "icon": "query_builder", + "iconPosition": "left", + "font": { + "size": 14, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.54)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "98bce47d-76df-5fc1-f8b9-8584d73a2439" + }, + "b9174a99-2a00-3dbe-0eae-927fd8506345": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": "", + "entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079", + "dataKeys": [ + { + "name": "cpuUsage", + "type": "timeseries", + "label": "{i18n:widgets.system-info.cpu}", + "color": "#305680", + "settings": { + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": true, + "lineType": "solid", + "lineWidth": 3, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.39181957822569946, + "decimals": null, + "aggregationType": null, + "units": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "memoryUsage", + "type": "timeseries", + "label": "{i18n:widgets.system-info.ram}", + "color": "#AC3BC9", + "settings": { + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": true, + "lineType": "solid", + "lineWidth": 3, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.9392996197028385, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "discUsage", + "type": "timeseries", + "label": "{i18n:widgets.system-info.disk}", + "color": "#40D0AE", + "settings": { + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": true, + "lineType": "solid", + "lineWidth": 3, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.027335636460212864, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + }, + "latestDataKeys": [] + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "timewindowMs": 3600000, + "quickInterval": "CURRENT_DAY", + "interval": 10000 + }, + "aggregation": { + "type": "AVG", + "limit": 25000 + }, + "timezone": null + }, + "showTitle": false, + "backgroundColor": "rgb(255, 255, 255)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "8px", + "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "", + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": 0, + "max": 100 + } + }, + "thresholds": [], + "dataZoom": false, + "stack": false, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "top", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": false, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "dd MMM yyyy HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": false, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 300, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "Time series chart", + "dropShadow": false, + "enableFullscreen": false, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": ".tb-time-series-chart-panel {\n padding: 0;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", + "pageSize": 1024, + "units": "%", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": true, + "iconSize": "24px", + "icon": "query_builder", + "iconPosition": "left", + "font": { + "size": 14, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.54)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "b9174a99-2a00-3dbe-0eae-927fd8506345" } }, "states": { @@ -2288,7 +2723,7 @@ "layouts": { "main": { "widgets": { - "8ee72d43-678c-4e25-e9a8-7d4cfd7a5f8e": { + "98bce47d-76df-5fc1-f8b9-8584d73a2439": { "sizeX": 24, "sizeY": 11, "row": 0, @@ -2315,14 +2750,6 @@ "layouts": { "main": { "widgets": { - "eace9148-b02a-48fe-1a95-acd9928aa8c5": { - "sizeX": 48, - "sizeY": 20, - "row": 8, - "col": 0, - "mobileOrder": 1, - "mobileHeight": 10 - }, "f0479b00-ed47-0a30-0c36-bde7847aae00": { "sizeX": 48, "sizeY": 8, @@ -2330,6 +2757,12 @@ "mobileHeight": 4, "row": 0, "col": 0 + }, + "b9174a99-2a00-3dbe-0eae-927fd8506345": { + "sizeX": 48, + "sizeY": 20, + "row": 8, + "col": 0 } }, "gridSettings": { @@ -2609,6 +3042,5 @@ "dashboardCss": ".tb-widget-container > .tb-widget {\n border: 1px solid rgba(0, 0, 0, 0.05);\n box-shadow: 0px 5px 16px rgba(0, 0, 0, 0.04);\n border-radius: 12px;\n}\n\n.tb-widget-container > .tb-widget:not([style*=\"padding: 0\"]) {\n padding: 16px !important;\n}\n\n.tb-card-title {\n display: grid;\n}\n\n.tb-home-widget-title {\n font-style: normal;\n font-weight: 500;\n font-size: 14px;\n line-height: 20px;\n letter-spacing: 0.25px;\n color: rgba(0, 0, 0, 0.54);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tb-home-widget-link {\n position: relative;\n border-bottom: none;\n}\n\n.tb-home-widget-link:hover {\n border-bottom: none;\n}\n\n.tb-home-widget-link:focus {\n border-bottom: none;\n}\n\n.tb-home-widget-link::after {\n content: 'arrow_forward';\n display: inline-block;\n transform: rotate(315deg);\n font-family: 'Material Icons';\n font-weight: normal;\n font-style: normal;\n font-size: 18px;\n color: rgba(0, 0, 0, 0.12);\n vertical-align: bottom;\n margin-left: 6px; \n}\n\n.tb-home-widget-link:hover::after {\n color: inherit;\n}\n\n.tb-home-widget-info-icon {\n color: rgba(0, 0, 0, 0.12);\n font-size: 16px;\n width: 16px;\n height: 16px;\n line-height: 15px;\n vertical-align: middle;\n}\n\n.tb-widget-container > .tb-widget .tb-timewindow {\n font-size: 14px;\n line-height: 20px;\n letter-spacing: 0.25px;\n color: rgba(0, 0, 0, 0.54);\n padding: 0;\n}\n\n.tb-widget-container > .tb-widget .tb-legend-keys .tb-legend-label {\n cursor: pointer;\n user-select: none;\n font-weight: 400;\n font-size: 14px;\n line-height: 20px;\n letter-spacing: 0.2px;\n color: rgba(0, 0, 0, 0.54);\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .tb-widget-container > .tb-widget {\n border-radius: 4px;\n }\n .tb-widget-container > .tb-widget:not([style*=\"padding: 0\"]) {\n padding: 2px !important;\n }\n .tb-hide-md {\n display: none;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1819px) {\n .tb-widget-container > .tb-widget:not([style*=\"padding: 0\"]) {\n padding: 8px !important;\n }\n .tb-hide-lg {\n display: none;\n }\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n .tb-hide-md-lg {\n display: none;\n }\n\n .tb-home-widget-title {\n font-size: 12px;\n line-height: 16px;\n }\n \n .tb-widget-container > .tb-widget .tb-widget-title {\n padding: 0;\n }\n\n .tb-widget-container > .tb-widget .tb-timewindow {\n font-size: 12px;\n line-height: 16px;\n min-height: 24px;\n padding: 0;\n }\n\n .tb-widget-container > .tb-widget .tb-timewindow .mat-mdc-icon-button.tb-mat-32 {\n width: 24px;\n height: 24px;\n line-height: 24px;\n }\n\n .tb-widget-container > .tb-widget .tb-timewindow .mat-mdc-icon-button.tb-mat-32 .mat-icon {\n width: 18px;\n height: 18px;\n font-size: 18px;\n }\n \n .tb-widget-container > .tb-widget tb-legend {\n padding-bottom: 0 !important;\n }\n \n .tb-widget-container > .tb-widget .tb-legend-keys .tb-legend-label {\n font-size: 11px;\n line-height: 16px;\n letter-spacing: 0.25px;\n }\n}\n\n@media screen and (max-width: 959px), screen and (min-width: 1820px) {\n .tb-hide-not-md-lg {\n display: none;\n }\n}\n" } }, - "externalId": null, "name": "System Administrator Home Page" } \ No newline at end of file diff --git a/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json b/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json index 37e8d82e45..b9a996b8a5 100644 --- a/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json +++ b/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json @@ -69,142 +69,6 @@ "id": "d70cc256-4c7b-ee06-9905-b8c5e546605f", "typeFullFqn": "system.cards.markdown_card" }, - "8ee72d43-678c-4e25-e9a8-7d4cfd7a5f8e": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079", - "filterId": null, - "dataKeys": [ - { - "name": "transportMsgCountHourly", - "type": "timeseries", - "label": "{i18n:widgets.transport-messages.title}", - "color": "#305680", - "settings": {}, - "_hash": 0.2880464219129071, - "aggregationType": null, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ], - "latestDataKeys": [] - } - ], - "timewindow": { - "hideInterval": false, - "hideLastInterval": false, - "hideQuickInterval": false, - "hideAggregation": true, - "hideAggInterval": false, - "hideTimezone": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 86400000, - "fixedTimewindow": { - "startTimeMs": 1680443065451, - "endTimeMs": 1680529465451 - }, - "quickInterval": "CURRENT_DAY" - }, - "aggregation": { - "type": "SUM", - "limit": 50000 - } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "0px", - "settings": { - "stack": true, - "fontSize": 10, - "fontColor": "#545454", - "showTooltip": true, - "tooltipIndividual": false, - "tooltipCumulative": false, - "hideZeros": false, - "grid": { - "verticalLines": false, - "horizontalLines": false, - "outlineWidth": 0, - "color": "#545454", - "backgroundColor": null, - "tickColor": "#DDDDDD" - }, - "xaxis": { - "title": null, - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "min": 0, - "max": null, - "title": null, - "showLabels": true, - "color": "#545454", - "tickSize": null, - "tickDecimals": 0, - "ticksFormatter": "return value % 1000 === 0 ? ((value / 1000) + 'k') : '';" - }, - "defaultBarWidth": 1800000, - "barAlignment": "left", - "comparisonEnabled": false, - "timeForComparison": "previousInterval", - "comparisonCustomIntervalValue": 7200000, - "xaxisSecond": { - "axisPosition": "top", - "title": null, - "showLabels": true - }, - "customLegendEnabled": false, - "dataKeysListForLabels": [], - "showLegend": false, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": true, - "showTotal": false, - "showLatest": false - } - }, - "title": "Transport messages", - "dropShadow": false, - "enableFullscreen": false, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "widgetStyle": { - "padding": "0" - }, - "useDashboardTimewindow": false, - "actions": {}, - "displayTimewindow": true, - "showTitleIcon": false, - "titleTooltip": "", - "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-widget-container > .tb-widget .flot-base {\n opacity: 0.48;\n}\n", - "pageSize": 1024, - "noDataDisplayMessage": "" - }, - "row": 0, - "col": 0, - "id": "8ee72d43-678c-4e25-e9a8-7d4cfd7a5f8e", - "typeFullFqn": "system.charts.timeseries_bars_flot" - }, "867f82cf-ecf2-2d5c-35cb-08c6f2edc3a4": { "type": "static", "sizeX": 7.5, @@ -269,159 +133,6 @@ "id": "a23185ad-dc46-806c-0e50-5b21fb080ace", "typeFullFqn": "system.home_page_widgets.getting_started" }, - "d26e5cd7-75ef-d475-00c7-1a2d1114efe8": { - "type": "timeseries", - "sizeX": 8, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "name": null, - "entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079", - "filterId": null, - "dataKeys": [ - { - "name": "activeDevicesCountHourly", - "type": "timeseries", - "label": "{i18n:device.devices}", - "color": "#305680", - "settings": { - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "excludeFromStacking": false, - "showLines": true, - "lineWidth": 3, - "fillLines": true, - "fillLinesOpacity": 0.04, - "showPoints": false, - "showSeparateAxis": false, - "axisPosition": "left", - "comparisonSettings": { - "showValuesForComparison": true, - "comparisonValuesLabel": "", - "color": "" - }, - "thresholds": [] - }, - "_hash": 0.9688095820365725, - "aggregationType": null, - "units": null, - "decimals": null, - "funcBody": null, - "usePostProcessing": null, - "postFuncBody": null - } - ], - "latestDataKeys": [] - } - ], - "timewindow": { - "hideInterval": false, - "hideLastInterval": false, - "hideQuickInterval": false, - "hideAggregation": true, - "hideAggInterval": true, - "hideTimezone": false, - "selectedTab": 1, - "history": { - "historyType": 0, - "timewindowMs": 2592000000, - "interval": 7200000, - "fixedTimewindow": { - "startTimeMs": 1681400576338, - "endTimeMs": 1681486976338 - }, - "quickInterval": "CURRENT_DAY" - }, - "aggregation": { - "type": "NONE", - "limit": 25000 - } - }, - "showTitle": false, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "0px", - "settings": { - "stack": false, - "fontSize": 10, - "fontColor": "#545454", - "showTooltip": true, - "tooltipIndividual": false, - "tooltipCumulative": false, - "hideZeros": false, - "grid": { - "verticalLines": false, - "horizontalLines": false, - "outlineWidth": 0, - "color": "#545454", - "backgroundColor": null, - "tickColor": "#DDDDDD" - }, - "xaxis": { - "title": null, - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "min": null, - "max": null, - "title": null, - "showLabels": true, - "color": "#545454", - "tickSize": null, - "tickDecimals": 0, - "ticksFormatter": "" - }, - "shadowSize": 0, - "smoothLines": true, - "comparisonEnabled": false, - "timeForComparison": "previousInterval", - "comparisonCustomIntervalValue": 7200000, - "xaxisSecond": { - "axisPosition": "top", - "title": null, - "showLabels": true - }, - "customLegendEnabled": false, - "dataKeysListForLabels": [], - "showLegend": false, - "legendConfig": { - "direction": "column", - "position": "bottom", - "sortDataKeys": false, - "showMin": false, - "showMax": false, - "showAvg": true, - "showTotal": false, - "showLatest": false - } - }, - "title": "Devices activity", - "dropShadow": false, - "enableFullscreen": false, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "useDashboardTimewindow": false, - "displayTimewindow": true, - "showTitleIcon": false, - "titleTooltip": "", - "widgetStyle": { - "padding": "0" - }, - "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n", - "pageSize": 1024, - "noDataDisplayMessage": "" - }, - "row": 0, - "col": 0, - "id": "d26e5cd7-75ef-d475-00c7-1a2d1114efe8", - "typeFullFqn": "system.charts.basic_timeseries" - }, "ebbd0a6e-8a47-e770-5086-7f4974250f2d": { "type": "static", "sizeX": 7.5, @@ -777,6 +488,686 @@ "col": 0, "id": "7ac20b6a-dc40-b18e-9f5f-bca20bc693bb", "typeFullFqn": "system.cards.markdown_card" + }, + "bf7f6efa-7614-3bc0-c4d0-6665d67510a8": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": "", + "entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079", + "dataKeys": [ + { + "name": "transportMsgCountHourly", + "type": "timeseries", + "label": "{i18n:widgets.transport-messages.title}", + "color": "#305680", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "bar", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "emptyCircle", + "pointSize": 4, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.39181957822569946, + "decimals": 0 + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + }, + "latestDataKeys": [] + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": true, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000, + "fixedTimewindow": { + "startTimeMs": 1709807941444, + "endTimeMs": 1709894341444 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "SUM", + "limit": 25000 + }, + "timezone": null + }, + "showTitle": false, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "return value === 0 ? value : ((value / 1000) + 'k');", + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": 0, + "max": null + } + }, + "thresholds": [], + "dataZoom": false, + "stack": false, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } + }, + "showLegend": false, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "top", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": true, + "showTotal": false, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "MMMM dd, yyyy", + "lastUpdateAgo": false, + "custom": true + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": false, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + } + }, + "title": "Time series chart", + "dropShadow": false, + "enableFullscreen": false, + "titleStyle": null, + "configMode": "advanced", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-time-series-chart-panel {\n padding: 0;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": true, + "iconSize": "24px", + "icon": "query_builder", + "iconPosition": "left", + "font": { + "size": 14, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.54)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "bf7f6efa-7614-3bc0-c4d0-6665d67510a8" + }, + "8e71a398-caf5-540d-cec5-6e5dc264343e": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": "", + "entityAliasId": "d9229b29-3f46-de8d-7fe8-eb0c43c75079", + "dataKeys": [ + { + "name": "activeDevicesCountHourly", + "type": "timeseries", + "label": "{i18n:device.devices}", + "color": "#305680", + "settings": { + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": true, + "lineType": "solid", + "lineWidth": 3, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "opacity", + "opacity": 0.04, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.39181957822569946, + "decimals": 0, + "aggregationType": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + }, + "latestDataKeys": [] + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": true, + "hideAggInterval": true, + "hideTimezone": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000, + "fixedTimewindow": { + "startTimeMs": 1709807941444, + "endTimeMs": 1709894341444 + }, + "quickInterval": "CURRENT_DAY" + }, + "aggregation": { + "type": "NONE", + "limit": 25000 + }, + "timezone": null + }, + "showTitle": false, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "thresholds": [], + "dataZoom": false, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "", + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "min": 0, + "max": null + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } + }, + "showLegend": false, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "top", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": true, + "showTotal": false, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "MMMM dd, yyyy", + "lastUpdateAgo": false, + "custom": true + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": false, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + }, + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": null, + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": 0 + } + }, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 200, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + } + }, + "title": "Time series chart", + "dropShadow": false, + "enableFullscreen": false, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-time-series-chart-panel {\n padding: 0;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": true, + "iconSize": "24px", + "icon": "query_builder", + "iconPosition": "left", + "font": { + "size": 14, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.54)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "8e71a398-caf5-540d-cec5-6e5dc264343e" } }, "states": { @@ -868,7 +1259,7 @@ "layouts": { "main": { "widgets": { - "8ee72d43-678c-4e25-e9a8-7d4cfd7a5f8e": { + "bf7f6efa-7614-3bc0-c4d0-6665d67510a8": { "sizeX": 24, "sizeY": 11, "row": 0, @@ -895,7 +1286,7 @@ "layouts": { "main": { "widgets": { - "d26e5cd7-75ef-d475-00c7-1a2d1114efe8": { + "8e71a398-caf5-540d-cec5-6e5dc264343e": { "sizeX": 24, "sizeY": 11, "row": 0, @@ -1049,6 +1440,5 @@ "dashboardCss": ".tb-widget-container > .tb-widget {\n border: 1px solid rgba(0, 0, 0, 0.05);\n box-shadow: 0px 5px 16px rgba(0, 0, 0, 0.04);\n border-radius: 12px;\n}\n\n.tb-widget-container > .tb-widget:not([style*=\"padding: 0\"]) {\n padding: 16px !important;\n}\n\n.tb-card-title {\n display: grid;\n}\n\n.tb-home-widget-title {\n font-style: normal;\n font-weight: 500;\n font-size: 14px;\n line-height: 20px;\n letter-spacing: 0.25px;\n color: rgba(0, 0, 0, 0.54);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tb-home-widget-link {\n position: relative;\n border-bottom: none;\n}\n\n.tb-home-widget-link:hover {\n border-bottom: none;\n}\n\n.tb-home-widget-link:focus {\n border-bottom: none;\n}\n\n.tb-home-widget-link::after {\n content: 'arrow_forward';\n display: inline-block;\n transform: rotate(315deg);\n font-family: 'Material Icons';\n font-weight: normal;\n font-style: normal;\n font-size: 18px;\n color: rgba(0, 0, 0, 0.12);\n vertical-align: bottom;\n margin-left: 6px; \n}\n\n.tb-home-widget-link:hover::after {\n color: inherit;\n}\n\n.tb-home-widget-info-icon {\n color: rgba(0, 0, 0, 0.12);\n font-size: 16px;\n width: 16px;\n height: 16px;\n line-height: 15px;\n vertical-align: middle;\n}\n\n.tb-widget-container > .tb-widget .tb-timewindow {\n font-size: 14px;\n line-height: 20px;\n letter-spacing: 0.25px;\n color: rgba(0, 0, 0, 0.54);\n padding: 0;\n}\n\n.tb-widget-container > .tb-widget .tb-legend-keys .tb-legend-label {\n cursor: pointer;\n user-select: none;\n font-weight: 400;\n font-size: 14px;\n line-height: 20px;\n letter-spacing: 0.2px;\n color: rgba(0, 0, 0, 0.54);\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .tb-widget-container > .tb-widget {\n border-radius: 4px;\n }\n .tb-widget-container > .tb-widget:not([style*=\"padding: 0\"]) {\n padding: 2px !important;\n }\n .tb-hide-md {\n display: none;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1819px) {\n .tb-widget-container > .tb-widget:not([style*=\"padding: 0\"]) {\n padding: 8px !important;\n }\n .tb-hide-lg {\n display: none;\n }\n}\n\n@media screen and (min-width: 960px) and (max-width: 1819px) {\n .tb-hide-md-lg {\n display: none;\n }\n\n .tb-home-widget-title {\n font-size: 12px;\n line-height: 16px;\n }\n \n .tb-widget-container > .tb-widget .tb-widget-title {\n padding: 0;\n }\n\n .tb-widget-container > .tb-widget .tb-timewindow {\n font-size: 12px;\n line-height: 16px;\n min-height: 24px;\n padding: 0;\n }\n\n .tb-widget-container > .tb-widget .tb-timewindow .mat-mdc-icon-button.tb-mat-32 {\n width: 24px;\n height: 24px;\n line-height: 24px;\n }\n\n .tb-widget-container > .tb-widget .tb-timewindow .mat-mdc-icon-button.tb-mat-32 .mat-icon {\n width: 18px;\n height: 18px;\n font-size: 18px;\n }\n \n .tb-widget-container > .tb-widget tb-legend {\n padding-bottom: 0 !important;\n }\n \n .tb-widget-container > .tb-widget .tb-legend-keys .tb-legend-label {\n font-size: 11px;\n line-height: 16px;\n letter-spacing: 0.25px;\n }\n}\n\n@media screen and (max-width: 959px), screen and (min-width: 1820px) {\n .tb-hide-not-md-lg {\n display: none;\n }\n}\n" } }, - "externalId": null, "name": "Tenant Administrator Home Page" -} +} \ No newline at end of file From 9779b80d94398565031b6004a333f34b21a69ea6 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 11 Mar 2024 17:53:15 +0200 Subject: [PATCH 339/397] UI: API usage dashboard added y-axis settings --- ui-ngx/src/assets/dashboard/api_usage.json | 2229 ++++++++++++-------- 1 file changed, 1395 insertions(+), 834 deletions(-) diff --git a/ui-ngx/src/assets/dashboard/api_usage.json b/ui-ngx/src/assets/dashboard/api_usage.json index 7d9eefd18d..8b285b2b0b 100644 --- a/ui-ngx/src/assets/dashboard/api_usage.json +++ b/ui-ngx/src/assets/dashboard/api_usage.json @@ -1373,42 +1373,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -1501,6 +1507,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -1693,42 +1709,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -1821,6 +1843,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -2095,42 +2127,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -2223,6 +2261,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -2419,42 +2467,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -2547,6 +2601,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -2739,42 +2803,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -2867,6 +2937,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -3136,42 +3216,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -3264,6 +3350,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -3460,42 +3556,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -3588,6 +3690,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -3773,42 +3885,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -3901,6 +4019,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -4043,42 +4171,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -4171,6 +4305,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -4304,42 +4448,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -4432,6 +4582,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -4581,42 +4741,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -4709,6 +4875,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -4858,42 +5034,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -4986,6 +5168,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -5119,42 +5311,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -5247,6 +5445,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -5380,42 +5588,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -5508,6 +5722,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -5641,42 +5865,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -5769,6 +5999,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -5902,42 +6142,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -6030,6 +6276,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -6163,42 +6419,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -6291,6 +6553,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -6424,42 +6696,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -6552,6 +6830,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -6685,42 +6973,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -6813,6 +7107,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -6946,42 +7250,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -7074,6 +7384,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 1000, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -7152,26 +7472,63 @@ "label": "{i18n:api-usage.successful}", "color": "#4caf50", "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 3, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } } - ], - "comparisonSettings": { - "showValuesForComparison": true } }, "_hash": 0.15490750967648736, @@ -7188,59 +7545,145 @@ "label": "{i18n:api-usage.permanent-failures}", "color": "#ef5350", "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 3, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.4186621166514697 - }, - { - "name": "tmpFailed", - "type": "timeseries", - "label": "{i18n:api-usage.processing-failures}", - "color": "#ffc107", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.4186621166514697, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "tmpFailed", + "type": "timeseries", + "label": "{i18n:api-usage.processing-failures}", + "color": "#ffc107", + "settings": { + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 3, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } } - ], - "comparisonSettings": { - "showValuesForComparison": true } }, - "_hash": 0.49891007198715376 + "_hash": 0.49891007198715376, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null } ], "alarmFilterConfig": { @@ -7269,42 +7712,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -7397,6 +7846,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 300, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", @@ -7475,29 +7934,72 @@ "label": "{i18n:api-usage.permanent-timeouts}", "color": "#4caf50", "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 3, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } } - ], - "comparisonSettings": { - "showValuesForComparison": true } }, - "_hash": 0.565222981550328 + "_hash": 0.565222981550328, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null }, { "name": "tmpTimeout", @@ -7505,29 +8007,72 @@ "label": "{i18n:api-usage.processing-timeouts}", "color": "#9c27b0", "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 1, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } } - ], - "comparisonSettings": { - "showValuesForComparison": true } }, - "_hash": 0.2679547062508352 + "_hash": 0.2679547062508352, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null } ], "alarmFilterConfig": { @@ -7556,42 +8101,48 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "showTicks": true, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": true, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "ticksFormatter": "const rounder = Math.pow(10, 1);\nconst powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nlet formattedValue = value;\nlet key = '';\nfor (let power of powers) {\n let reduced = value / power.value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n formattedValue = reduced;\n key = power.key;\n break;\n }\n}\nreturn formattedValue + key;", - "min": null, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -7684,6 +8235,16 @@ "tooltipDateInterval": true, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 300, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, "background": { "type": "color", "color": "#fff", From b3d536a5670f757ad05801c144f49d9e8b3ed8f8 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 12 Mar 2024 14:32:27 +0200 Subject: [PATCH 340/397] UI: Time series chart widgets performance and layout improvements. Update echarts version. --- ui-ngx/package.json | 2 +- ...charts+5.4.3.patch => echarts+5.5.0.patch} | 66 ++++----- ...e-series-chart-basic-config.component.html | 6 + ...ime-series-chart-basic-config.component.ts | 2 + .../bar-chart-with-labels-widget.component.ts | 7 +- .../lib/chart/doughnut-widget.component.ts | 2 +- .../widget/lib/chart/echarts-widget.models.ts | 1 + .../lib/chart/range-chart-widget.component.ts | 2 +- .../lib/chart/time-series-chart-bar.models.ts | 25 ++-- .../time-series-chart-widget.component.html | 3 +- .../time-series-chart-widget.component.scss | 20 +-- .../time-series-chart-widget.component.ts | 4 + .../chart/time-series-chart-widget.models.ts | 4 +- .../lib/chart/time-series-chart.models.ts | 24 +-- .../widget/lib/chart/time-series-chart.ts | 60 ++++++-- ...eries-chart-widget-settings.component.html | 17 ++- ...-series-chart-widget-settings.component.ts | 3 +- .../assets/dashboard/sys_admin_home_page.json | 12 +- .../dashboard/tenant_admin_home_page.json | 139 +++++++----------- .../assets/locale/locale.constant-en_US.json | 1 + ui-ngx/yarn.lock | 18 +-- 21 files changed, 211 insertions(+), 207 deletions(-) rename ui-ngx/patches/{echarts+5.4.3.patch => echarts+5.5.0.patch} (89%) diff --git a/ui-ngx/package.json b/ui-ngx/package.json index ab60ebd525..c39817749f 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -55,7 +55,7 @@ "core-js": "^3.29.1", "date-fns": "2.0.0-alpha.27", "dayjs": "1.11.4", - "echarts": "^5.4.3", + "echarts": "^5.5.0", "flot": "https://github.com/thingsboard/flot.git#0.9-work", "flot.curvedlines": "https://github.com/MichaelZinsmaier/CurvedLines.git#master", "font-awesome": "^4.7.0", diff --git a/ui-ngx/patches/echarts+5.4.3.patch b/ui-ngx/patches/echarts+5.5.0.patch similarity index 89% rename from ui-ngx/patches/echarts+5.4.3.patch rename to ui-ngx/patches/echarts+5.5.0.patch index bca89c616c..b25599afd8 100644 --- a/ui-ngx/patches/echarts+5.4.3.patch +++ b/ui-ngx/patches/echarts+5.5.0.patch @@ -1,8 +1,8 @@ diff --git a/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js b/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js -index 112ebe3..9afc9b7 100644 +index d6c05f3..d09baed 100644 --- a/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js +++ b/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js -@@ -422,7 +422,10 @@ function (_super) { +@@ -362,7 +362,10 @@ var DataZoomModel = /** @class */function (_super) { return axisProxy.getDataValueWindow(); } } else { @@ -14,32 +14,30 @@ index 112ebe3..9afc9b7 100644 } }; /** -@@ -449,11 +452,11 @@ function (_super) { +@@ -381,10 +384,10 @@ var DataZoomModel = /** @class */function (_super) { + var axisInfo = this._targetAxisInfoMap.get(axisDim); for (var j = 0; j < axisInfo.indexList.length; j++) { var proxy = this.getAxisProxy(axisDim, axisInfo.indexList[j]); - - if (proxy.hostedBy(this)) { + if (proxy && proxy.hostedBy(this)) { return proxy; } - - if (!firstProxy) { + if (proxy && !firstProxy) { firstProxy = proxy; } } diff --git a/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js b/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js -index 7163279..c37f9c2 100644 +index 06469b2..ccfbfa6 100644 --- a/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js +++ b/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js -@@ -112,12 +112,15 @@ var getRangeHandlers = { +@@ -96,11 +96,14 @@ var getRangeHandlers = { range[0] = (range[0] - percentPoint) * scale + percentPoint; - range[1] = (range[1] - percentPoint) * scale + percentPoint; // Restrict range. - + range[1] = (range[1] - percentPoint) * scale + percentPoint; + // Restrict range. - var minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); - sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan); - this.range = range; -- - if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { - return range; + var proxy = this.dataZoomModel.findRepresentativeAxisProxy(); @@ -47,7 +45,6 @@ index 7163279..c37f9c2 100644 + var minMaxSpan = proxy.getMinMaxSpan(); + sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan); + this.range = range; -+ + if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { + return range; + } @@ -55,7 +52,7 @@ index 7163279..c37f9c2 100644 }, pan: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e) { diff --git a/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js b/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js -index 590ef51..aff8a0a 100644 +index 98912e0..2e809af 100644 --- a/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js +++ b/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js @@ -64,7 +64,7 @@ var DEFAULT_MOVE_HANDLE_SIZE = 7; @@ -67,7 +64,7 @@ index 590ef51..aff8a0a 100644 var REALTIME_ANIMATION_CONFIG = { easing: 'cubicOut', duration: 100, -@@ -406,34 +406,37 @@ function (_super) { +@@ -359,30 +359,33 @@ var SliderZoomView = /** @class */function (_super) { var result; var ecModel = this.ecModel; dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { @@ -76,20 +73,16 @@ index 590ef51..aff8a0a 100644 - if (result) { - return; - } -- - if (showDataShadow !== true && indexOf(SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')) < 0) { - return; - } -- - var thisAxis = ecModel.getComponent(getAxisMainType(axisDim), axisIndex).axis; - var otherDim = getOtherDim(axisDim); - var otherAxisInverse; - var coordSys = seriesModel.coordinateSystem; -- - if (otherDim != null && coordSys.getOtherAxis) { - otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse; - } -- - otherDim = seriesModel.getData().mapDimension(otherDim); - result = { - thisAxis: thisAxis, @@ -106,20 +99,16 @@ index 590ef51..aff8a0a 100644 + if (result) { + return; + } -+ + if (showDataShadow !== true && indexOf(SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')) < 0) { + return; + } -+ + var thisAxis = ecModel.getComponent(getAxisMainType(axisDim), axisIndex).axis; + var otherDim = getOtherDim(axisDim); + var otherAxisInverse; + var coordSys = seriesModel.coordinateSystem; -+ + if (otherDim != null && coordSys.getOtherAxis) { + otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse; + } -+ + otherDim = seriesModel.getData().mapDimension(otherDim); + result = { + thisAxis: thisAxis, @@ -133,10 +122,10 @@ index 590ef51..aff8a0a 100644 }, this); return result; }; -@@ -595,12 +598,17 @@ function (_super) { - +@@ -530,12 +533,17 @@ var SliderZoomView = /** @class */function (_super) { + var dataZoomModel = this.dataZoomModel; + var handleEnds = this._handleEnds; var viewExtend = this._getViewExtent(); - - var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); - var percentExtent = [0, 100]; - sliderMove(delta, handleEnds, viewExtend, dataZoomModel.get('zoomLock') ? 'all' : handleIndex, minMaxSpan.minSpan != null ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null, minMaxSpan.maxSpan != null ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null); @@ -155,13 +144,13 @@ index 590ef51..aff8a0a 100644 + return false; + } }; - SliderZoomView.prototype._updateView = function (nonRealtime) { + var displaybles = this._displayables; diff --git a/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js b/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js -index 3871784..9bab428 100644 +index ce98fed..361b138 100644 --- a/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js +++ b/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js -@@ -91,7 +91,10 @@ var dataZoomProcessor = { +@@ -90,7 +90,10 @@ var dataZoomProcessor = { // init stage and not after action dispatch handler, because // reset should be called after seriesData.restoreData. dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { @@ -170,12 +159,12 @@ index 3871784..9bab428 100644 + if (axisProxy) { + axisProxy.reset(dataZoomModel); + } - }); // Caution: data zoom filtering is order sensitive when using + }); + // Caution: data zoom filtering is order sensitive when using // percent range and no min/max/scale set on axis. - // For example, we have dataZoom definition: -@@ -108,7 +111,10 @@ var dataZoomProcessor = { +@@ -107,7 +110,10 @@ var dataZoomProcessor = { + // So we should filter x-axis after reset x-axis immediately, // and then reset y-axis and filter y-axis. - dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { - dataZoomModel.getAxisProxy(axisDim, axisIndex).filterData(dataZoomModel, api); + var axisProxy = dataZoomModel.getAxisProxy(axisDim, axisIndex); @@ -186,23 +175,22 @@ index 3871784..9bab428 100644 }); ecModel.eachComponent('dataZoom', function (dataZoomModel) { diff --git a/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js b/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js -index c5ee405..957ffd2 100644 +index cf8d6bc..9b30ec1 100644 --- a/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js +++ b/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js -@@ -129,10 +129,13 @@ function (_super) { +@@ -109,9 +109,12 @@ var DataZoomFeature = /** @class */function (_super) { var axisModel = axis.model; - var dataZoomModel = findDataZoom(dimName, axisModel, ecModel); // Restrict range. - + var dataZoomModel = findDataZoom(dimName, axisModel, ecModel); + // Restrict range. - var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan(); +- if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) { +- minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan); + var proxy = dataZoomModel.findRepresentativeAxisProxy(axisModel); + if (proxy) { + var minMaxSpan = proxy.getMinMaxSpan(); - -- if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) { -- minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan); + if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) { + minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan); + } } - dataZoomModel && (snapshot[dataZoomModel.id] = { + dataZoomId: dataZoomModel.id, diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html index adaeb78acb..b254b4df68 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html @@ -245,6 +245,12 @@
    +
    +
    {{ 'widget-config.card-padding' | translate }}
    + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts index ba4b4c6371..31dca75c7e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.ts @@ -174,6 +174,7 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon cardButtons: [this.getCardButtons(configData.config), []], borderRadius: [configData.config.borderRadius, []], + padding: [settings.padding, []], actions: [configData.config.actions || {}, []] }); @@ -229,6 +230,7 @@ export class TimeSeriesChartBasicConfigComponent extends BasicWidgetConfigCompon this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.widgetConfig.config.borderRadius = config.borderRadius; + this.widgetConfig.config.settings.padding = config.padding; this.widgetConfig.config.actions = config.actions; return this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts index c523bf7927..4784a65c88 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts @@ -37,7 +37,6 @@ import { } from '@shared/models/widget-settings.models'; import { ResizeObserver } from '@juggle/resize-observer'; import { formatValue } from '@core/utils'; -import { DataKey } from '@shared/models/widget.models'; import { Observable } from 'rxjs'; import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; @@ -53,9 +52,9 @@ import { CallbackDataParams, CustomSeriesRenderItem, LabelLayoutOptionCallback } import { ECharts, echartsModule, - EChartsOption, EChartsSeriesItem, + EChartsOption, + EChartsSeriesItem, echartsTooltipFormatter, - NamedDataSet, toNamedData } from '@home/components/widget/lib/chart/echarts-widget.models'; import { IntervalMath } from '@shared/models/time/time.models'; @@ -381,7 +380,7 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft tooltip: { trigger: 'axis', confine: true, - appendToBody: true, + appendTo: 'body', axisPointer: { type: 'shadow' }, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts index 723b581fc5..d215f37a32 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/doughnut-widget.component.ts @@ -387,7 +387,7 @@ export class DoughnutWidgetComponent implements OnInit, OnDestroy, AfterViewInit tooltip: { trigger: this.settings.showTooltip ? 'item' : 'none', confine: false, - appendToBody: true + appendTo: 'body', }, series: [ { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts index 06e8e98fd0..c446fcbda1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts @@ -153,6 +153,7 @@ export type EChartsSeriesItem = { id: string; dataKey: DataKey; data: NamedDataSet; + dataSet?: DataSet; enabled: boolean; units?: string; decimals?: number; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts index 0a8c15b247..9909be6532 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts @@ -318,7 +318,7 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn tooltip: { trigger: 'axis', confine: true, - appendToBody: true, + appendTo: 'body', axisPointer: { type: 'shadow' }, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts index bf7f6cf764..c00a078b2f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-bar.models.ts @@ -33,14 +33,18 @@ export interface BarVisualSettings { borderRadius: number; } +export interface BarRenderSharedContext { + timeInterval: Interval; + noAggregationBarWidthStrategy: TimeSeriesChartNoAggregationBarWidthStrategy; + noAggregationWidthRelative: boolean; + noAggregationWidth: number; +} + export interface BarRenderContext { + shared: BarRenderSharedContext; barsCount?: number; barIndex?: number; - noAggregation: boolean; - noAggregationBarWidthStrategy: TimeSeriesChartNoAggregationBarWidthStrategy; - noAggregationWidthRelative?: boolean; - noAggregationWidth?: number; - timeInterval?: Interval; + noAggregation?: boolean; visualSettings?: BarVisualSettings; labelOption?: SeriesLabelOption; barStackIndex?: number; @@ -56,20 +60,20 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C const ts = start ? start : time; const separateBar = renderCtx.noAggregation && - renderCtx.noAggregationBarWidthStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate; + renderCtx.shared.noAggregationBarWidthStrategy === TimeSeriesChartNoAggregationBarWidthStrategy.separate; if (renderCtx.noAggregation) { - if (renderCtx.noAggregationWidthRelative) { + if (renderCtx.shared.noAggregationWidthRelative) { const scaleWidth = api.getWidth() / api.size([1,0])[0]; - interval = scaleWidth * (renderCtx.noAggregationWidth / 100); + interval = scaleWidth * (renderCtx.shared.noAggregationWidth / 100); } else { - interval = renderCtx.noAggregationWidth; + interval = renderCtx.shared.noAggregationWidth; } start = time - interval / 2; end = time + interval / 2; } if (!start || !end || !interval) { - interval = IntervalMath.numberValue(renderCtx.timeInterval); + interval = IntervalMath.numberValue(renderCtx.shared.timeInterval); start = time - interval / 2; } @@ -147,7 +151,6 @@ export const renderTimeSeriesBar = (params: CustomSeriesRenderItemParams, api: C } else { borderRadius = [renderCtx.visualSettings.borderRadius, renderCtx.visualSettings.borderRadius, 0, 0]; } - return rectShape && { type: 'rect', id: time + '', diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.html index 1b96aac669..4430579899 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.html @@ -15,7 +15,8 @@ limitations under the License. --> -
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss index 7da3d8e4b5..66428d9d91 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss @@ -24,7 +24,9 @@ $maxLegendHeight: 35%; display: flex; flex-direction: column; gap: 8px; - padding: 20px 24px 24px 24px; + &.overlay { + padding: 20px 24px 24px 24px; + } > div:not(.tb-time-series-chart-overlay) { z-index: 1; } @@ -101,22 +103,6 @@ $maxLegendHeight: 35%; width: 100%; table-layout: auto; } - - thead th, tbody th { - position: sticky; - z-index: 1; - backdrop-filter: blur(5000px); - } - thead th { - top: 0; - &:first-child { - left: 0; - z-index: 2; - } - } - tbody th { - left: 0; - } th, td { &:not(:last-child) { padding-right: 8px; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts index 560309b08b..fbb23c6c84 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.ts @@ -70,6 +70,8 @@ export class TimeSeriesChartWidgetComponent implements OnInit, OnDestroy, AfterV backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; + overlayEnabled: boolean; + padding: string; legendLabelStyle: ComponentStyle; disabledLegendLabelStyle: ComponentStyle; @@ -90,6 +92,8 @@ export class TimeSeriesChartWidgetComponent implements OnInit, OnDestroy, AfterV this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); + this.overlayEnabled = this.settings.background.overlay.enabled; + this.padding = this.overlayEnabled ? undefined : this.settings.padding; this.showLegend = this.settings.showLegend; if (this.showLegend) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.models.ts index ccfca7c4d0..6edf87251c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.models.ts @@ -25,6 +25,7 @@ export interface TimeSeriesChartWidgetSettings extends TimeSeriesChartSettings { legendLabelColor: string; legendConfig: LegendConfig; background: BackgroundSettings; + padding: string; } export const timeSeriesChartWidgetDefaultSettings: TimeSeriesChartWidgetSettings = @@ -48,5 +49,6 @@ export const timeSeriesChartWidgetDefaultSettings: TimeSeriesChartWidgetSettings color: 'rgba(255,255,255,0.72)', blur: 3 } - } + }, + padding: '12px' } as TimeSeriesChartWidgetSettings); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index 02cbdb2ff8..b5d5968565 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -37,11 +37,11 @@ import { import { LinearGradientObject } from 'zrender/lib/graphic/LinearGradient'; import tinycolor from 'tinycolor2'; import Axis2D from 'echarts/types/src/coord/cartesian/Axis2D'; -import { Interval } from '@shared/models/time/time.models'; import { ValueAxisBaseOption } from 'echarts/types/src/coord/axisCommonTypes'; import { SeriesLabelOption } from 'echarts/types/src/util/types'; import { BarRenderContext, + BarRenderSharedContext, BarVisualSettings, renderTimeSeriesBar } from '@home/components/widget/lib/chart/time-series-chart-bar.models'; @@ -915,13 +915,12 @@ export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartAxisSetting export const generateChartData = (dataItems: TimeSeriesChartDataItem[], thresholdItems: TimeSeriesChartThresholdItem[], - timeInterval: Interval, stack: boolean, noAggregation: boolean, - noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings, + barRenderSharedContext: BarRenderSharedContext, darkMode: boolean): Array => { - let series = generateChartSeries(dataItems, timeInterval, - stack, noAggregation, noAggregationBarWidthSettings, darkMode); + let series = generateChartSeries(dataItems, + stack, noAggregation, barRenderSharedContext, darkMode); if (thresholdItems.length) { const thresholds = generateChartThresholds(thresholdItems, darkMode); series = series.concat(thresholds); @@ -1030,10 +1029,9 @@ const createThresholdData = (val: string | number, item: TimeSeriesChartThreshol ]; const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], - timeInterval: Interval, stack: boolean, noAggregation: boolean, - noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings, + barRenderSharedContext: BarRenderSharedContext, darkMode: boolean): Array => { const series: Array = []; const enabledDataItems = dataItems.filter(d => d.enabled); @@ -1053,21 +1051,11 @@ const generateChartSeries = (dataItems: TimeSeriesChartDataItem[], if (item.dataKey.settings.type === TimeSeriesChartSeriesType.bar) { if (!item.barRenderContext) { item.barRenderContext = {noAggregation, - noAggregationBarWidthStrategy: noAggregationBarWidthSettings.strategy}; - const targetWidth = noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group ? - noAggregationBarWidthSettings.groupWidth : noAggregationBarWidthSettings.barWidth; - if (targetWidth.relative) { - item.barRenderContext.noAggregationWidthRelative = true; - item.barRenderContext.noAggregationWidth = targetWidth.relativeWidth; - } else { - item.barRenderContext.noAggregationWidthRelative = false; - item.barRenderContext.noAggregationWidth = targetWidth.absoluteWidth; - } + shared: barRenderSharedContext}; } item.barRenderContext.noAggregation = noAggregation; item.barRenderContext.barsCount = barsCount; item.barRenderContext.barIndex = stack ? barGroups.indexOf(item.yAxisIndex) : barDataItems.indexOf(item); - item.barRenderContext.timeInterval = timeInterval; if (stack) { const stackItems = enabledDataItems.filter(d => d.yAxisIndex === item.yAxisIndex); item.barRenderContext.currentStackItems = stackItems; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index abad3f79e8..57e52f5f5d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -19,21 +19,26 @@ import { AxisPosition, calculateThresholdsOffset, createTimeSeriesXAxisOption, - createTimeSeriesYAxis, defaultTimeSeriesChartYAxisSettings, + createTimeSeriesYAxis, + defaultTimeSeriesChartYAxisSettings, generateChartData, parseThresholdData, SeriesLabelPosition, TimeSeriesChartDataItem, timeSeriesChartDefaultSettings, timeSeriesChartKeyDefaultSettings, - TimeSeriesChartKeySettings, + TimeSeriesChartKeySettings, TimeSeriesChartNoAggregationBarWidthStrategy, TimeSeriesChartSeriesType, TimeSeriesChartSettings, - TimeSeriesChartShape, TimeSeriesChartThreshold, timeSeriesChartThresholdDefaultSettings, + TimeSeriesChartShape, + TimeSeriesChartThreshold, + timeSeriesChartThresholdDefaultSettings, TimeSeriesChartThresholdItem, TimeSeriesChartThresholdType, TimeSeriesChartType, - TimeSeriesChartYAxis, TimeSeriesChartYAxisId, TimeSeriesChartYAxisSettings, + TimeSeriesChartYAxis, + TimeSeriesChartYAxisId, + TimeSeriesChartYAxisSettings, updateDarkMode } from '@home/components/widget/lib/chart/time-series-chart.models'; import { ResizeObserver } from '@juggle/resize-observer'; @@ -52,7 +57,7 @@ import { toNamedData } from '@home/components/widget/lib/chart/echarts-widget.models'; import { DateFormatProcessor } from '@shared/models/widget-settings.models'; -import { isDefinedAndNotNull, mergeDeep } from '@core/utils'; +import { isDefinedAndNotNull, isEqual, mergeDeep } from '@core/utils'; import { DataKey, Datasource, DatasourceType, widgetType } from '@shared/models/widget.models'; import * as echarts from 'echarts/core'; import { CallbackDataParams } from 'echarts/types/dist/shared'; @@ -64,6 +69,7 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { WidgetSubscriptionOptions } from '@core/api/widget-api.models'; import { DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; import { DeepPartial } from '@shared/models/common'; +import { BarRenderSharedContext } from '@home/components/widget/lib/chart/time-series-chart-bar.models'; export class TbTimeSeriesChart { @@ -119,6 +125,8 @@ export class TbTimeSeriesChart { private highlightedDataKey: DataKey; + private barRenderSharedContext: BarRenderSharedContext; + yMin$ = this.yMinSubject.asObservable(); yMax$ = this.yMaxSubject.asObservable(); @@ -156,7 +164,10 @@ export class TbTimeSeriesChart { public update(): void { for (const item of this.dataItems) { const datasourceData = this.ctx.data ? this.ctx.data.find(d => d.dataKey === item.dataKey) : null; - item.data = datasourceData?.data ? toNamedData(datasourceData.data) : []; + if (!isEqual(item.dataSet, datasourceData?.data)) { + item.dataSet = datasourceData?.data; + item.data = datasourceData?.data ? toNamedData(datasourceData.data) : []; + } } this.onResize(); if (this.timeSeriesChart) { @@ -168,6 +179,7 @@ export class TbTimeSeriesChart { } else { this.timeSeriesChartOptions.tooltip[0].axisPointer.type = 'shadow'; } + this.barRenderSharedContext.timeInterval = this.ctx.timeWindow.interval; this.updateSeriesData(true); if (this.highlightedDataKey) { this.keyEnter(this.highlightedDataKey); @@ -277,6 +289,15 @@ export class TbTimeSeriesChart { } private setupData(): void { + const noAggregationBarWidthSettings = this.settings.noAggregationBarWidthSettings; + const targetBarWidth = noAggregationBarWidthSettings.strategy === TimeSeriesChartNoAggregationBarWidthStrategy.group ? + noAggregationBarWidthSettings.groupWidth : noAggregationBarWidthSettings.barWidth; + this.barRenderSharedContext = { + timeInterval: this.ctx.timeWindow?.interval, + noAggregationBarWidthStrategy: noAggregationBarWidthSettings.strategy, + noAggregationWidthRelative: targetBarWidth.relative, + noAggregationWidth: targetBarWidth.relative ? targetBarWidth.relativeWidth : targetBarWidth.absoluteWidth + }; if (this.ctx.datasources.length) { for (const datasource of this.ctx.datasources) { const dataKeys = datasource.dataKeys; @@ -458,7 +479,7 @@ export class TbTimeSeriesChart { tooltip: [{ trigger: this.settings.tooltipTrigger === EChartsTooltipTrigger.axis ? 'axis' : 'item', confine: true, - appendToBody: true, + appendTo: 'body', axisPointer: { type: this.noAggregation ? 'line' : 'shadow' }, @@ -533,10 +554,9 @@ export class TbTimeSeriesChart { private updateSeries(): Array { return generateChartData(this.dataItems, this.thresholdItems, - this.ctx.timeWindow.interval, this.settings.stack, this.noAggregation, - this.settings.noAggregationBarWidthSettings, this.darkMode); + this.barRenderSharedContext, this.darkMode); } private updateAxes() { @@ -721,10 +741,32 @@ export class TbTimeSeriesChart { const width = this.timeSeriesChart.getWidth(); const height = this.timeSeriesChart.getHeight(); if (width !== shapeWidth || height !== shapeHeight) { + let barItems: TimeSeriesChartDataItem[]; + if (this.animationEnabled()) { + barItems = + this.dataItems.filter(d => d.enabled && d.data.length && + d.dataKey.settings.type === TimeSeriesChartSeriesType.bar); + this.updateBarsAnimation(barItems, false); + } this.timeSeriesChart.resize(); + if (this.animationEnabled()) { + this.updateBarsAnimation(barItems, true); + } } } } } + private animationEnabled(): boolean { + return this.settings.animation.animation; + } + + private updateBarsAnimation(barItems: TimeSeriesChartDataItem[], animation: boolean) { + if (barItems.length) { + barItems.forEach(item => { + item.option.animation = animation; + }); + this.timeSeriesChart.setOption(this.timeSeriesChartOptions); + } + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html index 42249a67cd..cd6f1255f8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html @@ -160,10 +160,19 @@ -
    -
    {{ 'widgets.background.background' | translate }}
    - - +
    +
    widget-config.card-appearance
    +
    +
    {{ 'widgets.background.background' | translate }}
    + + +
    +
    +
    {{ 'widget-config.card-padding' | translate }}
    + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts index e270b97137..6edab7ecf2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.ts @@ -140,7 +140,8 @@ export class TimeSeriesChartWidgetSettingsComponent extends WidgetSettingsCompon animation: [settings.animation, []], - background: [settings.background, []] + background: [settings.background, []], + padding: [settings.padding, []] }); } diff --git a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json index b308bc98d6..29c692ad87 100644 --- a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json +++ b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json @@ -2110,13 +2110,14 @@ "color": "rgba(255,255,255,0.72)", "blur": 3 } - } + }, + "padding": "0" }, "title": "Time series chart", "dropShadow": false, "enableFullscreen": false, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -2134,7 +2135,7 @@ "titleColor": "rgba(0, 0, 0, 0.87)", "titleTooltip": "", "widgetStyle": {}, - "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-time-series-chart-panel {\n padding: 0;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", + "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", "pageSize": 1024, "units": "", "decimals": null, @@ -2580,7 +2581,8 @@ "color": "rgba(255,255,255,0.72)", "blur": 3 } - } + }, + "padding": "0" }, "title": "Time series chart", "dropShadow": false, @@ -2604,7 +2606,7 @@ "titleColor": "rgba(0, 0, 0, 0.87)", "titleTooltip": "", "widgetStyle": {}, - "widgetCss": ".tb-time-series-chart-panel {\n padding: 0;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", + "widgetCss": ".tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", "pageSize": 1024, "units": "%", "decimals": null, diff --git a/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json b/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json index b9a996b8a5..063cb0def2 100644 --- a/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json +++ b/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json @@ -758,13 +758,14 @@ "color": "rgba(255,255,255,0.72)", "blur": 3 } - } + }, + "padding": "0" }, "title": "Time series chart", "dropShadow": false, "enableFullscreen": false, "titleStyle": null, - "configMode": "advanced", + "configMode": "basic", "actions": {}, "showTitleIcon": false, "titleIcon": "thermostat", @@ -782,7 +783,7 @@ "titleColor": "rgba(0, 0, 0, 0.87)", "titleTooltip": "", "widgetStyle": {}, - "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-time-series-chart-panel {\n padding: 0;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", + "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", "pageSize": 1024, "units": "", "decimals": null, @@ -932,42 +933,47 @@ "color": "rgba(0, 0, 0, 0.87)", "padding": "0px", "settings": { + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": null, + "showTicks": false, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": false, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": false, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": 0 + } + }, "thresholds": [], "dataZoom": false, "stack": false, - "yAxis": { - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "ticksFormatter": "", - "showTicks": false, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": false, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": false, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "min": 0, - "max": null - }, "xAxis": { "show": true, "label": "", @@ -1060,53 +1066,6 @@ "tooltipDateInterval": false, "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", "tooltipBackgroundBlur": 4, - "background": { - "type": "color", - "color": "#fff", - "overlay": { - "enabled": false, - "color": "rgba(255,255,255,0.72)", - "blur": 3 - } - }, - "yAxes": { - "default": { - "units": null, - "decimals": 0, - "show": true, - "label": "", - "labelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "600", - "lineHeight": "1" - }, - "labelColor": "rgba(0, 0, 0, 0.54)", - "position": "left", - "showTickLabels": true, - "tickLabelFont": { - "family": "Roboto", - "size": 12, - "sizeUnit": "px", - "style": "normal", - "weight": "400", - "lineHeight": "1" - }, - "tickLabelColor": "rgba(0, 0, 0, 0.54)", - "ticksFormatter": null, - "showTicks": false, - "ticksColor": "rgba(0, 0, 0, 0.54)", - "showLine": false, - "lineColor": "rgba(0, 0, 0, 0.54)", - "showSplitLines": false, - "splitLinesColor": "rgba(0, 0, 0, 0.12)", - "id": "default", - "order": 0, - "min": 0 - } - }, "animation": { "animation": true, "animationThreshold": 2000, @@ -1116,7 +1075,17 @@ "animationDurationUpdate": 300, "animationEasingUpdate": "cubicOut", "animationDelayUpdate": 0 - } + }, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + }, + "padding": "0" }, "title": "Time series chart", "dropShadow": false, @@ -1140,7 +1109,7 @@ "titleColor": "rgba(0, 0, 0, 0.87)", "titleTooltip": "", "widgetStyle": {}, - "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-time-series-chart-panel {\n padding: 0;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", + "widgetCss": ".tb-widget-container > .tb-widget {\n border: none !important;\n border-radius: 0 !important;\n box-shadow: none !important;\n}\n\n.tb-time-series-chart-panel div.tb-widget-title {\n padding-top: 5px;\n padding-left: 5px;\n}", "pageSize": 1024, "units": "", "decimals": null, 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 decb97384e..f9fc2fa2ee 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -5213,6 +5213,7 @@ "card-buttons": "Card buttons", "show-card-buttons": "Show card buttons", "card-border-radius": "Card border radius", + "card-padding": "Card padding", "card-appearance": "Card appearance", "color": "Color", "tooltip": "Tooltip", diff --git a/ui-ngx/yarn.lock b/ui-ngx/yarn.lock index d78a9a52d6..4317883a2b 100644 --- a/ui-ngx/yarn.lock +++ b/ui-ngx/yarn.lock @@ -5367,13 +5367,13 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -echarts@^5.4.3: - version "5.4.3" - resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.4.3.tgz#f5522ef24419164903eedcfd2b506c6fc91fb20c" - integrity sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA== +echarts@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.5.0.tgz#c13945a7f3acdd67c134d8a9ac67e917830113ac" + integrity sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw== dependencies: tslib "2.3.0" - zrender "5.4.4" + zrender "5.5.0" editorconfig@^0.15.3: version "0.15.3" @@ -11101,9 +11101,9 @@ zone.js@~0.13.0: dependencies: tslib "^2.3.0" -zrender@5.4.4: - version "5.4.4" - resolved "https://registry.yarnpkg.com/zrender/-/zrender-5.4.4.tgz#8854f1d95ecc82cf8912f5a11f86657cb8c9e261" - integrity sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw== +zrender@5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/zrender/-/zrender-5.5.0.tgz#54d0d6c4eda81a96d9f60a9cd74dc48ea026bc1e" + integrity sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w== dependencies: tslib "2.3.0" From 018d3af3a741c92d6ebe26ee91ec125e62981981 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 12 Mar 2024 15:03:58 +0200 Subject: [PATCH 341/397] UI: API usage dashboard change line chart style --- ui-ngx/src/assets/dashboard/api_usage.json | 28 ++++++++++++---------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/ui-ngx/src/assets/dashboard/api_usage.json b/ui-ngx/src/assets/dashboard/api_usage.json index 8b285b2b0b..c0f3645156 100644 --- a/ui-ngx/src/assets/dashboard/api_usage.json +++ b/ui-ngx/src/assets/dashboard/api_usage.json @@ -7482,7 +7482,7 @@ "stepType": "start", "smooth": false, "lineType": "solid", - "lineWidth": 3, + "lineWidth": 2.5, "showPoints": false, "showPointLabel": false, "pointLabelPosition": "top", @@ -7496,7 +7496,7 @@ }, "pointLabelColor": "rgba(0, 0, 0, 0.76)", "pointShape": "circle", - "pointSize": 14, + "pointSize": 12, "fillAreaSettings": { "type": "none", "opacity": 0.4, @@ -7555,7 +7555,7 @@ "stepType": "start", "smooth": false, "lineType": "solid", - "lineWidth": 3, + "lineWidth": 2.5, "showPoints": false, "showPointLabel": false, "pointLabelPosition": "top", @@ -7569,7 +7569,7 @@ }, "pointLabelColor": "rgba(0, 0, 0, 0.76)", "pointShape": "circle", - "pointSize": 14, + "pointSize": 12, "fillAreaSettings": { "type": "none", "opacity": 0.4, @@ -7628,7 +7628,7 @@ "stepType": "start", "smooth": false, "lineType": "solid", - "lineWidth": 3, + "lineWidth": 2.5, "showPoints": false, "showPointLabel": false, "pointLabelPosition": "top", @@ -7642,7 +7642,7 @@ }, "pointLabelColor": "rgba(0, 0, 0, 0.76)", "pointShape": "circle", - "pointSize": 14, + "pointSize": 12, "fillAreaSettings": { "type": "none", "opacity": 0.4, @@ -7864,7 +7864,8 @@ "color": "rgba(255,255,255,0.72)", "blur": 3 } - } + }, + "padding": "12px" }, "title": "{i18n:api-usage.queue-stats}", "dropShadow": true, @@ -7944,7 +7945,7 @@ "stepType": "start", "smooth": false, "lineType": "solid", - "lineWidth": 3, + "lineWidth": 2.5, "showPoints": false, "showPointLabel": false, "pointLabelPosition": "top", @@ -7958,7 +7959,7 @@ }, "pointLabelColor": "rgba(0, 0, 0, 0.76)", "pointShape": "circle", - "pointSize": 14, + "pointSize": 12, "fillAreaSettings": { "type": "none", "opacity": 0.4, @@ -8017,7 +8018,7 @@ "stepType": "start", "smooth": false, "lineType": "solid", - "lineWidth": 1, + "lineWidth": 2.5, "showPoints": false, "showPointLabel": false, "pointLabelPosition": "top", @@ -8031,7 +8032,7 @@ }, "pointLabelColor": "rgba(0, 0, 0, 0.76)", "pointShape": "circle", - "pointSize": 14, + "pointSize": 12, "fillAreaSettings": { "type": "none", "opacity": 0.4, @@ -8253,7 +8254,8 @@ "color": "rgba(255,255,255,0.72)", "blur": 3 } - } + }, + "padding": "12px" }, "title": "{i18n:api-usage.processing-failures-and-timeouts}", "dropShadow": true, @@ -8716,7 +8718,7 @@ "dashboardLogoUrl": null, "hideToolbar": false, "showUpdateDashboardImage": false, - "dashboardCss": ".tb-time-series-chart-panel {\n padding: 13px;\n}\n\n.tb-time-series-chart-content {\n gap: 0; \n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n\n.card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n.card .unit {\n color: #666666;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} " + "dashboardCss": ".card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n\n.card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card > img {\n height: 0;\n}\n\n.card .content {\n flex: 1; \n padding: 12px 12px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-mdc-button-base {\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.card .mdc-button__label {\n pointer-events: none;\n}\n\n.action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n.card .unit {\n color: #666666;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-mdc-button-base {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-mdc-button-base {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-mdc-button-base {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} " } }, "name": "Api Usage" From 3d656192dde7c4db79f4dfa47576d6a317078c35 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 12 Mar 2024 17:18:42 +0200 Subject: [PATCH 342/397] UI: Update demo dashboards --- .../dashboards/rule_engine_statistics.json | 1086 ++++++++++++----- .../json/demo/dashboards/thermostats.json | 1057 ++++++++++++---- .../time-series-chart-widget.component.scss | 7 +- 3 files changed, 1618 insertions(+), 532 deletions(-) diff --git a/application/src/main/data/json/demo/dashboards/rule_engine_statistics.json b/application/src/main/data/json/demo/dashboards/rule_engine_statistics.json index c84faa359e..83a96c6fe6 100644 --- a/application/src/main/data/json/demo/dashboards/rule_engine_statistics.json +++ b/application/src/main/data/json/demo/dashboards/rule_engine_statistics.json @@ -5,104 +5,50 @@ "mobileOrder": null, "configuration": { "widgets": { - "81987f19-3eac-e4ce-b790-d96e9b54d9a0": { + "5eb79712-5c24-3060-7e4f-6af36b8f842d": { "type": "timeseries", - "sizeX": 12, - "sizeY": 7, + "sizeX": 24, + "sizeY": 5, "config": { "datasources": [ { "type": "entity", "dataKeys": [ { - "name": "successfulMsgs", + "name": "ruleEngineException", "type": "timeseries", - "label": "${entityName} Successful", - "color": "#4caf50", + "label": "Rule Chain", + "color": "#2196f3", "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } + "useCellStyleFunction": false, + "useCellContentFunction": true, + "cellContentFunction": "return JSON.parse(value).ruleChainName;" }, - "_hash": 0.15490750967648736 + "_hash": 0.9954481282345906 }, { - "name": "failedMsgs", + "name": "ruleEngineException", "type": "timeseries", - "label": "${entityName} Permanent Failures", - "color": "#ef5350", + "label": "Rule Node", + "color": "#4caf50", "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } + "useCellStyleFunction": false, + "useCellContentFunction": true, + "cellContentFunction": "return JSON.parse(value).ruleNodeName;" }, - "_hash": 0.4186621166514697 + "_hash": 0.18580357036589978 }, { - "name": "tmpFailed", + "name": "ruleEngineException", "type": "timeseries", - "label": "${entityName} Processing Failures", - "color": "#ffc107", + "label": "Latest Error", + "color": "#f44336", "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } + "useCellStyleFunction": false, + "useCellContentFunction": true, + "cellContentFunction": "return JSON.parse(value).message;" }, - "_hash": 0.49891007198715376 + "_hash": 0.7255162989552142 } ], "entityAliasId": "140f23dd-e3a0-ed98-6189-03c49d2d8018" @@ -111,312 +57,905 @@ "timewindow": { "realtime": { "interval": 1000, - "timewindowMs": 300000 + "timewindowMs": 86400000 }, "aggregation": { "type": "NONE", - "limit": 8640 - }, - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false + "limit": 200 + } }, "showTitle": true, - "backgroundColor": "#fff", + "backgroundColor": "rgb(255, 255, 255)", "color": "rgba(0, 0, 0, 0.87)", "padding": "8px", "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "showMin": true, - "showMax": true, - "showAvg": false, - "showTotal": true - } + "showTimestamp": true, + "displayPagination": true, + "defaultPageSize": 10 }, - "title": "Queue Stats", + "title": "Exceptions", "dropShadow": true, "enableFullscreen": true, "titleStyle": { "fontSize": "16px", "fontWeight": 400 }, - "mobileHeight": null, + "useDashboardTimewindow": false, + "showLegend": false, + "widgetStyle": {}, + "actions": {}, "showTitleIcon": false, "titleIcon": null, "iconColor": "rgba(0, 0, 0, 0.87)", "iconSize": "24px", "titleTooltip": "", - "widgetStyle": {}, - "useDashboardTimewindow": false, - "displayTimewindow": true, - "actions": {} + "displayTimewindow": true }, - "id": "81987f19-3eac-e4ce-b790-d96e9b54d9a0", - "typeFullFqn": "system.charts.basic_timeseries" + "id": "5eb79712-5c24-3060-7e4f-6af36b8f842d", + "typeFullFqn": "system.cards.timeseries_table" }, - "5eb79712-5c24-3060-7e4f-6af36b8f842d": { + "42face47-730d-f930-fef5-2a1ef6304b16": { + "typeFullFqn": "system.time_series_chart", "type": "timeseries", - "sizeX": 24, + "sizeX": 8, "sizeY": 5, "config": { "datasources": [ { "type": "entity", + "entityAliasId": "140f23dd-e3a0-ed98-6189-03c49d2d8018", "dataKeys": [ { - "name": "ruleEngineException", + "name": "successfulMsgs", "type": "timeseries", - "label": "Rule Chain", - "color": "#2196f3", + "label": "{i18n:api-usage.successful}", + "color": "#4caf50", "settings": { - "useCellStyleFunction": false, - "useCellContentFunction": true, - "cellContentFunction": "return JSON.parse(value).ruleChainName;" + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2.5, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 12, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } }, - "_hash": 0.9954481282345906 + "_hash": 0.15490750967648736, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null }, { - "name": "ruleEngineException", + "name": "failedMsgs", "type": "timeseries", - "label": "Rule Node", - "color": "#4caf50", + "label": "{i18n:api-usage.permanent-failures}", + "color": "#ef5350", "settings": { - "useCellStyleFunction": false, - "useCellContentFunction": true, - "cellContentFunction": "return JSON.parse(value).ruleNodeName;" + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2.5, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 12, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } }, - "_hash": 0.18580357036589978 + "_hash": 0.4186621166514697, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null }, { - "name": "ruleEngineException", + "name": "tmpFailed", "type": "timeseries", - "label": "Latest Error", - "color": "#f44336", + "label": "{i18n:api-usage.processing-failures}", + "color": "#ffc107", "settings": { - "useCellStyleFunction": false, - "useCellContentFunction": true, - "cellContentFunction": "return JSON.parse(value).message;" + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2.5, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 12, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } }, - "_hash": 0.7255162989552142 + "_hash": 0.49891007198715376, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null } ], - "entityAliasId": "140f23dd-e3a0-ed98-6189-03c49d2d8018" + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } } ], "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, "realtime": { - "interval": 1000, - "timewindowMs": 86400000 + "realtimeType": 0, + "timewindowMs": 300000, + "quickInterval": "CURRENT_DAY", + "interval": 1000 }, "aggregation": { "type": "NONE", - "limit": 200 + "limit": 8640 } }, "showTitle": true, - "backgroundColor": "rgb(255, 255, 255)", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", + "padding": "0px", "settings": { - "showTimestamp": true, - "displayPagination": true, - "defaultPageSize": 10 + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } + }, + "thresholds": [], + "dataZoom": true, + "stack": false, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } + }, + "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": true, + "showMax": true, + "showAvg": false, + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 300, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + }, + "padding": "12px" }, - "title": "Exceptions", + "title": "{i18n:api-usage.queue-stats}", "dropShadow": true, "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "useDashboardTimewindow": false, - "showLegend": false, - "widgetStyle": {}, + "titleStyle": null, + "configMode": "basic", "actions": {}, "showTitleIcon": false, - "titleIcon": null, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", "titleTooltip": "", - "displayTimewindow": true + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - "id": "5eb79712-5c24-3060-7e4f-6af36b8f842d", - "typeFullFqn": "system.cards.timeseries_table" + "row": 0, + "col": 0, + "id": "42face47-730d-f930-fef5-2a1ef6304b16" }, - "ad3f1417-87a8-750e-fc67-49a2de1466d4": { + "6a74ab56-cb36-e75e-c094-a51a896da94a": { + "typeFullFqn": "system.time_series_chart", "type": "timeseries", - "sizeX": 12, - "sizeY": 7, + "sizeX": 8, + "sizeY": 5, "config": { "datasources": [ { "type": "entity", + "entityAliasId": "140f23dd-e3a0-ed98-6189-03c49d2d8018", "dataKeys": [ { "name": "timeoutMsgs", "type": "timeseries", - "label": "${entityName} Permanent Timeouts", + "label": "{i18n:api-usage.permanent-timeouts}", "color": "#4caf50", "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2.5, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 12, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } } - ], - "comparisonSettings": { - "showValuesForComparison": true } }, - "_hash": 0.565222981550328 + "_hash": 0.565222981550328, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null }, { "name": "tmpTimeout", "type": "timeseries", - "label": "${entityName} Processing Timeouts", + "label": "{i18n:api-usage.processing-timeouts}", "color": "#9c27b0", "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": false, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": false, + "lineType": "solid", + "lineWidth": 2.5, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 12, + "fillAreaSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } } - ], - "comparisonSettings": { - "showValuesForComparison": true } }, - "_hash": 0.2679547062508352 + "_hash": 0.2679547062508352, + "aggregationType": null, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null } ], - "entityAliasId": "140f23dd-e3a0-ed98-6189-03c49d2d8018" + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + } } ], "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, "realtime": { - "interval": 1000, - "timewindowMs": 300000 + "realtimeType": 0, + "timewindowMs": 300000, + "quickInterval": "CURRENT_DAY", + "interval": 1000 }, "aggregation": { "type": "NONE", "limit": 8640 - }, - "hideInterval": false, - "hideAggregation": false, - "hideAggInterval": false + } }, "showTitle": true, - "backgroundColor": "#fff", + "backgroundColor": "#FFFFFF", "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", + "padding": "0px", "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 + "yAxes": { + "default": { + "units": null, + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": null, + "max": null + } }, + "thresholds": [], + "dataZoom": true, "stack": false, - "tooltipIndividual": false, - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupWidth": { + "relative": false, + "relativeWidth": 2, + "absoluteWidth": 1800000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } }, "showLegend": true, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", "legendConfig": { "direction": "column", "position": "bottom", + "sortDataKeys": false, "showMin": true, "showMax": true, "showAvg": false, - "showTotal": true - } + "showTotal": true, + "showLatest": false + }, + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "yyyy-MM-dd HH:mm:ss", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": true, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 300, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + }, + "padding": "12px" }, - "title": "Processing Failures and Timeouts", + "title": "{i18n:api-usage.processing-failures-and-timeouts}", "dropShadow": true, "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "mobileHeight": null, + "titleStyle": null, + "configMode": "basic", + "actions": {}, "showTitleIcon": false, - "titleIcon": null, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "widgetStyle": {}, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", "useDashboardTimewindow": false, "displayTimewindow": true, - "actions": {} + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" }, - "id": "ad3f1417-87a8-750e-fc67-49a2de1466d4", - "typeFullFqn": "system.charts.basic_timeseries" + "row": 0, + "col": 0, + "id": "6a74ab56-cb36-e75e-c094-a51a896da94a" } }, "states": { @@ -426,23 +965,21 @@ "layouts": { "main": { "widgets": { - "81987f19-3eac-e4ce-b790-d96e9b54d9a0": { - "sizeX": 12, - "sizeY": 7, - "mobileHeight": null, - "row": 0, - "col": 0 - }, "5eb79712-5c24-3060-7e4f-6af36b8f842d": { "sizeX": 24, "sizeY": 5, "row": 7, "col": 0 }, - "ad3f1417-87a8-750e-fc67-49a2de1466d4": { + "42face47-730d-f930-fef5-2a1ef6304b16": { + "sizeX": 12, + "sizeY": 7, + "row": 0, + "col": 0 + }, + "6a74ab56-cb36-e75e-c094-a51a896da94a": { "sizeX": 12, "sizeY": 7, - "mobileHeight": null, "row": 0, "col": 12 } @@ -511,6 +1048,5 @@ }, "filters": {} }, - "externalId": null, "name": "Rule Engine Statistics" } \ No newline at end of file diff --git a/application/src/main/data/json/demo/dashboards/thermostats.json b/application/src/main/data/json/demo/dashboards/thermostats.json index 967c1cb253..654a311386 100644 --- a/application/src/main/data/json/demo/dashboards/thermostats.json +++ b/application/src/main/data/json/demo/dashboards/thermostats.json @@ -325,240 +325,6 @@ "id": "7943196b-eedb-d422-f9c3-b32d379ad172", "typeFullFqn": "system.alarm_widgets.alarms_table" }, - "14a19183-f0b2-d6be-0f62-9863f0a51111": { - "type": "timeseries", - "sizeX": 18, - "sizeY": 6, - "config": { - "datasources": [ - { - "type": "entity", - "dataKeys": [ - { - "name": "temperature", - "type": "timeseries", - "label": "Temperature", - "color": "#ef5350", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": true, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.7852346160709658, - "units": "°C", - "decimals": 1 - } - ], - "entityAliasId": "12ae98c7-1ea2-52cf-64d5-763e9d993547" - } - ], - "timewindow": { - "realtime": { - "interval": 30000, - "timewindowMs": 3600000 - }, - "aggregation": { - "type": "AVG", - "limit": 25000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "smoothLines": true, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "showMin": true, - "showMax": true, - "showAvg": true, - "showTotal": false - } - }, - "title": "Temperature", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "mobileHeight": null, - "showTitleIcon": false, - "titleIcon": null, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "widgetStyle": {}, - "useDashboardTimewindow": false, - "displayTimewindow": true, - "actions": {} - }, - "id": "14a19183-f0b2-d6be-0f62-9863f0a51111", - "typeFullFqn": "system.charts.basic_timeseries" - }, - "07f49fd5-a73b-d74c-c220-362c20af81f4": { - "type": "timeseries", - "sizeX": 18, - "sizeY": 6, - "config": { - "datasources": [ - { - "type": "entity", - "dataKeys": [ - { - "name": "humidity", - "type": "timeseries", - "label": "Humidity", - "color": "#2196f3", - "settings": { - "excludeFromStacking": false, - "hideDataByDefault": false, - "disableDataHiding": false, - "removeFromLegend": false, - "showLines": true, - "fillLines": true, - "showPoints": false, - "showPointShape": "circle", - "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);", - "showPointsLineWidth": 5, - "showPointsRadius": 3, - "showSeparateAxis": false, - "axisPosition": "left", - "thresholds": [ - { - "thresholdValueSource": "predefinedValue" - } - ], - "comparisonSettings": { - "showValuesForComparison": true - } - }, - "_hash": 0.28640715926957183, - "units": "%", - "decimals": 0 - } - ], - "entityAliasId": "12ae98c7-1ea2-52cf-64d5-763e9d993547" - } - ], - "timewindow": { - "realtime": { - "interval": 30000, - "timewindowMs": 3600000 - }, - "aggregation": { - "type": "AVG", - "limit": 25000 - } - }, - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "8px", - "settings": { - "shadowSize": 4, - "fontColor": "#545454", - "fontSize": 10, - "xaxis": { - "showLabels": true, - "color": "#545454" - }, - "yaxis": { - "showLabels": true, - "color": "#545454" - }, - "grid": { - "color": "#545454", - "tickColor": "#DDDDDD", - "verticalLines": true, - "horizontalLines": true, - "outlineWidth": 1 - }, - "stack": false, - "tooltipIndividual": false, - "timeForComparison": "months", - "xaxisSecond": { - "axisPosition": "top", - "showLabels": true - }, - "smoothLines": true, - "showLegend": true, - "legendConfig": { - "direction": "column", - "position": "bottom", - "showMin": true, - "showMax": true, - "showAvg": true, - "showTotal": false - } - }, - "title": "Humidity", - "dropShadow": true, - "enableFullscreen": true, - "titleStyle": { - "fontSize": "16px", - "fontWeight": 400 - }, - "mobileHeight": null, - "showTitleIcon": false, - "titleIcon": null, - "iconColor": "rgba(0, 0, 0, 0.87)", - "iconSize": "24px", - "titleTooltip": "", - "widgetStyle": {}, - "useDashboardTimewindow": false, - "displayTimewindow": true, - "actions": {} - }, - "id": "07f49fd5-a73b-d74c-c220-362c20af81f4", - "typeFullFqn": "system.charts.basic_timeseries" - }, "c4631f94-2db3-523b-4d09-2a1a0a75d93f": { "type": "latest", "sizeX": 6, @@ -668,7 +434,9 @@ "fieldsAlignment": "column", "fieldsInRow": 2, "groupTitle": "${entityName}", - "widgetTitle": "Termostat settings" + "widgetTitle": "Termostat settings", + "columnGap": 10, + "rowGap": 5 }, "title": "New Update Multiple Attributes", "dropShadow": true, @@ -787,8 +555,8 @@ "markerImageSize": 48, "useColorFunction": false, "markerImages": [ - "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiNmNDQzMzZ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+", - "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiMyNzg2MjJ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+Cg==" + "tb-image:dGhlcm1vc3RhdHNfZGFzaGJvYXJkX3dpZGdldF90aGVybW9zdGF0X21hcHNfbWFya2VyX2ltYWdlXzAuc3Zn:IlRoZXJtb3N0YXRzIiBkYXNoYm9hcmQgd2lkZ2V0ICJUaGVybW9zdGF0IG1hcHMiIG1hcmtlciBpbWFnZSAw;data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiNmNDQzMzZ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+", + "tb-image:dGhlcm1vc3RhdHNfZGFzaGJvYXJkX3dpZGdldF90aGVybW9zdGF0X21hcHNfbWFya2VyX2ltYWdlXzEuc3Zn:IlRoZXJtb3N0YXRzIiBkYXNoYm9hcmQgd2lkZ2V0ICJUaGVybW9zdGF0IG1hcHMiIG1hcmtlciBpbWFnZSAx;data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiMyNzg2MjJ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+Cg==" ], "useMarkerImageFunction": true, "colorFunction": "\n", @@ -942,8 +710,8 @@ "markerImageSize": 34, "useColorFunction": false, "markerImages": [ - "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiNmNDQzMzZ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+", - "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiMyNzg2MjJ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+Cg==" + "tb-image:dGhlcm1vc3RhdHNfZGFzaGJvYXJkX3dpZGdldF90aGVybW9zdGF0X21hcHNfbWFya2VyX2ltYWdlXzAuc3Zn:IlRoZXJtb3N0YXRzIiBkYXNoYm9hcmQgd2lkZ2V0ICJUaGVybW9zdGF0IG1hcHMiIG1hcmtlciBpbWFnZSAw;data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiNmNDQzMzZ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+", + "tb-image:dGhlcm1vc3RhdHNfZGFzaGJvYXJkX3dpZGdldF90aGVybW9zdGF0X21hcHNfbWFya2VyX2ltYWdlXzEuc3Zn:IlRoZXJtb3N0YXRzIiBkYXNoYm9hcmQgd2lkZ2V0ICJUaGVybW9zdGF0IG1hcHMiIG1hcmtlciBpbWFnZSAx;data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiMyNzg2MjJ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+Cg==" ], "useMarkerImageFunction": true, "color": "#fe7569", @@ -1093,8 +861,8 @@ "markerImageSize": 34, "useColorFunction": false, "markerImages": [ - "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiNmNDQzMzZ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+", - "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiMyNzg2MjJ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+Cg==" + "tb-image:dGhlcm1vc3RhdHNfZGFzaGJvYXJkX3dpZGdldF90aGVybW9zdGF0X21hcHNfbWFya2VyX2ltYWdlXzAuc3Zn:IlRoZXJtb3N0YXRzIiBkYXNoYm9hcmQgd2lkZ2V0ICJUaGVybW9zdGF0IG1hcHMiIG1hcmtlciBpbWFnZSAw;data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiNmNDQzMzZ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+", + "tb-image:dGhlcm1vc3RhdHNfZGFzaGJvYXJkX3dpZGdldF90aGVybW9zdGF0X21hcHNfbWFya2VyX2ltYWdlXzEuc3Zn:IlRoZXJtb3N0YXRzIiBkYXNoYm9hcmQgd2lkZ2V0ICJUaGVybW9zdGF0IG1hcHMiIG1hcmtlciBpbWFnZSAx;data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiMyNzg2MjJ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+Cg==" ], "useMarkerImageFunction": true, "color": "#fe7569", @@ -1151,6 +919,786 @@ }, "id": "0a430429-9078-9ae6-2b67-e4a15a2bf8bf", "typeFullFqn": "system.input_widgets.markers_placement_openstreetmap" + }, + "eda8a397-0959-690c-405c-11e2c9b2bc7e": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": "", + "entityAliasId": "12ae98c7-1ea2-52cf-64d5-763e9d993547", + "dataKeys": [ + { + "name": "temperature", + "type": "timeseries", + "label": "Temperature", + "color": "#EF5350", + "settings": { + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": true, + "lineType": "solid", + "lineWidth": 2.5, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "gradient", + "opacity": 0.4, + "gradient": { + "start": 60, + "end": 10 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.5973804076994531, + "units": "°C", + "decimals": 1, + "aggregationType": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + }, + "latestDataKeys": [ + { + "name": "temperatureAlarmThreshold", + "type": "attribute", + "label": "temperatureAlarmThreshold", + "color": "#4caf50", + "settings": { + "__thresholdKey": true + }, + "_hash": 0.7120450032526351 + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "timewindowMs": 3600000, + "quickInterval": "CURRENT_DAY", + "interval": 30000 + }, + "aggregation": { + "type": "AVG", + "limit": 25000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "showLegend": true, + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": true, + "showMax": true, + "showAvg": true, + "showTotal": false, + "showLatest": false + }, + "thresholds": [ + { + "type": "latestKey", + "yAxisId": "default", + "units": "°C", + "decimals": 0, + "lineColor": "rgb(233, 30, 99)", + "lineType": "solid", + "lineWidth": 2, + "startSymbol": "none", + "startSymbolSize": 5, + "endSymbol": "arrow", + "endSymbolSize": 8, + "showLabel": true, + "labelPosition": "end", + "labelFont": { + "size": 14, + "family": "Roboto", + "weight": "500", + "style": "normal" + }, + "labelColor": "rgb(233, 30, 99)", + "latestKey": "temperatureAlarmThreshold", + "latestKeyType": "attribute" + } + ], + "dataZoom": true, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "MMM dd yyyy HH:mm", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": false, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + }, + "yAxes": { + "default": { + "units": "°C", + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": null, + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": 0 + } + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } + }, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 500, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, + "padding": "12px" + }, + "title": "Temperature", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "eda8a397-0959-690c-405c-11e2c9b2bc7e" + }, + "ac90f089-197f-b767-82c3-2668844265a2": { + "typeFullFqn": "system.time_series_chart", + "type": "timeseries", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": "", + "entityAliasId": "12ae98c7-1ea2-52cf-64d5-763e9d993547", + "dataKeys": [ + { + "name": "humidity", + "type": "timeseries", + "label": "Humidity", + "color": "#2196F3", + "settings": { + "yAxisId": "default", + "showInLegend": true, + "dataHiddenByDefault": false, + "type": "line", + "lineSettings": { + "showLine": true, + "step": false, + "stepType": "start", + "smooth": true, + "lineType": "solid", + "lineWidth": 2.5, + "showPoints": false, + "showPointLabel": false, + "pointLabelPosition": "top", + "pointLabelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "pointLabelColor": "rgba(0, 0, 0, 0.76)", + "pointShape": "circle", + "pointSize": 14, + "fillAreaSettings": { + "type": "gradient", + "opacity": 0.4, + "gradient": { + "start": 60, + "end": 10 + } + } + }, + "barSettings": { + "showBorder": false, + "borderWidth": 2, + "borderRadius": 0, + "showLabel": false, + "labelPosition": "top", + "labelFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.76)", + "backgroundSettings": { + "type": "none", + "opacity": 0.4, + "gradient": { + "start": 100, + "end": 0 + } + } + } + }, + "_hash": 0.4481337125330429, + "units": "%", + "decimals": 0, + "aggregationType": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ], + "alarmFilterConfig": { + "statusList": [ + "ACTIVE" + ] + }, + "latestDataKeys": [ + { + "name": "humidityAlarmThreshold", + "type": "attribute", + "label": "humidityAlarmThreshold", + "color": "#4caf50", + "settings": { + "__thresholdKey": true + }, + "_hash": 0.134733085341747 + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideLastInterval": false, + "hideQuickInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "hideTimezone": false, + "selectedTab": 0, + "realtime": { + "realtimeType": 0, + "timewindowMs": 3600000, + "quickInterval": "CURRENT_DAY", + "interval": 30000 + }, + "aggregation": { + "type": "AVG", + "limit": 25000 + }, + "timezone": null + }, + "showTitle": true, + "backgroundColor": "rgba(0, 0, 0, 0)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "0px", + "settings": { + "showLegend": true, + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": true, + "showMax": true, + "showAvg": true, + "showTotal": false, + "showLatest": false + }, + "thresholds": [ + { + "type": "latestKey", + "yAxisId": "default", + "units": "%", + "decimals": 0, + "lineColor": "rgb(4, 138, 211)", + "lineType": "solid", + "lineWidth": 2, + "startSymbol": "none", + "startSymbolSize": 5, + "endSymbol": "arrow", + "endSymbolSize": 8, + "showLabel": true, + "labelPosition": "end", + "labelFont": { + "size": 14, + "family": "Roboto", + "weight": "500", + "style": "normal" + }, + "labelColor": "rgb(4, 138, 211)", + "latestKey": "humidityAlarmThreshold", + "latestKeyType": "attribute" + } + ], + "dataZoom": true, + "stack": false, + "yAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "xAxis": { + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "bottom", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 10, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)" + }, + "legendLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "legendLabelColor": "rgba(0, 0, 0, 0.76)", + "showTooltip": true, + "tooltipTrigger": "axis", + "tooltipValueFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "500", + "lineHeight": "16px" + }, + "tooltipValueColor": "rgba(0, 0, 0, 0.76)", + "tooltipShowDate": true, + "tooltipDateFormat": { + "format": "MMM dd yyyy HH:mm", + "lastUpdateAgo": false, + "custom": false + }, + "tooltipDateFont": { + "family": "Roboto", + "size": 11, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "16px" + }, + "tooltipDateColor": "rgba(0, 0, 0, 0.76)", + "tooltipDateInterval": false, + "tooltipBackgroundColor": "rgba(255, 255, 255, 0.76)", + "tooltipBackgroundBlur": 4, + "background": { + "type": "color", + "color": "#fff", + "overlay": { + "enabled": false, + "color": "rgba(255,255,255,0.72)", + "blur": 3 + } + }, + "yAxes": { + "default": { + "units": "°C", + "decimals": 0, + "show": true, + "label": "", + "labelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "600", + "lineHeight": "1" + }, + "labelColor": "rgba(0, 0, 0, 0.54)", + "position": "left", + "showTickLabels": true, + "tickLabelFont": { + "family": "Roboto", + "size": 12, + "sizeUnit": "px", + "style": "normal", + "weight": "400", + "lineHeight": "1" + }, + "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormatter": null, + "showTicks": true, + "ticksColor": "rgba(0, 0, 0, 0.54)", + "showLine": true, + "lineColor": "rgba(0, 0, 0, 0.54)", + "showSplitLines": true, + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "id": "default", + "order": 0, + "min": 0 + } + }, + "noAggregationBarWidthSettings": { + "strategy": "group", + "groupWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + }, + "barWidth": { + "relative": true, + "relativeWidth": 2, + "absoluteWidth": 1000 + } + }, + "animation": { + "animation": true, + "animationThreshold": 2000, + "animationDuration": 500, + "animationEasing": "cubicOut", + "animationDelay": 0, + "animationDurationUpdate": 300, + "animationEasingUpdate": "cubicOut", + "animationDelayUpdate": 0 + }, + "padding": "12px" + }, + "title": "Humidity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": null, + "configMode": "basic", + "actions": {}, + "showTitleIcon": false, + "titleIcon": "thermostat", + "iconColor": "#1F6BDD", + "useDashboardTimewindow": false, + "displayTimewindow": true, + "titleFont": { + "size": 16, + "sizeUnit": "px", + "family": "Roboto", + "weight": "500", + "style": "normal", + "lineHeight": "24px" + }, + "titleColor": "rgba(0, 0, 0, 0.87)", + "titleTooltip": "", + "widgetStyle": {}, + "widgetCss": "", + "pageSize": 1024, + "units": "", + "decimals": null, + "noDataDisplayMessage": "", + "timewindowStyle": { + "showIcon": false, + "iconSize": "24px", + "icon": null, + "iconPosition": "left", + "font": { + "size": 12, + "sizeUnit": "px", + "family": "Roboto", + "weight": "400", + "style": "normal", + "lineHeight": "16px" + }, + "color": "rgba(0, 0, 0, 0.38)", + "displayTypePrefix": true + }, + "margin": "0px", + "borderRadius": "0px", + "iconSize": "0px" + }, + "row": 0, + "col": 0, + "id": "ac90f089-197f-b767-82c3-2668844265a2" } }, "states": { @@ -1226,20 +1774,6 @@ "layouts": { "main": { "widgets": { - "14a19183-f0b2-d6be-0f62-9863f0a51111": { - "sizeX": 18, - "sizeY": 6, - "mobileHeight": null, - "row": 0, - "col": 6 - }, - "07f49fd5-a73b-d74c-c220-362c20af81f4": { - "sizeX": 18, - "sizeY": 6, - "mobileHeight": null, - "row": 6, - "col": 6 - }, "c4631f94-2db3-523b-4d09-2a1a0a75d93f": { "sizeX": 6, "sizeY": 6, @@ -1251,6 +1785,18 @@ "sizeY": 6, "row": 6, "col": 0 + }, + "eda8a397-0959-690c-405c-11e2c9b2bc7e": { + "sizeX": 18, + "sizeY": 6, + "row": 0, + "col": 6 + }, + "ac90f089-197f-b767-82c3-2668844265a2": { + "sizeX": 18, + "sizeY": 6, + "row": 6, + "col": 6 } }, "gridSettings": { @@ -1327,6 +1873,5 @@ }, "filters": {} }, - "externalId": null, "name": "Thermostats" } \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss index 66428d9d91..ee0400d96f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart-widget.component.scss @@ -102,10 +102,15 @@ $maxLegendHeight: 35%; &.vertical { width: 100%; table-layout: auto; + tbody { + th { + width: 95%; + } + } } th, td { &:not(:last-child) { - padding-right: 8px; + padding-right: 16px; } } thead tr, tbody tr:not(:last-child) { From 33525f16eeee3ed7f3ac2d5fea1972e6b606e8aa Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 12 Mar 2024 17:31:02 +0200 Subject: [PATCH 343/397] UI: echarts patch updated. --- ui-ngx/patches/echarts+5.5.0.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ui-ngx/patches/echarts+5.5.0.patch b/ui-ngx/patches/echarts+5.5.0.patch index b25599afd8..39551ac137 100644 --- a/ui-ngx/patches/echarts+5.5.0.patch +++ b/ui-ngx/patches/echarts+5.5.0.patch @@ -194,3 +194,16 @@ index cf8d6bc..9b30ec1 100644 } dataZoomModel && (snapshot[dataZoomModel.id] = { dataZoomId: dataZoomModel.id, +diff --git a/node_modules/echarts/lib/component/tooltip/TooltipView.js b/node_modules/echarts/lib/component/tooltip/TooltipView.js +index b8a9b95..8e4cb2f 100644 +--- a/node_modules/echarts/lib/component/tooltip/TooltipView.js ++++ b/node_modules/echarts/lib/component/tooltip/TooltipView.js +@@ -360,7 +360,7 @@ var TooltipView = /** @class */function (_super) { + each(itemCoordSys.dataByAxis, function (axisItem) { + var axisModel = ecModel.getComponent(axisItem.axisDim + 'Axis', axisItem.axisIndex); + var axisValue = axisItem.value; +- if (!axisModel || axisValue == null) { ++ if (!axisModel || !axisModel.axis || axisValue == null) { + return; + } + var axisValueLabel = axisPointerViewHelper.getValueLabel(axisValue, axisModel.axis, ecModel, axisItem.seriesDataIndices, axisItem.valueLabelOpt); From b2460eb6429963bd37b0a6006d6a754f8ed0f4c6 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 12 Mar 2024 19:40:12 +0100 Subject: [PATCH 344/397] Parallel and multiarch build: yarn install --non-interactive --network-concurrency 4 --network-timeout 100000 --mutex network --- msa/js-executor/docker/Dockerfile | 2 +- msa/js-executor/pom.xml | 2 +- msa/web-ui/docker/Dockerfile | 2 +- msa/web-ui/pom.xml | 2 +- ui-ngx/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/msa/js-executor/docker/Dockerfile b/msa/js-executor/docker/Dockerfile index a7bebc8aaf..117bde8712 100644 --- a/msa/js-executor/docker/Dockerfile +++ b/msa/js-executor/docker/Dockerfile @@ -35,7 +35,7 @@ COPY src/server.js ./ RUN chmod a+x /tmp/*.sh \ && mv /tmp/start-js-executor.sh /usr/bin \ && chown -R node:node ${pkg.installFolder} \ - && yarn install --production && yarn cache clean --all + && yarn install --production --non-interactive --network-concurrency 4 --network-timeout 100000 --mutex network && yarn cache clean --all USER node diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index 5eb3a34c49..5880ff513a 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -81,7 +81,7 @@ yarn - install + install --non-interactive --network-concurrency 4 --network-timeout 100000 --mutex network diff --git a/msa/web-ui/docker/Dockerfile b/msa/web-ui/docker/Dockerfile index 8bac82683b..3081d90107 100644 --- a/msa/web-ui/docker/Dockerfile +++ b/msa/web-ui/docker/Dockerfile @@ -34,7 +34,7 @@ COPY src/server.js ./ RUN chmod a+x /tmp/*.sh \ && mv /tmp/start-web-ui.sh /usr/bin \ && chown -R node:node ${pkg.installFolder} \ - && yarn install --production && yarn cache clean --all + && yarn install --production --non-interactive --network-concurrency 4 --network-timeout 100000 --mutex network && yarn cache clean --all USER node diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index f60c73b8d1..c070210f02 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -90,7 +90,7 @@ yarn - install + install --non-interactive --network-concurrency 4 --network-timeout 100000 --mutex network diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index a13d364052..944ca04846 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -66,7 +66,7 @@ yarn - install + install --non-interactive --network-concurrency 4 --network-timeout 100000 --mutex network From 9d632430bafb81edbc6dc23f8f3a5ab38d275344 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 12 Mar 2024 19:40:42 +0100 Subject: [PATCH 345/397] license header format --- .../lwm2m/server/store/util/LwM2MClientSerDesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java index 8cdd7b5147..3e4d807da0 100644 --- a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 446ff16897f66716332d7950c826b6308710433b Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Wed, 13 Mar 2024 11:20:10 +0200 Subject: [PATCH 346/397] License format --- .../lwm2m/server/store/util/LwM2MClientSerDesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java index 8cdd7b5147..3e4d807da0 100644 --- a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 6d13086a53f8938f9275f7159321046c9a71914e Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 13 Mar 2024 18:17:24 +0200 Subject: [PATCH 347/397] added additional check for case when refresh token was dropped --- .../server/service/mail/RefreshTokenExpCheckService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/mail/RefreshTokenExpCheckService.java b/application/src/main/java/org/thingsboard/server/service/mail/RefreshTokenExpCheckService.java index 32fe4eb15c..8e6dfce8f0 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/RefreshTokenExpCheckService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/RefreshTokenExpCheckService.java @@ -54,7 +54,8 @@ public class RefreshTokenExpCheckService { AdminSettings settings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail"); if (settings != null && settings.getJsonValue().has("enableOauth2") && settings.getJsonValue().get("enableOauth2").asBoolean()) { JsonNode jsonValue = settings.getJsonValue(); - if (OFFICE_365.name().equals(jsonValue.get("providerId").asText()) && jsonValue.has("refreshTokenExpires")) { + if (OFFICE_365.name().equals(jsonValue.get("providerId").asText()) && jsonValue.has("refreshToken") + && jsonValue.has("refreshTokenExpires")) { long expiresIn = jsonValue.get("refreshTokenExpires").longValue(); if ((expiresIn - System.currentTimeMillis()) < 604800000L) { //less than 7 days log.info("Trying to refresh refresh token."); From 60f40ad6b8f63c082a9b47bb12df77cddc9b0053 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 13 Mar 2024 18:29:35 +0200 Subject: [PATCH 348/397] UI: Improve time series charts X axis and tooltip date formatting: introduce auto date format. --- .../json/demo/dashboards/thermostats.json | 44 +++-- .../json/system/widget_types/bar_chart.json | 2 +- .../widget_types/bar_chart_with_labels.json | 2 +- .../json/system/widget_types/line_chart.json | 2 +- .../json/system/widget_types/point_chart.json | 2 +- .../json/system/widget_types/range_chart.json | 5 +- .../widget_types/time_series_chart.json | 2 +- ...rt-with-labels-basic-config.component.html | 3 +- .../range-chart-basic-config.component.html | 3 +- ...e-series-chart-basic-config.component.html | 11 +- .../aggregated-value-card-widget.component.ts | 3 +- .../value-chart-card-widget.component.ts | 3 +- .../bar-chart-with-labels-widget.component.ts | 9 +- .../widget/lib/chart/echarts-widget.models.ts | 12 +- .../lib/chart/range-chart-widget.component.ts | 8 +- .../lib/chart/time-series-chart.models.ts | 108 ++++++++++-- .../widget/lib/chart/time-series-chart.ts | 30 +--- ...with-labels-widget-settings.component.html | 3 +- ...range-chart-widget-settings.component.html | 3 +- ...eries-chart-widget-settings.component.html | 3 +- ...-date-format-settings-panel.component.html | 49 ++++++ ...-date-format-settings-panel.component.scss | 73 ++++++++ ...to-date-format-settings-panel.component.ts | 92 ++++++++++ .../auto-date-format-settings.component.html | 25 +++ .../auto-date-format-settings.component.ts | 99 +++++++++++ ...-series-chart-axis-settings.component.html | 22 +++ ...me-series-chart-axis-settings.component.ts | 18 +- .../common/date-format-select.component.html | 5 + .../common/date-format-select.component.ts | 49 +++++- .../common/widget-settings-common.module.ts | 10 ++ .../shared/models/widget-settings.models.ts | 157 +++++++++++++++++- .../assets/dashboard/sys_admin_home_page.json | 14 +- .../dashboard/tenant_admin_home_page.json | 14 +- .../assets/locale/locale.constant-en_US.json | 15 +- 34 files changed, 797 insertions(+), 103 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.ts diff --git a/application/src/main/data/json/demo/dashboards/thermostats.json b/application/src/main/data/json/demo/dashboards/thermostats.json index 654a311386..223722fee1 100644 --- a/application/src/main/data/json/demo/dashboards/thermostats.json +++ b/application/src/main/data/json/demo/dashboards/thermostats.json @@ -1147,7 +1147,8 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormat": {} }, "legendLabelFont": { "family": "Roboto", @@ -1173,7 +1174,9 @@ "tooltipDateFormat": { "format": "MMM dd yyyy HH:mm", "lastUpdateAgo": false, - "custom": false + "custom": false, + "auto": true, + "autoDateFormatSettings": {} }, "tooltipDateFont": { "family": "Roboto", @@ -1537,7 +1540,8 @@ "showLine": true, "lineColor": "rgba(0, 0, 0, 0.54)", "showSplitLines": true, - "splitLinesColor": "rgba(0, 0, 0, 0.12)" + "splitLinesColor": "rgba(0, 0, 0, 0.12)", + "ticksFormat": {} }, "legendLabelFont": { "family": "Roboto", @@ -1561,9 +1565,11 @@ "tooltipValueColor": "rgba(0, 0, 0, 0.76)", "tooltipShowDate": true, "tooltipDateFormat": { - "format": "MMM dd yyyy HH:mm", + "format": null, "lastUpdateAgo": false, - "custom": false + "custom": false, + "auto": true, + "autoDateFormatSettings": {} }, "tooltipDateFont": { "family": "Roboto", @@ -1712,19 +1718,25 @@ "sizeX": 11, "sizeY": 11, "row": 0, - "col": 0 + "col": 0, + "mobileOrder": 1, + "mobileHeight": 5 }, "7943196b-eedb-d422-f9c3-b32d379ad172": { "sizeX": 13, "sizeY": 5, "row": 0, - "col": 11 + "col": 11, + "mobileOrder": 2, + "mobileHeight": 5 }, "3da9a9a1-0b9a-2e1f-0dcb-0ff34a695abb": { "sizeX": 13, "sizeY": 6, "row": 5, - "col": 11 + "col": 11, + "mobileOrder": 3, + "mobileHeight": 5 } }, "gridSettings": { @@ -1778,25 +1790,33 @@ "sizeX": 6, "sizeY": 6, "row": 0, - "col": 0 + "col": 0, + "mobileOrder": 3, + "mobileHeight": 5 }, "0a430429-9078-9ae6-2b67-e4a15a2bf8bf": { "sizeX": 6, "sizeY": 6, "row": 6, - "col": 0 + "col": 0, + "mobileOrder": 4, + "mobileHeight": 6 }, "eda8a397-0959-690c-405c-11e2c9b2bc7e": { "sizeX": 18, "sizeY": 6, "row": 0, - "col": 6 + "col": 6, + "mobileOrder": 1, + "mobileHeight": 6 }, "ac90f089-197f-b767-82c3-2668844265a2": { "sizeX": 18, "sizeY": 6, "row": 6, - "col": 6 + "col": 6, + "mobileOrder": 2, + "mobileHeight": 6 } }, "gridSettings": { diff --git a/application/src/main/data/json/system/widget_types/bar_chart.json b/application/src/main/data/json/system/widget_types/bar_chart.json index c857922eea..b3791f53a1 100644 --- a/application/src/main/data/json/system/widget_types/bar_chart.json +++ b/application/src/main/data/json/system/widget_types/bar_chart.json @@ -20,7 +20,7 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-time-series-chart-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"dd MMM yyyy HH:mm:ss\",\"lastUpdateAgo\":false,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Bar chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":1000,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Bar chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, "tags": [ "chart", diff --git a/application/src/main/data/json/system/widget_types/bar_chart_with_labels.json b/application/src/main/data/json/system/widget_types/bar_chart_with_labels.json index 75814a547a..356e91f90e 100644 --- a/application/src/main/data/json/system/widget_types/bar_chart_with_labels.json +++ b/application/src/main/data/json/system/widget_types/bar_chart_with_labels.json @@ -20,7 +20,7 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-bar-chart-with-labels-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity\",\"color\":\"rgb(125, 142, 255)\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 50) {\\n\\tvalue = 50;\\n} else if (value > 80) {\\n\\tvalue = 80;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Soil moisture\",\"color\":\"rgb(249, 111, 255)\",\"settings\":{},\"_hash\":0.9111685461089025,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 30) {\\n\\tvalue = 30;\\n} else if (value > 90) {\\n\\tvalue = 90;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Leaf wetness\",\"color\":\"rgb(255, 163, 137)\",\"settings\":{},\"_hash\":0.8487533373085416,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 40) {\\n\\tvalue = 40;\\n} else if (value > 70) {\\n\\tvalue = 70;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cloud cover\",\"color\":\"#FFED53\",\"settings\":{},\"_hash\":0.7690144858984289,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 20) {\\n\\tvalue = 20;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]}}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":1,\"history\":{\"historyType\":2,\"timewindowMs\":60000,\"interval\":\"MONTH\",\"fixedTimewindow\":{\"startTimeMs\":1704293713163,\"endTimeMs\":1704380113163},\"quickInterval\":\"CURRENT_HALF_YEAR\"},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showBarLabel\":true,\"barLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"12px\"},\"barLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showBarValue\":true,\"barValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"700\",\"lineHeight\":\"12px\"},\"barValueColor\":\"rgba(0, 0, 0, 0.76)\",\"showLegend\":true,\"legendPosition\":\"top\",\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"MMMM y\",\"lastUpdateAgo\":false,\"custom\":true},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Bar chart with labels\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"public\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"%\",\"decimals\":0,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"24px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity\",\"color\":\"rgb(125, 142, 255)\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 50) {\\n\\tvalue = 50;\\n} else if (value > 80) {\\n\\tvalue = 80;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Soil moisture\",\"color\":\"rgb(249, 111, 255)\",\"settings\":{},\"_hash\":0.9111685461089025,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 30) {\\n\\tvalue = 30;\\n} else if (value > 90) {\\n\\tvalue = 90;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Leaf wetness\",\"color\":\"rgb(255, 163, 137)\",\"settings\":{},\"_hash\":0.8487533373085416,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 40) {\\n\\tvalue = 40;\\n} else if (value > 70) {\\n\\tvalue = 70;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cloud cover\",\"color\":\"#FFED53\",\"settings\":{},\"_hash\":0.7690144858984289,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 20) {\\n\\tvalue = 20;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]}}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":1,\"history\":{\"historyType\":2,\"timewindowMs\":60000,\"interval\":\"MONTH\",\"fixedTimewindow\":{\"startTimeMs\":1704293713163,\"endTimeMs\":1704380113163},\"quickInterval\":\"CURRENT_HALF_YEAR\"},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showBarLabel\":true,\"barLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"12px\"},\"barLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showBarValue\":true,\"barValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"700\",\"lineHeight\":\"12px\"},\"barValueColor\":\"rgba(0, 0, 0, 0.76)\",\"showLegend\":true,\"legendPosition\":\"top\",\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"tooltipDateInterval\":true},\"title\":\"Bar chart with labels\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"public\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"%\",\"decimals\":0,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"24px\"}" }, "tags": [ "bar chart", diff --git a/application/src/main/data/json/system/widget_types/line_chart.json b/application/src/main/data/json/system/widget_types/line_chart.json index 5fff201c28..273281e17a 100644 --- a/application/src/main/data/json/system/widget_types/line_chart.json +++ b/application/src/main/data/json/system/widget_types/line_chart.json @@ -20,7 +20,7 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-time-series-chart-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"opacity\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.3409583261715494,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"decimals\":null,\"aggregationType\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"dd MMM yyyy HH:mm:ss\",\"lastUpdateAgo\":false,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Line chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"opacity\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.3409583261715494,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"decimals\":null,\"aggregationType\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":1000,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Line chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, "tags": [ "chart", diff --git a/application/src/main/data/json/system/widget_types/point_chart.json b/application/src/main/data/json/system/widget_types/point_chart.json index f16d6823ee..d692570136 100644 --- a/application/src/main/data/json/system/widget_types/point_chart.json +++ b/application/src/main/data/json/system/widget_types/point_chart.json @@ -20,7 +20,7 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-time-series-chart-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"dd MMM yyyy HH:mm:ss\",\"lastUpdateAgo\":false,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Point chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":1000,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Point chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, "tags": [ "chart", diff --git a/application/src/main/data/json/system/widget_types/range_chart.json b/application/src/main/data/json/system/widget_types/range_chart.json index 981e3582c5..72cbeeacbb 100644 --- a/application/src/main/data/json/system/widget_types/range_chart.json +++ b/application/src/main/data/json/system/widget_types/range_chart.json @@ -2,7 +2,7 @@ "fqn": "range_chart", "name": "Range chart", "deprecated": false, - "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAMAAAB+IdObAAAC/VBMVEX////////8/PwAAAD///////+bsfP+wEzu7u73lkzz8/P1eWTT09PN1emRpeOcsvSxsbGQpeLc3NyXl5epqanjXHPLy8tti+OgoKD/wU26urr29vbts0fnkUf39/fIrYP4l02oqKjJroPl5eWUrPPDw8PCwsLJroSQqfKLpfKDn/HU1NSnu/X/tzD/pwNyku//vD//sB3m5ub2jj98mfB2lfD2hTD/rRPu8v3/3qD1fCD3+f7K1vnnjEf1eh30awSWrvOBnfFkhOLld1n1dRX0cxH/9N/1cVvld1jmjEf2izn/qQry9f2Yr/P/+u/+9u+RpuP82r//yGDdM1D3kEPzWD32gSixwfBWeN//2JDzY0v+vkf/siT+5+RBaNr7x6DbYWXxTC96mPD+7N+VqN35tID2emX3oWD3k0fm6/zc5PvV3vq2xveWrfL+8/Hd3d09ZNr/6b/6vZCPj4/2h3TfQl3bKkjaIUD/ujnxQCL0bwrC0PiWqN5Kbt3/79D6zMqGhob/0n/iUWn0aVH+vUPZGjr/tSuwwvZpiOLR0dH+2I97e3v1dWDkcV3fPVnxSCr/qw+Jo/F/m/GLoum3xOj64uZef+H41NoyW9hdfNbJycnxqLT7x5/4no/nb4P/zXDiVm3hS2TlcV3zXEPyUzj+uTTwRCbkbRB+mOaareN5k+FyjuBHbNw4YNn7xr3/47D70LD5t6zumqjngJH/2I+Ojo7lYnf4oWC+mF7utEj2iDTmfSrxRyrunw/kZwLL1vWWrfS/zPORqfP98fKjt/GGofHv7+/+7erK0umHnuKDm+Lf39/t5d7829bm2dT949Dzt8HqwLFse6r4raDsjJz3lIPopHzGpnT4q3DZVmXSNkvnj0LnjD7mgjbjWzHiSzHwRyrunQXv8/3+9POquOWot+Tu4s3u3b3rzrfUxrHu166boa6coK76uKzTvJvoppv6vpDuyYfdboDmkXH1fGffR2H3oV/kbVnnjkHtrTbOIDTiUiLhUCD/rhTuoROM0RHwAAAABXRSTlMg77MAvxFwlo8AAA5CSURBVHja1JtJaBNRGMfj8scXk8MwSYZxoiFhaC9FEQoRA7YHE6K9iMZ4KIoWcTkpqK3oRVH05HISwX1Db66guF48eHHFBfcFQUUQ933BL6PxZZyZRE2+of4aMhPyWvKb73vzf3nQQL9A/z743+lLGoE+Qlea0JLShVA0mFHFwP9Hn0CgL7QwdERgKnGlmY7QBYgNGwY2lleHBjLSNwAIpdlAFPRIQERBsIjcvDGQEUEimqLq0FFysUR4WLKiG5yQiKGiJGIqIJYCKQEGDhV6wAmJCD3VBDWqCxCmrjeBg+7tK06DkQD8Yd3C2ML1YMM/kY2FWM9GsOGfyLLuWOEg2PBPZMW22JotYMM3kYs9sdjbw2DDN5Eta2KxbQWw4ZtIYRmJrAAbfomsXxgjFq4DF36JXCmQB2eQ+CWybHuMKPAFiU8i61bESqy5Ai58EtnYY4l08wWJTyKHuy2R7d3gwieRnmWkwRok/ogsoc6y4FzI84tYsU4wBwm/iBXrP+i5CC74RcqxTnAu5C0RMypgppQ4lCaIlN6CxnKwUBZZcwhsWN/ZE4CeUA3TiCIiEImjoVCs/6T7MNggkXAk1YIo4lGoCaEDiQQIRRGN4fynaWVu3BRskIjRBJ0sbPtaDRR5fm/1jtWrV+/YsXrH+3uCDRJpDpNI5Me+VlwnMYFG8qYz9IvdZ8AFicQjioKmlC4A0JFeNJSuvBRZuxdcBEAIlGcGkUBDWdIVkuy6DCb4c+TqzpmhED0sipvBBL9IMU8WZToXgAd+kSknQhUs7wQP/CKXd1WK5E88BAv8IvnllSKruO6/7CJzFq0KVbJ2ClhgF9nbFbLRdQ4ssIss6LSLFJ+BBXaRYinWZ9LPT3YyBQmviIx19iCpS2QOanK1GCJ4g6R+kQVLUIvO5SE7+SLqgkWkmEcNptwP/c4i1AeDyIGu3VNqDSn+DyL5zp3VZ66M9Zm9WeTcfVpwVJvvtliXInNQBwwiFHU1UkHGOvcaRYqYKoSiAc0mEs2KwB8wZRFF3apdVa8vuRIzfRRZaiAiVMPUDOiq+KN9rQO7an/jo1h3cIJTxCgJIB5FWMR1wBSoTdGax/ku75LIWJ/pU0WEoRr4y32tS1/GjB4zevSYu9eEJ6/vjh5DY8pPNJ6ePl8SPARIIBqZr0ZKFQHiEUATtUXGHh87dtSosaPu7DkrvDh+ZxQNGVt6EHQsne15IngIgKCKGIaigaCDjppMXxz8SW6G55j2oAu58eDBEkGCZExYmCZqc6Qt+JOOHDzYRGOcZPeDgX/OkczEYLJ8iafCnWQ6SNA4G21T8Y9wiGzKyk/WkYE77bN/OPRmkcyx2s2yn2R7u8h4muqybTpa4casScEKkr1SZFbaPn/Hw4VMa9CNzAz8Exwi09sn2q71MbeSXKCquTGpF4lMbfutXxa7lORFeZAcm+xtInTvtZN2KUlrR4VE76zI1Jw9G4h2R0lkrCftKpNmwZ2qic8i0pp2XOtJrQ7brDSoHJ5MH/H6s+NQBQYRucySzHaUJFlhaxPyFMnMgycsIu9ss9irYXJyHtmF0h6tNa69FZ5wiIyjj+hWkun2hs86FX5WJAlXxufavXuLQ2Rqm3s8XIdExrq9raqsAzAvk/XuLQ6RTIcVCcnfS5IdB4kj1muLJI+lPXuLQ4SWWbUTm2I9+bci6dbZXr3FIkLLLHdm58ZV9Elb0FMk7T71KHfq6i1LZG6LQEJrAehovZA4cm62vffleZssiYx15xJlYsZjrlsLhDoo/9dbSjU0s8mAoqlV9rWut5UFHCoTqSQy1r1wisgaUm/VJ6LGof/Y12pW4zoQ9hJxLLNsRtlfJdmU/WsRus3V2VsBEIZm29fyZFMu6E0HlUTG+l+KpDvKi896RDQDKO9r6YDqua91+/iQKuwpb9btue096NYp4capD9Z7Z+va1zJ1VY0rYSoLoWtzI/AQefRgsIOj8vTjSWHx9KRzkDx7IFx4/ONXvr2sT0TTNBEPt8AirCXgwYSVA4hBA0rIM8mIkSixdfKAKgyDC/u+Wu8NHQ4XGp4j32kvYxWFgSiKVsOkVlnyVrARbJYJM1XID6QJWKQT/Qm7VAFBLLbKH1hZ2/iBq6s4WW/MDle8oCHeIeT47ry85MlW96pKyvy8zlntWcNA9rtfb5nMwXoDSOZ0W4Ik211hs7zoxhS5guQKZatbTRdgvQHEVfp/mSZp8yJ60QXSLC82kS0GZF30Acj9u7K9pF0gdaE1kS0SRIyWW0AQA+Mm8OtzkGOqNZEtDgSiT6qoFWhz63OQrXeAlM5v2HBh1dK1AtmDENkiQdwWk0SoE6SxmsgWB5KlQAAnLMg80ZrIFgdiDlw9EOSI/TD1NpmtOg8EqQstDAaudhlcfLHytnDZsqdAkNIE3St6ISBy8Gu5bM2TDEBCxiwuZfIMxNiz+VK21imAhIxZLBOAwF5n+9Z+FQiysp0DCfMkWW169jqbLVN9B4FkTeBtC5yBjyAL11oqTLbyRIeBWMO2KRSClDv9YrYy1wKZDM6f6HKcdIxZ0Hx7qiD35Pn/ua8iprpafLZK40GieBaf39PH0fBjOIUxC6YsXrtSPShZepfrW27rQT4HaqhmIxVHavoF67oKIFz/NY8gdeNn/tBs4evM6Q4SqdHlOAzovcKOKQACl6eytXB/QeLLMR7/kGoFK27DQDQXixzKTgVljxswKo6NwVBsCDgH5wMM/QbfNt18QU495Zz8RdkfyLEsLXT30OveSy+99Bs6ltWVlfHKMnoklhTNyPM0T5ITEtx8uNh7tYbt841vJyL0h4ep2qLfAj7/J/Lm7Y1Mxnv869a18bvWz3O4CBFRtJCIojAKQyyxjkVb7fqlTYTG2IVX7A/bZgc0wzq2n6O5icVza412yhvvc/4zn4Izuv+dBQrX7+aqlDw0kS9PV/xK4yO+OOftZ5xjo6tiwVWdKztdtl0vHY98buK+HUXZ8M7h6XEKjx/36PZ79BxZZRWTAEZBesaxFIGB24KOU2dlYMHWbB4SdLkbJXK3kfewRu1D5NNpYNR8H1ggSrO5dCKSVO7Bu1iK5GKivjOKWFg1su43y4y5EFnn03IBY927JCDzSbzq3KKtQ3YwUtpGCKNEkmU/CphIhHrAJZFGSDtpqCv52hJSbAyRHhkinY0mhAJ8clKZRH5lQwOARVvbhmWrPi/hQiSJjbmSF2dIB5KRJiDC0IBxbaUxO/XytSqYA5FtQe7hvXtlZO8kQ5naosfBMe1pZuNCRMSvSgd0050hECLVctiRaEsHbsoTYkLEkhAfgNG4JHISxMGureSBsf4iaXZAiVA5GsGAKvxOeOPUvs3IGFRbdG43697SH8/IqvCJWGvQbBcC8VVd4vw131hY5lYvkn3SOXybWRNCFzjVip0INVkqPMjrbsAEtLbo3NZyD2/656nEzJaQyvvJBEhiRmHVVir3KL1IyqymRKgTjdV/HwbHzwe1VSa7rnOzV0skZ5QI3bAnhEfU502tLsrBvRcky1QdQ0dKxJ4Qd4CfF32Wp09+epH8q+56WqSG4Wj98yCHlQ1JiCGBQhk6KONpQBD04pxH8DZ7moN4WfbgwF5d8Kh4c0XWb+Dfo2cRVARvfgdP+iH8pdlprKGtioudRztN8vq68zYv/ZPD9OKF1Ej+S4dUvbj9j68jsd4zqmhNs7V3uT7C5SshNVSMRgouHTOqBOe05ZKFB6qOR0KiThDbjWylNxpxkFx7VGeZjLAJrFjPaxUMogwPVPGovbeNrcZI8IeR206ylV7XfHdtN67Y62hJKAZZleKw+pP4n8BASrN16UPkbtwK/+1ohCuAjxpG8nCX34u/vW1Mm1IyZqvlNHp5dz1xEXvEiurXwiRCeaxpe/3LlzA/4xcqERqzNjdpJaZiq6Jv99TxZ2B9MWkKCgJRtTBUaLlZ0YF/+Zj9hMcviKlnmF48Di3rb+DHiFRqyykuQHBcWRD2vn8799/x/Ond27dp8bh79+mnJkctX2M9w4AxP7h/vsbOrMkdnT9/NI/1QRvBbCcaWS2a3MGTJ9Ha0I0slrWPJwdo4nDn4LCuDN3IfFln69UCTbxbrt7WlaEbidmarXZ/NXm0ipXBG6mz9epZwv08+gdvpM7W692EO3wfy4M3ss7WzrOUercXy8M3sliFDnmbUnNEDN8IZSs996YYvpGQreUC3dgAIz5bs94O2QAjPluvDtGDDTBC2Zod7aIHm2BksaJzbx82wch8+XoPfdgEI5jN0IuNMLJYoB/BCJNghpcYG+RGFQ6Dwhz9ODZSSIwFJLh1xTTMa93Z+m1o3cWWJyR98KBZ90a0Xs9r5fTxx/j4uYt9cELSq3mznnHFbDJBlx5y8MgAYe29CUXLgMAFhE72yjF4ZPBQcMcvdGSqMHmgcm/ojqAPR5RgDV1OznNrJlTUI6BEA3csMOGFI6kvpVJq1O1SoZRulzI+SqRdp1/B3wC2sN7dwwmsQM6Q534hWK6hRZVEte/8dsowBVglHVN9jK3SS8tKGtRuLUUuVYdUAO1SmSORdhkJ40VURsy+s4IZWzizfqWo1utdlOa0LTTXtI+K0ikXJFWGWTEqtGxKuVDtUlsY1ioV+7xMpL9rRAluBZ+CT41TiEYs84dkXPi/5YzjWkTpFh95KTPHUh6lYJapdinLmWmVagvjEunvGgGXgjNYIZSORuwEBMWclE6CGZgiSicY8Upa3hNcoJgKE6Vjy/dHHVLIVqkoyVkqzU6hFYrW0dgb4XBvxMgKRVtWH3LrnlJUo1VIioNkGPP4bbhvAFNUEUxyYh66WloRrdKy4JN2qeEGqTQ7i3+EPGnoZLvJvItlSMnTWbb57wJH9RLtM9lpbDpOnc3O/ACb/i1NA1ABvwAAAABJRU5ErkJggg==", + "image": "tb-image:cmFuZ2VfY2hhcnRfc3lzdGVtX3dpZGdldF9pbWFnZS5wbmc=:IlJhbmdlIGNoYXJ0IiBzeXN0ZW0gd2lkZ2V0IGltYWdl;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAACgCAMAAAB+IdObAAAC/VBMVEX////////8/PwAAAD///////+bsfP+wEzu7u73lkzz8/P1eWTT09PN1emRpeOcsvSxsbGQpeLc3NyXl5epqanjXHPLy8tti+OgoKD/wU26urr29vbts0fnkUf39/fIrYP4l02oqKjJroPl5eWUrPPDw8PCwsLJroSQqfKLpfKDn/HU1NSnu/X/tzD/pwNyku//vD//sB3m5ub2jj98mfB2lfD2hTD/rRPu8v3/3qD1fCD3+f7K1vnnjEf1eh30awSWrvOBnfFkhOLld1n1dRX0cxH/9N/1cVvld1jmjEf2izn/qQry9f2Yr/P/+u/+9u+RpuP82r//yGDdM1D3kEPzWD32gSixwfBWeN//2JDzY0v+vkf/siT+5+RBaNr7x6DbYWXxTC96mPD+7N+VqN35tID2emX3oWD3k0fm6/zc5PvV3vq2xveWrfL+8/Hd3d09ZNr/6b/6vZCPj4/2h3TfQl3bKkjaIUD/ujnxQCL0bwrC0PiWqN5Kbt3/79D6zMqGhob/0n/iUWn0aVH+vUPZGjr/tSuwwvZpiOLR0dH+2I97e3v1dWDkcV3fPVnxSCr/qw+Jo/F/m/GLoum3xOj64uZef+H41NoyW9hdfNbJycnxqLT7x5/4no/nb4P/zXDiVm3hS2TlcV3zXEPyUzj+uTTwRCbkbRB+mOaareN5k+FyjuBHbNw4YNn7xr3/47D70LD5t6zumqjngJH/2I+Ojo7lYnf4oWC+mF7utEj2iDTmfSrxRyrunw/kZwLL1vWWrfS/zPORqfP98fKjt/GGofHv7+/+7erK0umHnuKDm+Lf39/t5d7829bm2dT949Dzt8HqwLFse6r4raDsjJz3lIPopHzGpnT4q3DZVmXSNkvnj0LnjD7mgjbjWzHiSzHwRyrunQXv8/3+9POquOWot+Tu4s3u3b3rzrfUxrHu166boa6coK76uKzTvJvoppv6vpDuyYfdboDmkXH1fGffR2H3oV/kbVnnjkHtrTbOIDTiUiLhUCD/rhTuoROM0RHwAAAABXRSTlMg77MAvxFwlo8AAA5CSURBVHja1JtJaBNRGMfj8scXk8MwSYZxoiFhaC9FEQoRA7YHE6K9iMZ4KIoWcTkpqK3oRVH05HISwX1Db66guF48eHHFBfcFQUUQ933BL6PxZZyZRE2+of4aMhPyWvKb73vzf3nQQL9A/z743+lLGoE+Qlea0JLShVA0mFHFwP9Hn0CgL7QwdERgKnGlmY7QBYgNGwY2lleHBjLSNwAIpdlAFPRIQERBsIjcvDGQEUEimqLq0FFysUR4WLKiG5yQiKGiJGIqIJYCKQEGDhV6wAmJCD3VBDWqCxCmrjeBg+7tK06DkQD8Yd3C2ML1YMM/kY2FWM9GsOGfyLLuWOEg2PBPZMW22JotYMM3kYs9sdjbw2DDN5Eta2KxbQWw4ZtIYRmJrAAbfomsXxgjFq4DF36JXCmQB2eQ+CWybHuMKPAFiU8i61bESqy5Ai58EtnYY4l08wWJTyKHuy2R7d3gwieRnmWkwRok/ogsoc6y4FzI84tYsU4wBwm/iBXrP+i5CC74RcqxTnAu5C0RMypgppQ4lCaIlN6CxnKwUBZZcwhsWN/ZE4CeUA3TiCIiEImjoVCs/6T7MNggkXAk1YIo4lGoCaEDiQQIRRGN4fynaWVu3BRskIjRBJ0sbPtaDRR5fm/1jtWrV+/YsXrH+3uCDRJpDpNI5Me+VlwnMYFG8qYz9IvdZ8AFicQjioKmlC4A0JFeNJSuvBRZuxdcBEAIlGcGkUBDWdIVkuy6DCb4c+TqzpmhED0sipvBBL9IMU8WZToXgAd+kSknQhUs7wQP/CKXd1WK5E88BAv8IvnllSKruO6/7CJzFq0KVbJ2ClhgF9nbFbLRdQ4ssIss6LSLFJ+BBXaRYinWZ9LPT3YyBQmviIx19iCpS2QOanK1GCJ4g6R+kQVLUIvO5SE7+SLqgkWkmEcNptwP/c4i1AeDyIGu3VNqDSn+DyL5zp3VZ66M9Zm9WeTcfVpwVJvvtliXInNQBwwiFHU1UkHGOvcaRYqYKoSiAc0mEs2KwB8wZRFF3apdVa8vuRIzfRRZaiAiVMPUDOiq+KN9rQO7an/jo1h3cIJTxCgJIB5FWMR1wBSoTdGax/ku75LIWJ/pU0WEoRr4y32tS1/GjB4zevSYu9eEJ6/vjh5DY8pPNJ6ePl8SPARIIBqZr0ZKFQHiEUATtUXGHh87dtSosaPu7DkrvDh+ZxQNGVt6EHQsne15IngIgKCKGIaigaCDjppMXxz8SW6G55j2oAu58eDBEkGCZExYmCZqc6Qt+JOOHDzYRGOcZPeDgX/OkczEYLJ8iafCnWQ6SNA4G21T8Y9wiGzKyk/WkYE77bN/OPRmkcyx2s2yn2R7u8h4muqybTpa4casScEKkr1SZFbaPn/Hw4VMa9CNzAz8Exwi09sn2q71MbeSXKCquTGpF4lMbfutXxa7lORFeZAcm+xtInTvtZN2KUlrR4VE76zI1Jw9G4h2R0lkrCftKpNmwZ2qic8i0pp2XOtJrQ7brDSoHJ5MH/H6s+NQBQYRucySzHaUJFlhaxPyFMnMgycsIu9ss9irYXJyHtmF0h6tNa69FZ5wiIyjj+hWkun2hs86FX5WJAlXxufavXuLQ2Rqm3s8XIdExrq9raqsAzAvk/XuLQ6RTIcVCcnfS5IdB4kj1muLJI+lPXuLQ4SWWbUTm2I9+bci6dbZXr3FIkLLLHdm58ZV9Elb0FMk7T71KHfq6i1LZG6LQEJrAehovZA4cm62vffleZssiYx15xJlYsZjrlsLhDoo/9dbSjU0s8mAoqlV9rWut5UFHCoTqSQy1r1wisgaUm/VJ6LGof/Y12pW4zoQ9hJxLLNsRtlfJdmU/WsRus3V2VsBEIZm29fyZFMu6E0HlUTG+l+KpDvKi896RDQDKO9r6YDqua91+/iQKuwpb9btue096NYp4capD9Z7Z+va1zJ1VY0rYSoLoWtzI/AQefRgsIOj8vTjSWHx9KRzkDx7IFx4/ONXvr2sT0TTNBEPt8AirCXgwYSVA4hBA0rIM8mIkSixdfKAKgyDC/u+Wu8NHQ4XGp4j32kvYxWFgSiKVsOkVlnyVrARbJYJM1XID6QJWKQT/Qm7VAFBLLbKH1hZ2/iBq6s4WW/MDle8oCHeIeT47ry85MlW96pKyvy8zlntWcNA9rtfb5nMwXoDSOZ0W4Ik211hs7zoxhS5guQKZatbTRdgvQHEVfp/mSZp8yJ60QXSLC82kS0GZF30Acj9u7K9pF0gdaE1kS0SRIyWW0AQA+Mm8OtzkGOqNZEtDgSiT6qoFWhz63OQrXeAlM5v2HBh1dK1AtmDENkiQdwWk0SoE6SxmsgWB5KlQAAnLMg80ZrIFgdiDlw9EOSI/TD1NpmtOg8EqQstDAaudhlcfLHytnDZsqdAkNIE3St6ISBy8Gu5bM2TDEBCxiwuZfIMxNiz+VK21imAhIxZLBOAwF5n+9Z+FQiysp0DCfMkWW169jqbLVN9B4FkTeBtC5yBjyAL11oqTLbyRIeBWMO2KRSClDv9YrYy1wKZDM6f6HKcdIxZ0Hx7qiD35Pn/ua8iprpafLZK40GieBaf39PH0fBjOIUxC6YsXrtSPShZepfrW27rQT4HaqhmIxVHavoF67oKIFz/NY8gdeNn/tBs4evM6Q4SqdHlOAzovcKOKQACl6eytXB/QeLLMR7/kGoFK27DQDQXixzKTgVljxswKo6NwVBsCDgH5wMM/QbfNt18QU495Zz8RdkfyLEsLXT30OveSy+99Bs6ltWVlfHKMnoklhTNyPM0T5ITEtx8uNh7tYbt841vJyL0h4ep2qLfAj7/J/Lm7Y1Mxnv869a18bvWz3O4CBFRtJCIojAKQyyxjkVb7fqlTYTG2IVX7A/bZgc0wzq2n6O5icVza412yhvvc/4zn4Izuv+dBQrX7+aqlDw0kS9PV/xK4yO+OOftZ5xjo6tiwVWdKztdtl0vHY98buK+HUXZ8M7h6XEKjx/36PZ79BxZZRWTAEZBesaxFIGB24KOU2dlYMHWbB4SdLkbJXK3kfewRu1D5NNpYNR8H1ggSrO5dCKSVO7Bu1iK5GKivjOKWFg1su43y4y5EFnn03IBY927JCDzSbzq3KKtQ3YwUtpGCKNEkmU/CphIhHrAJZFGSDtpqCv52hJSbAyRHhkinY0mhAJ8clKZRH5lQwOARVvbhmWrPi/hQiSJjbmSF2dIB5KRJiDC0IBxbaUxO/XytSqYA5FtQe7hvXtlZO8kQ5naosfBMe1pZuNCRMSvSgd0050hECLVctiRaEsHbsoTYkLEkhAfgNG4JHISxMGureSBsf4iaXZAiVA5GsGAKvxOeOPUvs3IGFRbdG43697SH8/IqvCJWGvQbBcC8VVd4vw131hY5lYvkn3SOXybWRNCFzjVip0INVkqPMjrbsAEtLbo3NZyD2/656nEzJaQyvvJBEhiRmHVVir3KL1IyqymRKgTjdV/HwbHzwe1VSa7rnOzV0skZ5QI3bAnhEfU502tLsrBvRcky1QdQ0dKxJ4Qd4CfF32Wp09+epH8q+56WqSG4Wj98yCHlQ1JiCGBQhk6KONpQBD04pxH8DZ7moN4WfbgwF5d8Kh4c0XWb+Dfo2cRVARvfgdP+iH8pdlprKGtioudRztN8vq68zYv/ZPD9OKF1Ej+S4dUvbj9j68jsd4zqmhNs7V3uT7C5SshNVSMRgouHTOqBOe05ZKFB6qOR0KiThDbjWylNxpxkFx7VGeZjLAJrFjPaxUMogwPVPGovbeNrcZI8IeR206ylV7XfHdtN67Y62hJKAZZleKw+pP4n8BASrN16UPkbtwK/+1ohCuAjxpG8nCX34u/vW1Mm1IyZqvlNHp5dz1xEXvEiurXwiRCeaxpe/3LlzA/4xcqERqzNjdpJaZiq6Jv99TxZ2B9MWkKCgJRtTBUaLlZ0YF/+Zj9hMcviKlnmF48Di3rb+DHiFRqyykuQHBcWRD2vn8799/x/Ond27dp8bh79+mnJkctX2M9w4AxP7h/vsbOrMkdnT9/NI/1QRvBbCcaWS2a3MGTJ9Ha0I0slrWPJwdo4nDn4LCuDN3IfFln69UCTbxbrt7WlaEbidmarXZ/NXm0ipXBG6mz9epZwv08+gdvpM7W692EO3wfy4M3ss7WzrOUercXy8M3sliFDnmbUnNEDN8IZSs996YYvpGQreUC3dgAIz5bs94O2QAjPluvDtGDDTBC2Zod7aIHm2BksaJzbx82wch8+XoPfdgEI5jN0IuNMLJYoB/BCJNghpcYG+RGFQ6Dwhz9ODZSSIwFJLh1xTTMa93Z+m1o3cWWJyR98KBZ90a0Xs9r5fTxx/j4uYt9cELSq3mznnHFbDJBlx5y8MgAYe29CUXLgMAFhE72yjF4ZPBQcMcvdGSqMHmgcm/ojqAPR5RgDV1OznNrJlTUI6BEA3csMOGFI6kvpVJq1O1SoZRulzI+SqRdp1/B3wC2sN7dwwmsQM6Q534hWK6hRZVEte/8dsowBVglHVN9jK3SS8tKGtRuLUUuVYdUAO1SmSORdhkJ40VURsy+s4IZWzizfqWo1utdlOa0LTTXtI+K0ikXJFWGWTEqtGxKuVDtUlsY1ioV+7xMpL9rRAluBZ+CT41TiEYs84dkXPi/5YzjWkTpFh95KTPHUh6lYJapdinLmWmVagvjEunvGgGXgjNYIZSORuwEBMWclE6CGZgiSicY8Upa3hNcoJgKE6Vjy/dHHVLIVqkoyVkqzU6hFYrW0dgb4XBvxMgKRVtWH3LrnlJUo1VIioNkGPP4bbhvAFNUEUxyYh66WloRrdKy4JN2qeEGqTQ7i3+EPGnoZLvJvItlSMnTWbb57wJH9RLtM9lpbDpOnc3O/ACb/i1NA1ABvwAAAABJRU5ErkJggg==", "description": "Displays changes to time-series data over time visualized with color ranges — for example, temperature or humidity readings.", "descriptor": { "type": "timeseries", @@ -20,9 +20,8 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-range-chart-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}]}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"dataZoom\":true,\"rangeColors\":[{\"to\":-20,\"color\":\"#234CC7\"},{\"from\":-20,\"to\":0,\"color\":\"#305AD7\"},{\"from\":0,\"to\":10,\"color\":\"#7191EF\"},{\"from\":10,\"to\":20,\"color\":\"#FFA600\"},{\"from\":20,\"to\":30,\"color\":\"#F36900\"},{\"from\":30,\"to\":40,\"color\":\"#F04022\"},{\"from\":40,\"color\":\"#D81838\"}],\"outOfRangeColor\":\"#ccc\",\"fillArea\":true,\"showLegend\":true,\"legendPosition\":\"top\",\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"dd MMM yyyy HH:mm\",\"lastUpdateAgo\":false,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Range chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"°C\",\"decimals\":0,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}]}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"dataZoom\":true,\"rangeColors\":[{\"to\":-20,\"color\":\"#234CC7\"},{\"from\":-20,\"to\":0,\"color\":\"#305AD7\"},{\"from\":0,\"to\":10,\"color\":\"#7191EF\"},{\"from\":10,\"to\":20,\"color\":\"#FFA600\"},{\"from\":20,\"to\":30,\"color\":\"#F36900\"},{\"from\":30,\"to\":40,\"color\":\"#F04022\"},{\"from\":40,\"color\":\"#D81838\"}],\"outOfRangeColor\":\"#ccc\",\"fillArea\":true,\"showLegend\":true,\"legendPosition\":\"top\",\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"tooltipDateInterval\":true},\"title\":\"Range chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"°C\",\"decimals\":0,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, - "externalId": null, "tags": [ "range", "color range", diff --git a/application/src/main/data/json/system/widget_types/time_series_chart.json b/application/src/main/data/json/system/widget_types/time_series_chart.json index 688cce76fb..1c215e21c8 100644 --- a/application/src/main/data/json/system/widget_types/time_series_chart.json +++ b/application/src/main/data/json/system/widget_types/time_series_chart.json @@ -20,7 +20,7 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-time-series-chart-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":\"dd MMM yyyy HH:mm:ss\",\"lastUpdateAgo\":false,\"custom\":false},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}}},\"title\":\"Time series chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":1000,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Time series chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, "tags": [ "chart", diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.html index fe642f3d6c..c98c9274cc 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/bar-chart-with-labels-basic-config.component.html @@ -195,7 +195,8 @@ {{ 'tooltip.date' | translate }}
    - + diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.html index 6f888a3de0..5be56204fa 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/range-chart-basic-config.component.html @@ -169,7 +169,8 @@ {{ 'tooltip.date' | translate }}
    - + diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html index b254b4df68..94866da201 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/chart/time-series-chart-basic-config.component.html @@ -25,10 +25,6 @@ forceSingleDatasource formControlName="datasources"> - - + +
    - + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts index 852f4950ce..7ed3e9c1cd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts @@ -37,6 +37,7 @@ import { import { WidgetContext } from '@home/models/widget-component.models'; import { Observable } from 'rxjs'; import { + autoDateFormat, backgroundStyle, ComponentStyle, DateFormatProcessor, @@ -193,7 +194,7 @@ export class AggregatedValueCardWidgetComponent implements OnInit, AfterViewInit } }, tooltipDateInterval: false, - tooltipDateFormat: simpleDateFormat('dd MMM yyyy HH:mm:ss') + tooltipDateFormat: autoDateFormat() }; this.lineChart = new TbTimeSeriesChart(this.ctx, settings, this.chartElement.nativeElement, this.renderer, true); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts index a7981b3acf..fe5953787a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-chart-card-widget.component.ts @@ -30,6 +30,7 @@ import { import { WidgetContext } from '@home/models/widget-component.models'; import { formatValue, isDefinedAndNotNull, isNumeric } from '@core/utils'; import { + autoDateFormat, backgroundStyle, ColorProcessor, ComponentStyle, @@ -174,7 +175,7 @@ export class ValueChartCardWidgetComponent implements OnInit, AfterViewInit, OnD } }, tooltipDateInterval: false, - tooltipDateFormat: simpleDateFormat('dd MMM yyyy HH:mm:ss') + tooltipDateFormat: autoDateFormat() }; this.lineChart = new TbTimeSeriesChart(this.ctx, settings, this.chartElement.nativeElement, this.renderer, false); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts index 4784a65c88..da7f4d4e40 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts @@ -57,7 +57,7 @@ import { echartsTooltipFormatter, toNamedData } from '@home/components/widget/lib/chart/echarts-widget.models'; -import { IntervalMath } from '@shared/models/time/time.models'; +import { AggregationType, IntervalMath } from '@shared/models/time/time.models'; type BarChartDataItem = EChartsSeriesItem; @@ -97,6 +97,10 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft legendLabelStyle: ComponentStyle; disabledLegendLabelStyle: ComponentStyle; + private get noAggregation(): boolean { + return this.ctx.defaultSubscription.timeWindowConfig?.aggregation?.type === AggregationType.NONE; + } + private shapeResize$: ResizeObserver; private decimals = 0; @@ -388,7 +392,8 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft if (this.settings.showTooltip) { const focusedSeriesIndex = this.focusedSeriesIndex(); return echartsTooltipFormatter(this.renderer, this.tooltipDateFormat, - this.settings, params, this.decimals, this.units, focusedSeriesIndex); + this.settings, params, this.decimals, this.units, focusedSeriesIndex, null, + this.noAggregation ? null : this.ctx.timeWindow.interval); } else { return undefined; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts index c446fcbda1..bac5616506 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts @@ -44,9 +44,10 @@ import { } from 'echarts/charts'; import { LabelLayout } from 'echarts/features'; import { CanvasRenderer, SVGRenderer } from 'echarts/renderers'; -import { DataEntry, DataKey, DataSet, LegendDirection } from '@shared/models/widget.models'; +import { DataEntry, DataKey, DataSet } from '@shared/models/widget.models'; import { calculateAggIntervalWithWidgetTimeWindow, + Interval, IntervalMath, WidgetTimewindow } from '@shared/models/time/time.models'; @@ -333,7 +334,8 @@ export const echartsTooltipFormatter = (renderer: Renderer2, decimals: number, units: string, focusedSeriesIndex: number, - series?: EChartsSeriesItem[]): null | HTMLElement => { + series?: EChartsSeriesItem[], + interval?: Interval): null | HTMLElement => { if (!params || Array.isArray(params) && !params[0]) { return null; } @@ -349,8 +351,8 @@ export const echartsTooltipFormatter = (renderer: Renderer2, const startTs = firstParam.value[2]; const endTs = firstParam.value[3]; if (settings.tooltipDateInterval && startTs && endTs && (endTs - 1) > startTs) { - const startDateText = tooltipDateFormat.update(startTs); - const endDateText = tooltipDateFormat.update(endTs - 1); + const startDateText = tooltipDateFormat.update(startTs, interval); + const endDateText = tooltipDateFormat.update(endTs - 1, interval); if (startDateText === endDateText) { dateText = startDateText; } else { @@ -358,7 +360,7 @@ export const echartsTooltipFormatter = (renderer: Renderer2, } } else { const ts = firstParam.value[0]; - dateText = tooltipDateFormat.update(ts); + dateText = tooltipDateFormat.update(ts, interval); } renderer.appendChild(dateElement, renderer.createText(dateText)); renderer.setStyle(dateElement, 'font-family', settings.tooltipDateFont.family); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts index 9909be6532..1705074a1e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts @@ -54,6 +54,7 @@ import { toNamedData } from '@home/components/widget/lib/chart/echarts-widget.models'; import { CallbackDataParams } from 'echarts/types/dist/shared'; +import { AggregationType } from '@shared/models/time/time.models'; interface VisualPiece { lt?: number; @@ -197,6 +198,10 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn disabledLegendLabelStyle: ComponentStyle; visibleRangeItems: RangeItem[]; + private get noAggregation(): boolean { + return this.ctx.defaultSubscription.timeWindowConfig?.aggregation?.type === AggregationType.NONE; + } + private rangeItems: RangeItem[]; private shapeResize$: ResizeObserver; @@ -324,7 +329,8 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn }, formatter: (params: CallbackDataParams[]) => this.settings.showTooltip ? echartsTooltipFormatter(this.renderer, this.tooltipDateFormat, - this.settings, params, this.decimals, this.units, 0) : undefined, + this.settings, params, this.decimals, this.units, 0, null, + this.noAggregation ? null : this.ctx.timeWindow.interval) : undefined, padding: [8, 12], backgroundColor: this.settings.tooltipBackgroundColor, borderWidth: 0, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index b5d5968565..3c2343853c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -19,10 +19,16 @@ import { EChartsOption, EChartsSeriesItem, EChartsTooltipTrigger, - EChartsTooltipWidgetSettings, + EChartsTooltipWidgetSettings, getYAxis, measureThresholdLabelOffset } from '@home/components/widget/lib/chart/echarts-widget.models'; -import { ComponentStyle, Font, simpleDateFormat, textStyle } from '@shared/models/widget-settings.models'; +import { + autoDateFormat, AutoDateFormatSettings, + ComponentStyle, + Font, + simpleDateFormat, + textStyle, tsToFormatTimeUnit +} from '@shared/models/widget-settings.models'; import { XAXisOption, YAXisOption } from 'echarts/types/dist/shared'; import { CustomSeriesOption, LineSeriesOption } from 'echarts/charts'; import { @@ -50,6 +56,7 @@ import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { TbColorScheme } from '@shared/models/color.models'; import { AbstractControl, ValidationErrors } from '@angular/forms'; import { MarkLine2DDataItemOption } from 'echarts/types/src/component/marker/MarkLineModel'; +import { DatePipe } from '@angular/common'; export enum TimeSeriesChartType { default = 'default', @@ -297,6 +304,20 @@ export interface TimeSeriesChartAxisSettings { splitLinesColor: string; } +export interface TimeSeriesChartXAxisSettings extends TimeSeriesChartAxisSettings { + ticksFormat: AutoDateFormatSettings; +} + +export const defaultXAxisTicksFormat: AutoDateFormatSettings = { + millisecond: 'HH:mm:ss SSS', + second: 'HH:mm:ss', + minute: 'HH:mm', + hour: 'HH:mm', + day: 'MMM dd', + month: 'MMM', + year: 'yyyy' +}; + export type TimeSeriesChartYAxisId = 'default' | string; export interface TimeSeriesChartYAxisSettings extends TimeSeriesChartAxisSettings { @@ -304,6 +325,8 @@ export interface TimeSeriesChartYAxisSettings extends TimeSeriesChartAxisSetting order?: number; units?: string; decimals?: number; + interval?: number; + splitNumber?: number; min?: number | string; max?: number | string; intervalCalculator?: string; @@ -536,7 +559,7 @@ export interface TimeSeriesChartSettings extends EChartsTooltipWidgetSettings { dataZoom: boolean; stack: boolean; yAxes: TimeSeriesChartYAxes; - xAxis: TimeSeriesChartAxisSettings; + xAxis: TimeSeriesChartXAxisSettings; animation: TimeSeriesChartAnimationSettings; noAggregationBarWidthSettings: TimeSeriesChartNoAggregationBarWidthSettings; } @@ -574,6 +597,7 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { lineHeight: '1' }, tickLabelColor: timeSeriesChartColorScheme['axis.tickLabel'].light, + ticksFormat: {}, showTicks: true, ticksColor: timeSeriesChartColorScheme['axis.ticks'].light, showLine: true, @@ -616,7 +640,7 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { }, tooltipValueColor: 'rgba(0, 0, 0, 0.76)', tooltipShowDate: true, - tooltipDateFormat: simpleDateFormat('dd MMM yyyy HH:mm:ss'), + tooltipDateFormat: autoDateFormat(), tooltipDateFont: { family: 'Roboto', size: 11, @@ -851,12 +875,59 @@ export const createTimeSeriesYAxis = (units: string, return yAxis; }; -export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartAxisSettings, - min: number, max: number, darkMode: boolean): XAXisOption => { +export const updateYAxisIntervals = (chart: ECharts, + yAxis: TimeSeriesChartYAxis, empty: boolean): boolean => { + let changed = false; + let interval: number; + let splitNumber: number; + let minInterval: number; + if (!empty) { + interval = calculateYAxisInterval(chart, yAxis); + if (isUndefinedOrNull(interval)) { + if (isDefinedAndNotNull(yAxis.settings.splitNumber)) { + splitNumber = yAxis.settings.splitNumber; + } else { + minInterval = (1 / Math.pow(10, yAxis.decimals)); + } + } + } + if (yAxis.option.interval !== interval) { + yAxis.option.interval = interval; + changed = true; + } + if (yAxis.option.splitNumber !== splitNumber) { + yAxis.option.splitNumber = splitNumber; + changed = true; + } + if (yAxis.option.minInterval !== minInterval) { + yAxis.option.minInterval = minInterval; + changed = true; + } + return changed; +}; + +const calculateYAxisInterval = (chart: ECharts, yAxis: TimeSeriesChartYAxis): number | undefined => { + let interval = yAxis.settings.interval; + if (yAxis.intervalCalculator) { + const axis = getYAxis(chart, yAxis.id); + if (axis) { + try { + interval = yAxis.intervalCalculator(axis); + } catch (_e) {} + } + } + return interval; +}; + +export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartXAxisSettings, + min: number, max: number, + datePipe: DatePipe, + darkMode: boolean): XAXisOption => { const xAxisTickLabelStyle = createChartTextStyle(settings.tickLabelFont, settings.tickLabelColor, darkMode, 'axis.tickLabel'); const xAxisNameStyle = createChartTextStyle(settings.labelFont, settings.labelColor, darkMode, 'axis.label'); + const ticksFormat = mergeDeep({}, defaultXAxisTicksFormat, settings.ticksFormat); return { show: settings.show, type: 'time', @@ -885,15 +956,16 @@ export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartAxisSetting fontFamily: xAxisTickLabelStyle.fontFamily, fontSize: xAxisTickLabelStyle.fontSize, hideOverlap: true, - /* formatter: { - year: '{yyyy}', - month: '{MMM}', - day: '{d}', - hour: '{HH}:{mm}', - minute: '{HH}:{mm}', - second: '{HH}:{mm}:{ss}', - millisecond: '{hh}:{mm}:{ss} {SSS}' - } */ + formatter: (value: number, index: number, extra: {level: number}) => { + const unit = tsToFormatTimeUnit(value); + const format = ticksFormat[unit]; + const formatted = datePipe.transform(value, format); + if (extra.level > 0) { + return `{primary|${formatted}}`; + } else { + return formatted; + } + } }, axisLine: { show: settings.showLine, @@ -970,10 +1042,10 @@ const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[], dataGroupId: item.id, yAxisIndex: item.yAxisIndex, data: [], - tooltip: { - show: false - }, markLine: { + tooltip: { + show: false + }, lineStyle: { width: item.settings.lineWidth, color: prepareChartThemeColor(item.settings.lineColor, darkMode, 'threshold.line'), diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 57e52f5f5d..8e5fc4f305 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -39,7 +39,7 @@ import { TimeSeriesChartYAxis, TimeSeriesChartYAxisId, TimeSeriesChartYAxisSettings, - updateDarkMode + updateDarkMode, updateYAxisIntervals } from '@home/components/widget/lib/chart/time-series-chart.models'; import { ResizeObserver } from '@juggle/resize-observer'; import { @@ -51,12 +51,11 @@ import { echartsTooltipFormatter, EChartsTooltipTrigger, getAxisExtent, - getYAxis, measureXAxisNameHeight, measureYAxisNameWidth, toNamedData } from '@home/components/widget/lib/chart/echarts-widget.models'; -import { DateFormatProcessor } from '@shared/models/widget-settings.models'; +import { autoDateFormat, DateFormatProcessor } from '@shared/models/widget-settings.models'; import { isDefinedAndNotNull, isEqual, mergeDeep } from '@core/utils'; import { DataKey, Datasource, DatasourceType, widgetType } from '@shared/models/widget.models'; import * as echarts from 'echarts/core'; @@ -485,7 +484,8 @@ export class TbTimeSeriesChart { }, formatter: (params: CallbackDataParams[]) => this.settings.showTooltip ? echartsTooltipFormatter(this.renderer, this.tooltipDateFormat, - this.settings, params, 0, '', -1, this.dataItems) : undefined, + this.settings, params, 0, '', -1, this.dataItems, + this.noAggregation ? null : this.ctx.timeWindow.interval) : undefined, padding: [8, 12], backgroundColor: this.settings.tooltipBackgroundColor, borderWidth: 0, @@ -499,7 +499,7 @@ export class TbTimeSeriesChart { }], xAxis: [ createTimeSeriesXAxisOption(this.settings.xAxis, this.ctx.defaultSubscription.timeWindow.minTime, - this.ctx.defaultSubscription.timeWindow.maxTime, this.darkMode) + this.ctx.defaultSubscription.timeWindow.maxTime, this.ctx.date, this.darkMode) ], yAxis: this.yAxisList.map(axis => axis.option), dataZoom: [ @@ -611,7 +611,7 @@ export class TbTimeSeriesChart { this.timeSeriesChartOptions.yAxis = this.yAxisList.map(axis => axis.option); this.timeSeriesChart.setOption(this.timeSeriesChartOptions, {replaceMerge: ['yAxis', 'xAxis', 'grid'], lazyUpdate: true}); } - changed = this.calculateYAxisInterval(this.yAxisList); + changed = this.updateYAxesIntervals(this.yAxisList); if (changed) { this.timeSeriesChartOptions.yAxis = this.yAxisList.map(axis => axis.option); this.timeSeriesChart.setOption(this.timeSeriesChartOptions, {replaceMerge: ['yAxis'], lazyUpdate: true}); @@ -696,26 +696,12 @@ export class TbTimeSeriesChart { return !axisDataItems.length; } - private calculateYAxisInterval(axisList: TimeSeriesChartYAxis[]): boolean { + private updateYAxesIntervals(axisList: TimeSeriesChartYAxis[]): boolean { let changed = false; for (const yAxis of axisList) { - const minInterval = this.yAxisEmpty(yAxis) ? undefined : (1 / Math.pow(10, yAxis.decimals)); - if (yAxis.option.minInterval !== minInterval) { - yAxis.option.minInterval = minInterval; + if (updateYAxisIntervals(this.timeSeriesChart, yAxis, this.yAxisEmpty(yAxis))) { changed = true; } - if (yAxis.intervalCalculator) { - const axis = getYAxis(this.timeSeriesChart, yAxis.id); - if (axis) { - try { - const interval = yAxis.intervalCalculator(axis); - if ((yAxis.option as any).interval !== interval) { - (yAxis.option as any).interval = interval; - changed = true; - } - } catch (_e) {} - } - } } return changed; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.html index e40470d75e..b20b941bd1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/bar-chart-with-labels-widget-settings.component.html @@ -114,7 +114,8 @@ {{ 'tooltip.date' | translate }}
    - + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.html index 94b64caad4..cf5bbcfdd5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/range-chart-widget-settings.component.html @@ -104,7 +104,8 @@ {{ 'tooltip.date' | translate }}
    - + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html index cd6f1255f8..fbd960be18 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/chart/time-series-chart-widget-settings.component.html @@ -123,7 +123,8 @@ {{ 'tooltip.date' | translate }}
    - + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.html new file mode 100644 index 0000000000..a88ea77488 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.html @@ -0,0 +1,49 @@ + +
    +
    date.time-granularity-formats
    +
    +
    +
    {{ formatTimeUnitTranslations.get(unit) | translate }}
    +
    + + +
    +
    + +
    {{ previewText[unit] }}
    +
    +
    +
    +
    + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.scss new file mode 100644 index 0000000000..be50f87af8 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.scss @@ -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 '../../../../../../../../scss/constants'; + +.tb-auto-date-format-settings-panel { + width: 620px; + display: flex; + flex-direction: column; + gap: 16px; + @media #{$mat-lt-md} { + width: 90vw; + } + .tb-auto-date-format-settings-title { + font-size: 16px; + font-weight: 500; + line-height: 24px; + letter-spacing: 0.25px; + color: rgba(0, 0, 0, 0.87); + } + .tb-auto-date-format-settings-panel-content { + display: flex; + flex-direction: column; + gap: 16px; + overflow: auto; + margin: -10px; + padding: 10px; + } + .tb-form-row { + .fixed-title-width { + min-width: 120px; + } + .mat-mdc-form-field.tb-date-format-input { + .mat-mdc-text-field-wrapper.mdc-text-field--outlined { + .mat-mdc-form-field-flex { + .mat-mdc-form-field-icon-suffix { + display: flex; + align-items: center; + line-height: normal; + } + } + } + } + .preview-text { + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: 0.2px; + color: rgba(0, 0, 0, 0.38); + } + } + .tb-auto-date-format-settings-panel-buttons { + height: 40px; + display: flex; + flex-direction: row; + gap: 16px; + justify-content: flex-end; + align-items: flex-end; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.component.ts new file mode 100644 index 0000000000..dcfc942778 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings-panel.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, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core'; +import { PageComponent } from '@shared/components/page.component'; +import { + AutoDateFormatSettings, defaultAutoDateFormatSettings, + FormatTimeUnit, + formatTimeUnits, + formatTimeUnitTranslations +} from '@shared/models/widget-settings.models'; +import { TbPopoverComponent } from '@shared/components/popover.component'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { DatePipe } from '@angular/common'; + +@Component({ + selector: 'tb-auto-date-format-settings-panel', + templateUrl: './auto-date-format-settings-panel.component.html', + providers: [], + styleUrls: ['./auto-date-format-settings-panel.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class AutoDateFormatSettingsPanelComponent extends PageComponent implements OnInit { + + formatTimeUnits = formatTimeUnits; + + formatTimeUnitTranslations = formatTimeUnitTranslations; + + @Input() + autoDateFormatSettings: AutoDateFormatSettings; + + @Input() + defaultValues = defaultAutoDateFormatSettings; + + @Input() + popover: TbPopoverComponent; + + @Output() + autoDateFormatSettingsApplied = new EventEmitter(); + + autoDateFormatFormGroup: UntypedFormGroup; + + previewText: {[unit in FormatTimeUnit]: string} = {} as any; + + constructor(private date: DatePipe, + private fb: UntypedFormBuilder, + protected store: Store) { + super(store); + } + + ngOnInit(): void { + this.autoDateFormatFormGroup = this.fb.group({}); + for (const unit of formatTimeUnits) { + this.autoDateFormatFormGroup.addControl(unit, + this.fb.control(this.autoDateFormatSettings[unit] || this.defaultValues[unit], [Validators.required])); + this.autoDateFormatFormGroup.get(unit).valueChanges.subscribe((value: string) => { + this.previewText[unit] = this.date.transform(Date.now(), value); + }); + this.previewText[unit] = this.date.transform(Date.now(), this.autoDateFormatSettings[unit] || this.defaultValues[unit]); + } + } + + cancel() { + this.popover?.hide(); + } + + applyAutoDateFormatSettings() { + const autoDateFormatSettings: AutoDateFormatSettings = this.autoDateFormatFormGroup.value; + for (const unit of formatTimeUnits) { + if (autoDateFormatSettings[unit] === this.defaultValues[unit]) { + delete autoDateFormatSettings[unit]; + } + } + this.autoDateFormatSettingsApplied.emit(autoDateFormatSettings); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.html new file mode 100644 index 0000000000..864ad3047c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.html @@ -0,0 +1,25 @@ + + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.component.ts new file mode 100644 index 0000000000..cf5b9033fa --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/auto-date-format-settings.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, Renderer2, ViewContainerRef } from '@angular/core'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { AutoDateFormatSettings, defaultAutoDateFormatSettings } from '@shared/models/widget-settings.models'; +import { MatButton } from '@angular/material/button'; +import { TbPopoverService } from '@shared/components/popover.service'; +import { deepClone, mergeDeep } from '@core/utils'; +import { + AutoDateFormatSettingsPanelComponent +} from '@home/components/widget/lib/settings/common/auto-date-format-settings-panel.component'; + +@Component({ + selector: 'tb-auto-date-format-settings', + templateUrl: './auto-date-format-settings.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AutoDateFormatSettingsComponent), + multi: true + } + ] +}) +export class AutoDateFormatSettingsComponent implements OnInit, ControlValueAccessor { + + @Input() + disabled: boolean; + + @Input() + defaultValues = defaultAutoDateFormatSettings; + + private modelValue: AutoDateFormatSettings; + + private propagateChange = null; + + constructor(private popoverService: TbPopoverService, + private renderer: Renderer2, + private viewContainerRef: ViewContainerRef) {} + + ngOnInit(): void { + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + } + + writeValue(value: AutoDateFormatSettings): void { + this.modelValue = value; + } + + openAutoFormatSettingsPopup($event: Event, matButton: MatButton) { + if ($event) { + $event.stopPropagation(); + } + const trigger = matButton._elementRef.nativeElement; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const ctx: any = { + autoDateFormatSettings: deepClone(this.modelValue), + defaultValues: this.defaultValues + }; + const autoDateFormatSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, AutoDateFormatSettingsPanelComponent, ['leftOnly', 'leftTopOnly', 'leftBottomOnly'], true, null, + ctx, + {}, + {}, {}, true); + autoDateFormatSettingsPanelPopover.tbComponentRef.instance.popover = autoDateFormatSettingsPanelPopover; + autoDateFormatSettingsPanelPopover.tbComponentRef.instance.autoDateFormatSettingsApplied.subscribe((autoDateFormatSettings) => { + autoDateFormatSettingsPanelPopover.hide(); + this.modelValue = autoDateFormatSettings; + this.propagateChange(this.modelValue); + }); + } + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html index 9511baf121..1d4bb95f5c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.html @@ -74,6 +74,10 @@
    widgets.time-series-chart.axis.tick-labels
    + +
    +
    +
    + {{ 'widgets.time-series-chart.axis.ticks-interval' | translate }} +
    + + + +
    +
    +
    + {{ 'widgets.time-series-chart.axis.split-number' | translate }} +
    + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts index a88fc2e123..8dafc7050f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/chart/time-series-chart-axis-settings.component.ts @@ -23,9 +23,9 @@ import { Validators } from '@angular/forms'; import { - AxisPosition, + AxisPosition, defaultXAxisTicksFormat, timeSeriesAxisPositionTranslations, - TimeSeriesChartAxisSettings, + TimeSeriesChartAxisSettings, TimeSeriesChartXAxisSettings, TimeSeriesChartYAxisSettings } from '@home/components/widget/lib/chart/time-series-chart.models'; import { merge } from 'rxjs'; @@ -58,6 +58,8 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu functionScopeVariables = this.widgetService.getWidgetScopeVariables(); + defaultXAxisTicksFormat = defaultXAxisTicksFormat; + @Input() disabled: boolean; @@ -68,7 +70,7 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu @coerceBoolean() advanced = false; - private modelValue: TimeSeriesChartAxisSettings | TimeSeriesChartYAxisSettings; + private modelValue: TimeSeriesChartXAxisSettings | TimeSeriesChartYAxisSettings; private propagateChange = null; @@ -103,8 +105,12 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu this.axisSettingsFormGroup.addControl('units', this.fb.control(null, [])); this.axisSettingsFormGroup.addControl('decimals', this.fb.control(null, [Validators.min(0)])); this.axisSettingsFormGroup.addControl('ticksFormatter', this.fb.control(null, [])); + this.axisSettingsFormGroup.addControl('interval', this.fb.control(null, [Validators.min(0)])); + this.axisSettingsFormGroup.addControl('splitNumber', this.fb.control(null, [Validators.min(1)])); this.axisSettingsFormGroup.addControl('min', this.fb.control(null, [])); this.axisSettingsFormGroup.addControl('max', this.fb.control(null, [])); + } else if (this.axisType === 'xAxis') { + this.axisSettingsFormGroup.addControl('ticksFormat', this.fb.control(null, [])); } this.axisSettingsFormGroup.valueChanges.subscribe(() => { this.updateModel(); @@ -161,12 +167,18 @@ export class TimeSeriesChartAxisSettingsComponent implements OnInit, ControlValu if (this.axisType === 'yAxis') { this.axisSettingsFormGroup.get('ticksFormatter').enable({emitEvent: false}); } + if (this.axisType === 'xAxis') { + this.axisSettingsFormGroup.get('ticksFormat').enable({emitEvent: false}); + } } else { this.axisSettingsFormGroup.get('tickLabelFont').disable({emitEvent: false}); this.axisSettingsFormGroup.get('tickLabelColor').disable({emitEvent: false}); if (this.axisType === 'yAxis') { this.axisSettingsFormGroup.get('ticksFormatter').disable({emitEvent: false}); } + if (this.axisType === 'xAxis') { + this.axisSettingsFormGroup.get('ticksFormat').disable({emitEvent: false}); + } } if (showTicks) { this.axisSettingsFormGroup.get('ticksColor').enable({emitEvent: false}); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.html index 79854d0a65..93d4ec68c6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.html @@ -23,4 +23,9 @@ *ngIf="dateFormatFormControl.value?.custom" matSuffix mat-icon-button (click)="openDateFormatSettingsPopup($event, customFormatButton)"> edit + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts index 3e2393d6ff..144f02fe46 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/date-format-select.component.ts @@ -16,16 +16,26 @@ import { Component, forwardRef, Input, OnInit, Renderer2, ViewChild, ViewContainerRef } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormControl } from '@angular/forms'; -import { compareDateFormats, dateFormats, DateFormatSettings } from '@shared/models/widget-settings.models'; +import { + AutoDateFormatSettings, + compareDateFormats, + dateFormats, + DateFormatSettings, + dateFormatsWithAuto, + defaultAutoDateFormatSettings +} from '@shared/models/widget-settings.models'; import { TranslateService } from '@ngx-translate/core'; import { DatePipe } from '@angular/common'; import { MatButton } from '@angular/material/button'; import { TbPopoverService } from '@shared/components/popover.service'; -import { deepClone } from '@core/utils'; +import { deepClone, mergeDeep } from '@core/utils'; import { DateFormatSettingsPanelComponent } from '@home/components/widget/lib/settings/common/date-format-settings-panel.component'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { + AutoDateFormatSettingsPanelComponent +} from '@home/components/widget/lib/settings/common/auto-date-format-settings-panel.component'; @Component({ selector: 'tb-date-format-select', @@ -51,6 +61,10 @@ export class DateFormatSelectComponent implements OnInit, ControlValueAccessor { @coerceBoolean() excludeLastUpdateAgo = false; + @Input() + @coerceBoolean() + includeAuto = false; + dateFormatList: DateFormatSettings[]; dateFormatsCompare = compareDateFormats; @@ -70,8 +84,9 @@ export class DateFormatSelectComponent implements OnInit, ControlValueAccessor { private viewContainerRef: ViewContainerRef) {} ngOnInit(): void { + const targetDateFormats = this.includeAuto ? dateFormatsWithAuto : dateFormats; this.dateFormatList = this.excludeLastUpdateAgo ? - dateFormats.filter(format => !format.lastUpdateAgo) : dateFormats; + targetDateFormats.filter(format => !format.lastUpdateAgo) : dateFormats; this.dateFormatFormControl = new UntypedFormControl(); this.dateFormatFormControl.valueChanges.subscribe((value: DateFormatSettings) => { this.updateModel(value); @@ -116,6 +131,8 @@ export class DateFormatSelectComponent implements OnInit, ControlValueAccessor { return this.translate.instant('date.custom-date'); } else if (value.lastUpdateAgo) { return this.translate.instant('date.last-update-n-ago'); + } else if (value.auto) { + return this.translate.instant('date.auto'); } else { if (!this.formatCache[value.format]) { this.formatCache[value.format] = this.date.transform(Date.now(), value.format); @@ -148,4 +165,30 @@ export class DateFormatSelectComponent implements OnInit, ControlValueAccessor { }); } } + + openAutoFormatSettingsPopup($event: Event, matButton: MatButton) { + if ($event) { + $event.stopPropagation(); + } + const trigger = matButton._elementRef.nativeElement; + if (this.popoverService.hasPopover(trigger)) { + this.popoverService.hidePopover(trigger); + } else { + const ctx: any = { + autoDateFormatSettings: mergeDeep({} as AutoDateFormatSettings, + defaultAutoDateFormatSettings, this.modelValue.autoDateFormatSettings) + }; + const autoDateFormatSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer, + this.viewContainerRef, AutoDateFormatSettingsPanelComponent, ['leftOnly', 'leftTopOnly', 'leftBottomOnly'], true, null, + ctx, + {}, + {}, {}, true); + autoDateFormatSettingsPanelPopover.tbComponentRef.instance.popover = autoDateFormatSettingsPanelPopover; + autoDateFormatSettingsPanelPopover.tbComponentRef.instance.autoDateFormatSettingsApplied.subscribe((autoDateFormatSettings) => { + autoDateFormatSettingsPanelPopover.hide(); + this.modelValue.autoDateFormatSettings = autoDateFormatSettings; + this.propagateChange(this.modelValue); + }); + } + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts index b80b20f402..5ed50a226f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/widget-settings-common.module.ts @@ -121,6 +121,12 @@ import { import { TimeSeriesChartAnimationSettingsComponent } from '@home/components/widget/lib/settings/common/chart/time-series-chart-animation-settings.component'; +import { + AutoDateFormatSettingsPanelComponent +} from '@home/components/widget/lib/settings/common/auto-date-format-settings-panel.component'; +import { + AutoDateFormatSettingsComponent +} from '@home/components/widget/lib/settings/common/auto-date-format-settings.component'; @NgModule({ declarations: [ @@ -134,6 +140,8 @@ import { CssSizeInputComponent, DateFormatSelectComponent, DateFormatSettingsPanelComponent, + AutoDateFormatSettingsComponent, + AutoDateFormatSettingsPanelComponent, BackgroundSettingsComponent, BackgroundSettingsPanelComponent, ValueSourceComponent, @@ -185,6 +193,8 @@ import { CssSizeInputComponent, DateFormatSelectComponent, DateFormatSettingsPanelComponent, + AutoDateFormatSettingsComponent, + AutoDateFormatSettingsPanelComponent, BackgroundSettingsComponent, BackgroundSettingsPanelComponent, ValueSourceComponent, diff --git a/ui-ngx/src/app/shared/models/widget-settings.models.ts b/ui-ngx/src/app/shared/models/widget-settings.models.ts index 1e2e0d2415..f3722c54b1 100644 --- a/ui-ngx/src/app/shared/models/widget-settings.models.ts +++ b/ui-ngx/src/app/shared/models/widget-settings.models.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { isDefinedAndNotNull, isNumber, isNumeric, isUndefinedOrNull, parseFunction } from '@core/utils'; +import { isDefinedAndNotNull, isNumber, isNumeric, isUndefinedOrNull, mergeDeep, parseFunction } from '@core/utils'; import { DataEntry, DataKey, @@ -34,6 +34,8 @@ import { Observable, of } from 'rxjs'; import { ImagePipe } from '@shared/pipe/image.pipe'; import { map } from 'rxjs/operators'; import { DomSanitizer } from '@angular/platform-browser'; +import { AVG_MONTH, DAY, HOUR, Interval, IntervalMath, MINUTE, SECOND, YEAR } from '@shared/models/time/time.models'; +import moment from 'moment'; export type ComponentStyle = {[klass: string]: any}; @@ -323,35 +325,85 @@ class FunctionColorProcessor extends ColorProcessor { } } +export type FormatTimeUnit = 'millisecond' | 'second' | 'minute' | 'hour' + | 'day' | 'month' | 'year'; + + +export const formatTimeUnits: FormatTimeUnit[] = [ + 'year', 'month', 'day', 'hour', 'minute', 'second', 'millisecond' +]; + +export const formatTimeUnitTranslations = new Map( + [ + ['year', 'date.unit-year'], + ['month', 'date.unit-month'], + ['day', 'date.unit-day'], + ['hour', 'date.unit-hour'], + ['minute', 'date.unit-minute'], + ['second', 'date.unit-second'], + ['millisecond', 'date.unit-millisecond'] + ] +); + +export type AutoDateFormatSettings = { + [unit in FormatTimeUnit]?: string; +}; + export interface DateFormatSettings { format?: string; lastUpdateAgo?: boolean; custom?: boolean; + auto?: boolean; hideLastUpdatePrefix?: boolean; + autoDateFormatSettings?: AutoDateFormatSettings; } export const simpleDateFormat = (format: string): DateFormatSettings => ({ format, lastUpdateAgo: false, - custom: false + custom: false, + auto: false }); export const lastUpdateAgoDateFormat = (): DateFormatSettings => ({ format: null, lastUpdateAgo: true, - custom: false + custom: false, + auto: false }); export const customDateFormat = (format: string): DateFormatSettings => ({ format, lastUpdateAgo: false, - custom: true + custom: true, + auto: false +}); + +export const defaultAutoDateFormatSettings: AutoDateFormatSettings = { + millisecond: 'MMM dd yyyy HH:mm:ss.SSS', + second: 'MMM dd yyyy HH:mm:ss', + minute: 'MMM dd yyyy HH:mm', + hour: 'MMM dd yyyy HH:mm', + day: 'MMM dd yyyy', + month: 'MMM yyyy', + year: 'yyyy' +}; + +export const autoDateFormat = (): DateFormatSettings => ({ + format: null, + lastUpdateAgo: false, + custom: false, + auto: true, + autoDateFormatSettings: {} }); -export const dateFormats = ['MMM dd yyyy HH:mm', 'dd MMM yyyy HH:mm', 'dd MMM yyyy HH:mm:ss', 'yyyy MMM dd HH:mm', - 'MM/dd/yyyy HH:mm', 'dd/MM/yyyy HH:mm', 'yyyy/MM/dd HH:mm:ss', 'yyyy-MM-dd HH:mm:ss', 'yyyy-MM-dd HH:mm:ss.SSS'] +export const dateFormats = ['MMM yyyy', 'MMM dd yyyy', 'MMM dd yyyy HH:mm', 'dd MMM yyyy HH:mm', 'dd MMM yyyy HH:mm:ss', + 'yyyy MMM dd HH:mm', 'MM/dd/yyyy HH:mm', 'dd/MM/yyyy HH:mm', 'MMM dd yyyy HH:mm:ss', 'yyyy/MM/dd HH:mm:ss', 'yyyy-MM-dd HH:mm:ss', + 'MMM dd yyyy HH:mm:ss.SSS', 'yyyy-MM-dd HH:mm:ss.SSS'] .map(f => simpleDateFormat(f)).concat([lastUpdateAgoDateFormat(), customDateFormat('EEE, MMMM dd, yyyy')]); +export const dateFormatsWithAuto = [autoDateFormat()].concat(dateFormats); + export const compareDateFormats = (df1: DateFormatSettings, df2: DateFormatSettings): boolean => { if (df1 === df2) { return true; @@ -360,7 +412,9 @@ export const compareDateFormats = (df1: DateFormatSettings, df2: DateFormatSetti return true; } else if (df1.custom && df2.custom) { return true; - } else if (!df1.lastUpdateAgo && !df2.lastUpdateAgo && !df1.custom && !df2.custom) { + } else if (df1.auto && df2.auto && !df1.custom && !df2.custom) { + return true; + } else if (!df1.lastUpdateAgo && !df2.lastUpdateAgo && !df1.custom && !df2.custom && !df1.auto && !df2.auto) { return df1.format === df2.format; } } @@ -372,6 +426,8 @@ export abstract class DateFormatProcessor { static fromSettings($injector: Injector, settings: DateFormatSettings): DateFormatProcessor { if (settings.lastUpdateAgo) { return new LastUpdateAgoDateFormatProcessor($injector, settings); + } else if (settings.auto && !settings.custom) { + return new AutoDateFormatProcessor($injector, settings); } else { return new SimpleDateFormatProcessor($injector, settings); } @@ -383,7 +439,7 @@ export abstract class DateFormatProcessor { protected settings: DateFormatSettings) { } - abstract update(ts: string | number | Date): string; + abstract update(ts: string | number | Date, interval?: Interval): string; } @@ -437,6 +493,91 @@ export class LastUpdateAgoDateFormatProcessor extends DateFormatProcessor { } +export class AutoDateFormatProcessor extends DateFormatProcessor { + + private datePipe: DatePipe; + private readonly autoDateFormatSettings: AutoDateFormatSettings; + + constructor(protected $injector: Injector, + protected settings: DateFormatSettings) { + super($injector, settings); + this.datePipe = $injector.get(DatePipe); + this.autoDateFormatSettings = mergeDeep({} as AutoDateFormatSettings, + defaultAutoDateFormatSettings, this.settings.autoDateFormatSettings); + } + + update(ts: string| number | Date, interval?: Interval): string { + if (ts) { + const unit = interval ? intervalToFormatTimeUnit(interval) : tsToFormatTimeUnit(ts); + const format = this.autoDateFormatSettings[unit]; + if (format) { + this.formatted = this.datePipe.transform(ts, format); + } else { + this.formatted = ' '; + } + } else { + this.formatted = ' '; + } + return this.formatted; + } +} + +const intervalToFormatTimeUnit = (interval: Interval): FormatTimeUnit => { + const intervalValue = IntervalMath.numberValue(interval); + if (intervalValue < SECOND) { + return 'millisecond'; + } else if (intervalValue < MINUTE) { + return 'second'; + } else if (intervalValue < HOUR) { + return 'minute'; + } else if (intervalValue < DAY) { + return 'hour'; + } else if (intervalValue < AVG_MONTH) { + return 'day'; + } else if (intervalValue < YEAR) { + return 'month'; + } else { + return 'year'; + } +}; + +export const tsToFormatTimeUnit = (ts: string | number | Date): FormatTimeUnit => { + const date = moment(ts); + const M = date.month() + 1; + const d = date.date(); + const h = date.hours(); + const m = date.minutes(); + const s = date.seconds(); + const S = date.milliseconds(); + const isSecond = S === 0; + const isMinute = isSecond && s === 0; + const isHour = isMinute && m === 0; + const isDay = isHour && h === 0; + const isMonth = isDay && d === 1; + const isYear = isMonth && M === 1; + if (isYear) { + return 'year'; + } + else if (isMonth) { + return 'month'; + } + else if (isDay) { + return 'day'; + } + else if (isHour) { + return 'hour'; + } + else if (isMinute) { + return 'minute'; + } + else if (isSecond) { + return 'second'; + } + else { + return 'millisecond'; + } +}; + export enum BackgroundType { image = 'image', color = 'color' diff --git a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json index 29c692ad87..a47103059e 100644 --- a/ui-ngx/src/assets/dashboard/sys_admin_home_page.json +++ b/ui-ngx/src/assets/dashboard/sys_admin_home_page.json @@ -2023,6 +2023,7 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormat": {}, "showTicks": false, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": false, @@ -2076,9 +2077,11 @@ "tooltipValueColor": "rgba(0, 0, 0, 0.76)", "tooltipShowDate": true, "tooltipDateFormat": { - "format": "MMMM dd, yyyy", + "format": null, "lastUpdateAgo": false, - "custom": true + "custom": false, + "auto": true, + "autoDateFormatSettings": {} }, "tooltipDateFont": { "family": "Roboto", @@ -2494,6 +2497,7 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormat": {}, "showTicks": false, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": false, @@ -2547,9 +2551,11 @@ "tooltipValueColor": "rgba(0, 0, 0, 0.76)", "tooltipShowDate": true, "tooltipDateFormat": { - "format": "dd MMM yyyy HH:mm:ss", + "format": null, "lastUpdateAgo": false, - "custom": false + "custom": false, + "auto": true, + "autoDateFormatSettings": {} }, "tooltipDateFont": { "family": "Roboto", diff --git a/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json b/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json index 063cb0def2..85669b8bf4 100644 --- a/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json +++ b/ui-ngx/src/assets/dashboard/tenant_admin_home_page.json @@ -671,6 +671,7 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormat": {}, "showTicks": false, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": false, @@ -724,9 +725,11 @@ "tooltipValueColor": "rgba(0, 0, 0, 0.76)", "tooltipShowDate": true, "tooltipDateFormat": { - "format": "MMMM dd, yyyy", + "format": null, "lastUpdateAgo": false, - "custom": true + "custom": false, + "auto": true, + "autoDateFormatSettings": {} }, "tooltipDateFont": { "family": "Roboto", @@ -997,6 +1000,7 @@ "lineHeight": "1" }, "tickLabelColor": "rgba(0, 0, 0, 0.54)", + "ticksFormat": {}, "showTicks": false, "ticksColor": "rgba(0, 0, 0, 0.54)", "showLine": false, @@ -1050,9 +1054,11 @@ "tooltipValueColor": "rgba(0, 0, 0, 0.76)", "tooltipShowDate": true, "tooltipDateFormat": { - "format": "MMMM dd, yyyy", + "format": null, "lastUpdateAgo": false, - "custom": true + "custom": false, + "auto": true, + "autoDateFormatSettings": {} }, "tooltipDateFont": { "family": "Roboto", 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 8f02129a80..b836c7fad9 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1025,7 +1025,16 @@ "last-update-n-ago-text": "Last update {{ agoText }}", "custom-date": "Custom date", "format": "Format", - "preview": "Preview" + "preview": "Preview", + "auto": "Auto", + "time-granularity-formats": "Time granularity formats", + "unit-year": "Years", + "unit-month": "Months", + "unit-day": "Days", + "unit-hour": "Hours", + "unit-minute": "Minutes", + "unit-second": "Seconds", + "unit-millisecond": "Milliseconds" }, "datetime": { "date-from": "Date from", @@ -6691,6 +6700,10 @@ "show-split-lines": "Show split lines", "show-split-lines-x-axis-hint": "If enabled, the vertical lines on the chart will be shown.", "show-split-lines-y-axis-hint": "If enabled, the horizontal lines on the chart will be shown.", + "ticks-interval": "Ticks interval", + "ticks-interval-hint": "Compulsively set segmentation interval for axis.", + "split-number": "Split number", + "split-number-hint": "Number of segments that the axis is split into.", "scale": "Scale", "scale-min": "min", "scale-max": "max", From 15a88a90a31c7f03efe56d60ac1d43e4350818b8 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 13 Mar 2024 20:32:24 +0200 Subject: [PATCH 349/397] UI: time series chart - fix axis intervals calculation. --- .../widget/lib/chart/time-series-chart.ts | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 8e5fc4f305..521a3ce06e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -55,7 +55,7 @@ import { measureYAxisNameWidth, toNamedData } from '@home/components/widget/lib/chart/echarts-widget.models'; -import { autoDateFormat, DateFormatProcessor } from '@shared/models/widget-settings.models'; +import { DateFormatProcessor } from '@shared/models/widget-settings.models'; import { isDefinedAndNotNull, isEqual, mergeDeep } from '@core/utils'; import { DataKey, Datasource, DatasourceType, widgetType } from '@shared/models/widget.models'; import * as echarts from 'echarts/core'; @@ -73,7 +73,7 @@ import { BarRenderSharedContext } from '@home/components/widget/lib/chart/time-s export class TbTimeSeriesChart { public static dataKeySettings(type = TimeSeriesChartType.default): DataKeySettingsFunction { - return (key, isLatestDataKey) => { + return (_key, isLatestDataKey) => { if (!isLatestDataKey) { const settings = mergeDeep({} as TimeSeriesChartKeySettings, timeSeriesChartKeyDefaultSettings); @@ -629,18 +629,6 @@ export class TbTimeSeriesChart { } } - private updateYAxisScale(axisList: TimeSeriesChartYAxis[]): boolean { - let changed = false; - for (const yAxis of axisList) { - const scaleYAxis = this.scaleYAxis(yAxis); - if (yAxis.option.scale !== scaleYAxis) { - yAxis.option.scale = scaleYAxis; - changed = true; - } - } - return changed; - } - private updateYAxisOffset(axisList: TimeSeriesChartYAxis[]): {offset: number; changed: boolean} { const result = {offset: 0, changed: false}; let width = 0; @@ -684,6 +672,21 @@ export class TbTimeSeriesChart { return result; } + private updateYAxisScale(axisList: TimeSeriesChartYAxis[]): boolean { + let changed = false; + for (const yAxis of axisList) { + const scaleYAxis = this.scaleYAxis(yAxis); + if (yAxis.option.scale !== scaleYAxis) { + yAxis.option.scale = scaleYAxis; + changed = true; + } + if (updateYAxisIntervals(this.timeSeriesChart, yAxis, this.yAxisEmpty(yAxis))) { + changed = true; + } + } + return changed; + } + private scaleYAxis(yAxis: TimeSeriesChartYAxis): boolean { const axisBarDataItems = this.dataItems.filter(d => d.yAxisId === yAxis.id && d.enabled && d.data.length && d.dataKey.settings.type === TimeSeriesChartSeriesType.bar); From c4bc1ba6bb8398f7e0c36d5fb9d3f2855b6de2d6 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 14 Mar 2024 12:32:51 +0200 Subject: [PATCH 350/397] UI: Improve time series charts ticks generation. --- ui-ngx/patches/echarts+5.5.0.patch | 141 ++++++++++++++++++ .../aggregated-value-card-widget.component.ts | 7 +- .../lib/chart/time-series-chart.models.ts | 112 +++++++------- .../widget/lib/chart/time-series-chart.ts | 29 +--- 4 files changed, 196 insertions(+), 93 deletions(-) diff --git a/ui-ngx/patches/echarts+5.5.0.patch b/ui-ngx/patches/echarts+5.5.0.patch index 39551ac137..f74beb7ea8 100644 --- a/ui-ngx/patches/echarts+5.5.0.patch +++ b/ui-ngx/patches/echarts+5.5.0.patch @@ -207,3 +207,144 @@ index b8a9b95..8e4cb2f 100644 return; } var axisValueLabel = axisPointerViewHelper.getValueLabel(axisValue, axisModel.axis, ecModel, axisItem.seriesDataIndices, axisItem.valueLabelOpt); +diff --git a/node_modules/echarts/lib/coord/axisHelper.js b/node_modules/echarts/lib/coord/axisHelper.js +index a76c66b..be22cb0 100644 +--- a/node_modules/echarts/lib/coord/axisHelper.js ++++ b/node_modules/echarts/lib/coord/axisHelper.js +@@ -187,7 +187,9 @@ export function createScaleByModel(model, axisType) { + }); + default: + // case 'value'/'interval', 'log', or others. +- return new (Scale.getClass(axisType) || IntervalScale)(); ++ return new (Scale.getClass(axisType) || IntervalScale)({ ++ ticksGenerator: model.get('ticksGenerator') ++ }); + } + } + } +diff --git a/node_modules/echarts/lib/coord/cartesian/Grid.js b/node_modules/echarts/lib/coord/cartesian/Grid.js +index 5b18f02..4960e67 100644 +--- a/node_modules/echarts/lib/coord/cartesian/Grid.js ++++ b/node_modules/echarts/lib/coord/cartesian/Grid.js +@@ -91,11 +91,11 @@ var Grid = /** @class */function () { + var scale = axis.scale; + if ( + // Only value and log axis without interval support alignTicks. +- isIntervalOrLogScale(scale) && model.get('alignTicks') && model.get('interval') == null) { ++ isIntervalOrLogScale(scale) && model.get('alignTicks') && model.get('interval') == null && model.get('ticksGenerator') == null) { + axisNeedsAlign.push(axis); + } else { + niceScaleExtent(scale, model); +- if (isIntervalOrLogScale(scale)) { ++ if (isIntervalOrLogScale(scale) && !scale.isBlank()) { + // Can only align to interval or log axis. + alignTo = axis; + } +@@ -105,10 +105,15 @@ var Grid = /** @class */function () { + // All axes has set alignTicks. Pick the first one. + // PENDING. Should we find the axis that both set interval, min, max and align to this one? + if (axisNeedsAlign.length) { +- if (!alignTo) { +- alignTo = axisNeedsAlign.pop(); +- niceScaleExtent(alignTo.scale, alignTo.model); ++ while (!alignTo && axisNeedsAlign.length) { ++ var axis = axisNeedsAlign.pop(); ++ niceScaleExtent(axis.scale, axis.model); ++ if (!axis.scale.isBlank()) { ++ alignTo = axis; ++ } + } ++ } ++ if (axisNeedsAlign.length && alignTo) { + each(axisNeedsAlign, function (axis) { + alignScaleTicks(axis.scale, axis.model, alignTo.scale); + }); +diff --git a/node_modules/echarts/lib/scale/Interval.js b/node_modules/echarts/lib/scale/Interval.js +index 1094662..8f4e07a 100644 +--- a/node_modules/echarts/lib/scale/Interval.js ++++ b/node_modules/echarts/lib/scale/Interval.js +@@ -46,12 +46,17 @@ import * as numberUtil from '../util/number.js'; + import * as formatUtil from '../util/format.js'; + import Scale from './Scale.js'; + import * as helper from './helper.js'; ++import { isFunction } from 'zrender/lib/core/util.js'; + var roundNumber = numberUtil.round; + var IntervalScale = /** @class */function (_super) { + __extends(IntervalScale, _super); +- function IntervalScale() { +- var _this = _super !== null && _super.apply(this, arguments) || this; ++ function IntervalScale(setting) { ++ var _this = _super.call(this, setting) || this; + _this.type = 'interval'; ++ var ticksGenerator = _this.getSetting('ticksGenerator'); ++ if (isFunction(ticksGenerator)) { ++ _this._ticksGenerator = ticksGenerator; ++ } + // Step is calculated in adjustExtent. + _this._interval = 0; + _this._intervalPrecision = 2; +@@ -104,7 +109,17 @@ var IntervalScale = /** @class */function (_super) { + var extent = this._extent; + var niceTickExtent = this._niceExtent; + var intervalPrecision = this._intervalPrecision; +- var ticks = []; ++ var ticksGenerator = this._ticksGenerator; ++ var ticks; ++ if (ticksGenerator) { ++ try { ++ ticks = ticksGenerator(extent, interval, niceTickExtent, intervalPrecision); ++ if (ticks) { ++ return ticks; ++ } ++ } catch (_e) {} ++ } ++ ticks = []; + // If interval is 0, return []; + if (!interval) { + return ticks; +diff --git a/node_modules/echarts/types/dist/shared.d.ts b/node_modules/echarts/types/dist/shared.d.ts +index ca74097..98f8b18 100644 +--- a/node_modules/echarts/types/dist/shared.d.ts ++++ b/node_modules/echarts/types/dist/shared.d.ts +@@ -2422,6 +2422,9 @@ interface AxisBaseOptionCommon extends ComponentOption, AnimationOptionMixin { + max: number; + }) => ScaleDataValue); + } ++ ++declare type NumericAxisTicksGenerator = (extent?: number[], interval?: number, niceTickExtent?: number[], intervalPrecision?: number) => {value: number}[]; ++ + interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon { + boundaryGap?: [number | string, number | string]; + /** +@@ -2447,6 +2450,8 @@ interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon { + * Will be ignored if interval is set. + */ + alignTicks?: boolean; ++ ++ ticksGenerator?: NumericAxisTicksGenerator; + } + interface CategoryAxisBaseOption extends AxisBaseOptionCommon { + type?: 'category'; +diff --git a/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts b/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts +index c5c2792..d524b70 100644 +--- a/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts ++++ b/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts +@@ -56,6 +56,9 @@ export interface AxisBaseOptionCommon extends ComponentOption, AnimationOptionMi + max: number; + }) => ScaleDataValue); + } ++ ++export declare type NumericAxisTicksGenerator = (extent?: number[], interval?: number, niceTickExtent?: number[], intervalPrecision?: number) => {value: number}[]; ++ + export interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon { + boundaryGap?: [number | string, number | string]; + /** +@@ -81,6 +84,8 @@ export interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon { + * Will be ignored if interval is set. + */ + alignTicks?: boolean; ++ ++ ticksGenerator?: NumericAxisTicksGenerator; + } + export interface CategoryAxisBaseOption extends AxisBaseOptionCommon { + type?: 'category'; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts index 7ed3e9c1cd..908ed263e4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/aggregated-value-card-widget.component.ts @@ -44,7 +44,6 @@ import { getDataKey, getLatestSingleTsValue, overlayStyle, - simpleDateFormat, textStyle } from '@shared/models/widget-settings.models'; import { DataKey } from '@shared/models/widget.models'; @@ -55,10 +54,9 @@ import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; import { TbTimeSeriesChart } from '@home/components/widget/lib/chart/time-series-chart'; import { - TimeSeriesChartAxisSettings, TimeSeriesChartKeySettings, TimeSeriesChartSeriesType, - TimeSeriesChartSettings, TimeSeriesChartYAxisSettings + TimeSeriesChartSettings } from '@home/components/widget/lib/chart/time-series-chart.models'; import { DeepPartial } from '@shared/models/common'; @@ -189,8 +187,7 @@ export class AggregatedValueCardWidgetComponent implements OnInit, AfterViewInit showSplitLines: true, min: 'dataMin', max: 'dataMax', - intervalCalculator: - 'var scale = axis.scale; return !scale.isBlank() ? ((scale.getExtent()[1] - scale.getExtent()[0]) / 2) : undefined;' + ticksGenerator: (extent?: number[]) => (extent ? [{ value: (extent[0] + extent[1]) / 2}] : []) } }, tooltipDateInterval: false, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index 3c2343853c..fba1a9f8e2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -19,21 +19,23 @@ import { EChartsOption, EChartsSeriesItem, EChartsTooltipTrigger, - EChartsTooltipWidgetSettings, getYAxis, + EChartsTooltipWidgetSettings, measureThresholdLabelOffset } from '@home/components/widget/lib/chart/echarts-widget.models'; import { - autoDateFormat, AutoDateFormatSettings, + autoDateFormat, + AutoDateFormatSettings, ComponentStyle, Font, - simpleDateFormat, - textStyle, tsToFormatTimeUnit + textStyle, + tsToFormatTimeUnit } from '@shared/models/widget-settings.models'; import { XAXisOption, YAXisOption } from 'echarts/types/dist/shared'; import { CustomSeriesOption, LineSeriesOption } from 'echarts/charts'; import { formatValue, isDefinedAndNotNull, + isFunction, isNumeric, isUndefined, isUndefinedOrNull, @@ -42,7 +44,6 @@ import { } from '@core/utils'; import { LinearGradientObject } from 'zrender/lib/graphic/LinearGradient'; import tinycolor from 'tinycolor2'; -import Axis2D from 'echarts/types/src/coord/cartesian/Axis2D'; import { ValueAxisBaseOption } from 'echarts/types/src/coord/axisCommonTypes'; import { SeriesLabelOption } from 'echarts/types/src/util/types'; import { @@ -320,6 +321,12 @@ export const defaultXAxisTicksFormat: AutoDateFormatSettings = { export type TimeSeriesChartYAxisId = 'default' | string; +export type TimeSeriesChartTicksGenerator = + (extent?: number[], interval?: number, niceTickExtent?: number[], intervalPrecision?: number) => {value: number}[]; + +export type TimeSeriesChartTicksFormatter = + (value: any) => string; + export interface TimeSeriesChartYAxisSettings extends TimeSeriesChartAxisSettings { id?: TimeSeriesChartYAxisId; order?: number; @@ -329,8 +336,8 @@ export interface TimeSeriesChartYAxisSettings extends TimeSeriesChartAxisSetting splitNumber?: number; min?: number | string; max?: number | string; - intervalCalculator?: string; - ticksFormatter?: string; + ticksGenerator?: TimeSeriesChartTicksGenerator | string; + ticksFormatter?: TimeSeriesChartTicksFormatter | string; } export const timeSeriesChartYAxisValid = (axis: TimeSeriesChartYAxisSettings): boolean => @@ -788,8 +795,6 @@ export interface TimeSeriesChartYAxis { decimals: number; settings: TimeSeriesChartYAxisSettings; option: YAXisOption & ValueAxisBaseOption; - intervalCalculator?: (axis: Axis2D) => number; - ticksFormatter?: (value: any) => string; } export const createTimeSeriesYAxis = (units: string, @@ -800,11 +805,37 @@ export const createTimeSeriesYAxis = (units: string, settings.tickLabelColor, darkMode, 'axis.tickLabel'); const yAxisNameStyle = createChartTextStyle(settings.labelFont, settings.labelColor, darkMode, 'axis.label'); - let ticksFormatter: (value: any) => string; - if (settings.ticksFormatter && settings.ticksFormatter.length) { - ticksFormatter = parseFunction(settings.ticksFormatter, ['value']); + + let ticksFormatter: TimeSeriesChartTicksFormatter; + if (settings.ticksFormatter) { + if (isFunction(settings.ticksFormatter)) { + ticksFormatter = settings.ticksFormatter as TimeSeriesChartTicksFormatter; + } else if (settings.ticksFormatter.length) { + ticksFormatter = parseFunction(settings.ticksFormatter, ['value']); + } + } + let ticksGenerator: TimeSeriesChartTicksGenerator; + let minInterval: number; + let interval: number; + let splitNumber: number; + if (settings.ticksGenerator) { + if (isFunction(settings.ticksGenerator)) { + ticksGenerator = settings.ticksGenerator as TimeSeriesChartTicksGenerator; + } else if (settings.ticksGenerator.length) { + ticksGenerator = parseFunction(settings.ticksGenerator, ['extent', 'interval', 'niceTickExtent', 'intervalPrecision']); + } } - const yAxis: TimeSeriesChartYAxis = { + if (!ticksGenerator) { + interval = settings.interval; + if (isUndefinedOrNull(interval)) { + if (isDefinedAndNotNull(settings.splitNumber)) { + splitNumber = settings.splitNumber; + } else { + minInterval = (1 / Math.pow(10, decimals)); + } + } + } + return { id: settings.id, decimals, settings, @@ -818,6 +849,10 @@ export const createTimeSeriesYAxis = (units: string, scale: true, min: settings.min, max: settings.max, + minInterval, + splitNumber, + interval, + ticksGenerator, name: settings.label, nameLocation: 'middle', nameRotate: settings.position === AxisPosition.left ? 90 : -90, @@ -853,7 +888,8 @@ export const createTimeSeriesYAxis = (units: string, if (ticksFormatter) { try { result = ticksFormatter(value); - } catch (_e) {} + } catch (_e) { + } } if (isUndefined(result)) { result = formatValue(value, decimals, units, false); @@ -869,54 +905,6 @@ export const createTimeSeriesYAxis = (units: string, } } }; - if (settings.intervalCalculator && settings.intervalCalculator.length) { - yAxis.intervalCalculator = parseFunction(settings.intervalCalculator, ['axis']); - } - return yAxis; -}; - -export const updateYAxisIntervals = (chart: ECharts, - yAxis: TimeSeriesChartYAxis, empty: boolean): boolean => { - let changed = false; - let interval: number; - let splitNumber: number; - let minInterval: number; - if (!empty) { - interval = calculateYAxisInterval(chart, yAxis); - if (isUndefinedOrNull(interval)) { - if (isDefinedAndNotNull(yAxis.settings.splitNumber)) { - splitNumber = yAxis.settings.splitNumber; - } else { - minInterval = (1 / Math.pow(10, yAxis.decimals)); - } - } - } - if (yAxis.option.interval !== interval) { - yAxis.option.interval = interval; - changed = true; - } - if (yAxis.option.splitNumber !== splitNumber) { - yAxis.option.splitNumber = splitNumber; - changed = true; - } - if (yAxis.option.minInterval !== minInterval) { - yAxis.option.minInterval = minInterval; - changed = true; - } - return changed; -}; - -const calculateYAxisInterval = (chart: ECharts, yAxis: TimeSeriesChartYAxis): number | undefined => { - let interval = yAxis.settings.interval; - if (yAxis.intervalCalculator) { - const axis = getYAxis(chart, yAxis.id); - if (axis) { - try { - interval = yAxis.intervalCalculator(axis); - } catch (_e) {} - } - } - return interval; }; export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartXAxisSettings, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 521a3ce06e..cbb6c2e3e0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -27,7 +27,8 @@ import { TimeSeriesChartDataItem, timeSeriesChartDefaultSettings, timeSeriesChartKeyDefaultSettings, - TimeSeriesChartKeySettings, TimeSeriesChartNoAggregationBarWidthStrategy, + TimeSeriesChartKeySettings, + TimeSeriesChartNoAggregationBarWidthStrategy, TimeSeriesChartSeriesType, TimeSeriesChartSettings, TimeSeriesChartShape, @@ -39,7 +40,7 @@ import { TimeSeriesChartYAxis, TimeSeriesChartYAxisId, TimeSeriesChartYAxisSettings, - updateDarkMode, updateYAxisIntervals + updateDarkMode } from '@home/components/widget/lib/chart/time-series-chart.models'; import { ResizeObserver } from '@juggle/resize-observer'; import { @@ -611,11 +612,6 @@ export class TbTimeSeriesChart { this.timeSeriesChartOptions.yAxis = this.yAxisList.map(axis => axis.option); this.timeSeriesChart.setOption(this.timeSeriesChartOptions, {replaceMerge: ['yAxis', 'xAxis', 'grid'], lazyUpdate: true}); } - changed = this.updateYAxesIntervals(this.yAxisList); - if (changed) { - this.timeSeriesChartOptions.yAxis = this.yAxisList.map(axis => axis.option); - this.timeSeriesChart.setOption(this.timeSeriesChartOptions, {replaceMerge: ['yAxis'], lazyUpdate: true}); - } if (this.yAxisList.length) { const extent = getAxisExtent(this.timeSeriesChart, this.yAxisList[0].id); const min = extent[0]; @@ -680,9 +676,6 @@ export class TbTimeSeriesChart { yAxis.option.scale = scaleYAxis; changed = true; } - if (updateYAxisIntervals(this.timeSeriesChart, yAxis, this.yAxisEmpty(yAxis))) { - changed = true; - } } return changed; } @@ -693,22 +686,6 @@ export class TbTimeSeriesChart { return !axisBarDataItems.length; } - private yAxisEmpty(yAxis: TimeSeriesChartYAxis): boolean { - const axisDataItems = this.dataItems.filter(d => d.yAxisId === yAxis.id && d.enabled && - d.data.length); - return !axisDataItems.length; - } - - private updateYAxesIntervals(axisList: TimeSeriesChartYAxis[]): boolean { - let changed = false; - for (const yAxis of axisList) { - if (updateYAxisIntervals(this.timeSeriesChart, yAxis, this.yAxisEmpty(yAxis))) { - changed = true; - } - } - return changed; - } - private minTopOffset(): number { const showTickLabels = !!this.yAxisList.find(yAxis => yAxis.settings.show && yAxis.settings.showTickLabels); From 43de32fe9dec01c3ca9e372990bfe34debb81603 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 14 Mar 2024 12:38:43 +0200 Subject: [PATCH 351/397] UI: Automatically close default dialogs (Alert/Confirm/Error) on route change --- .../src/app/core/services/dialog.service.ts | 37 ++++++++++--------- .../dialog/alert-dialog.component.ts | 14 +++++-- .../dialog/confirm-dialog.component.ts | 14 +++++-- .../dialog/error-alert-dialog.component.ts | 11 +++++- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/ui-ngx/src/app/core/services/dialog.service.ts b/ui-ngx/src/app/core/services/dialog.service.ts index 011a21987f..8a2de4a694 100644 --- a/ui-ngx/src/app/core/services/dialog.service.ts +++ b/ui-ngx/src/app/core/services/dialog.service.ts @@ -21,22 +21,25 @@ import { TranslateService } from '@ngx-translate/core'; import { AuthService } from '@core/auth/auth.service'; import { ColorPickerDialogComponent, - ColorPickerDialogData, ColorPickerDialogResult + ColorPickerDialogData, + ColorPickerDialogResult } from '@shared/components/dialog/color-picker-dialog.component'; import { MaterialIconsDialogComponent, - MaterialIconsDialogData, MaterialIconsDialogResult + MaterialIconsDialogData, + MaterialIconsDialogResult } from '@shared/components/dialog/material-icons-dialog.component'; -import { ConfirmDialogComponent } from '@shared/components/dialog/confirm-dialog.component'; -import { AlertDialogComponent } from '@shared/components/dialog/alert-dialog.component'; -import { ErrorAlertDialogComponent } from '@shared/components/dialog/error-alert-dialog.component'; +import { ConfirmDialogComponent, ConfirmDialogData } from '@shared/components/dialog/confirm-dialog.component'; +import { AlertDialogComponent, AlertDialogData } from '@shared/components/dialog/alert-dialog.component'; +import { + ErrorAlertDialogComponent, + ErrorAlertDialogData +} from '@shared/components/dialog/error-alert-dialog.component'; import { TodoDialogComponent } from '@shared/components/dialog/todo-dialog.component'; -@Injectable( - { - providedIn: 'root' - } -) +@Injectable({ + providedIn: 'root' +}) export class DialogService { constructor( @@ -47,7 +50,7 @@ export class DialogService { } confirm(title: string, message: string, cancel: string = null, ok: string = null, fullscreen: boolean = false): Observable { - const dialogConfig: MatDialogConfig = { + const dialogConfig: MatDialogConfig = { disableClose: true, data: { title, @@ -59,12 +62,12 @@ export class DialogService { if (fullscreen) { dialogConfig.panelClass = ['tb-fullscreen-dialog']; } - const dialogRef = this.dialog.open(ConfirmDialogComponent, dialogConfig); + const dialogRef = this.dialog.open(ConfirmDialogComponent, dialogConfig); return dialogRef.afterClosed(); } alert(title: string, message: string, ok: string = null, fullscreen: boolean = false): Observable { - const dialogConfig: MatDialogConfig = { + const dialogConfig: MatDialogConfig = { disableClose: true, data: { title, @@ -75,12 +78,12 @@ export class DialogService { if (fullscreen) { dialogConfig.panelClass = ['tb-fullscreen-dialog']; } - const dialogRef = this.dialog.open(AlertDialogComponent, dialogConfig); + const dialogRef = this.dialog.open(AlertDialogComponent, dialogConfig); return dialogRef.afterClosed(); } - errorAlert(title: string, message: string, error: any, ok: string = null, fullscreen: boolean = false): Observable { - const dialogConfig: MatDialogConfig = { + errorAlert(title: string, message: string, error: any, ok: string = null, fullscreen: boolean = false): Observable { + const dialogConfig: MatDialogConfig = { disableClose: true, data: { title, @@ -92,7 +95,7 @@ export class DialogService { if (fullscreen) { dialogConfig.panelClass = ['tb-fullscreen-dialog']; } - const dialogRef = this.dialog.open(ErrorAlertDialogComponent, dialogConfig); + const dialogRef = this.dialog.open(ErrorAlertDialogComponent, dialogConfig); return dialogRef.afterClosed(); } diff --git a/ui-ngx/src/app/shared/components/dialog/alert-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/alert-dialog.component.ts index da539bd328..c0e78cb968 100644 --- a/ui-ngx/src/app/shared/components/dialog/alert-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/alert-dialog.component.ts @@ -16,6 +16,10 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { AppState } from '@core/core.state'; +import { Router } from '@angular/router'; +import { Store } from '@ngrx/store'; export interface AlertDialogData { title: string; @@ -29,7 +33,11 @@ export interface AlertDialogData { templateUrl: './alert-dialog.component.html', styleUrls: ['./alert-dialog.component.scss'] }) -export class AlertDialogComponent { - constructor(public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: AlertDialogData) {} +export class AlertDialogComponent extends DialogComponent{ + constructor(protected store: Store, + protected router: Router, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: AlertDialogData) { + super(store, router, dialogRef); + } } diff --git a/ui-ngx/src/app/shared/components/dialog/confirm-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/confirm-dialog.component.ts index d315dad6a9..e2cf5ec7d7 100644 --- a/ui-ngx/src/app/shared/components/dialog/confirm-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/confirm-dialog.component.ts @@ -16,6 +16,10 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { AppState } from '@core/core.state'; +import { Router } from '@angular/router'; +import { Store } from '@ngrx/store'; export interface ConfirmDialogData { title: string; @@ -30,7 +34,11 @@ export interface ConfirmDialogData { templateUrl: './confirm-dialog.component.html', styleUrls: ['./confirm-dialog.component.scss'] }) -export class ConfirmDialogComponent { - constructor(public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: ConfirmDialogData) {} +export class ConfirmDialogComponent extends DialogComponent{ + constructor(protected store: Store, + protected router: Router, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: ConfirmDialogData) { + super(store, router, dialogRef); + } } diff --git a/ui-ngx/src/app/shared/components/dialog/error-alert-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/error-alert-dialog.component.ts index f8a3859b44..e1418f26ea 100644 --- a/ui-ngx/src/app/shared/components/dialog/error-alert-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/error-alert-dialog.component.ts @@ -16,6 +16,10 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { AppState } from '@core/core.state'; +import { Router } from '@angular/router'; +import { Store } from '@ngrx/store'; +import { DialogComponent } from '@shared/components/dialog.component'; export interface ErrorAlertDialogData { title: string; @@ -29,15 +33,18 @@ export interface ErrorAlertDialogData { templateUrl: './error-alert-dialog.component.html', styleUrls: ['./error-alert-dialog.component.scss'] }) -export class ErrorAlertDialogComponent { +export class ErrorAlertDialogComponent extends DialogComponent{ title: string; message: string; errorMessage: string; errorDetails?: string; - constructor(public dialogRef: MatDialogRef, + constructor(protected store: Store, + protected router: Router, + public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: ErrorAlertDialogData) { + super(store, router, dialogRef); this.title = this.data.title; this.message = this.data.message; this.errorMessage = this.data.error.message ? this.data.error.message : JSON.stringify(this.data.error); From f49e7c5c0bf2548368bbf401b93a5121b1b6f09d Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 14 Mar 2024 15:37:44 +0200 Subject: [PATCH 352/397] UI: Improved notification settings behavior --- ...otification-template-configuration.component.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html index 8297985a16..21b660010d 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html @@ -30,7 +30,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.WEB).icon }} @@ -83,7 +83,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.MOBILE_APP).icon }} @@ -148,7 +148,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.SMS).icon }} @@ -180,7 +180,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.EMAIL).icon }} @@ -210,7 +210,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.SLACK).icon }} @@ -236,7 +236,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.MICROSOFT_TEAMS).icon }} From 0fcb5aeaba60d7eafb5eb87ae0597f689b09bb00 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 14 Mar 2024 15:38:36 +0200 Subject: [PATCH 353/397] Suppress JWT token expired error in websocket handler. --- .../server/controller/plugin/TbWebSocketHandler.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java index 64536ddb54..90dea7cc31 100644 --- a/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java +++ b/application/src/main/java/org/thingsboard/server/controller/plugin/TbWebSocketHandler.java @@ -46,6 +46,7 @@ import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.cache.limits.RateLimitService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.jwt.JwtAuthenticationProvider; +import org.thingsboard.server.service.security.exception.JwtExpiredTokenException; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.subscription.SubscriptionErrorCode; @@ -232,6 +233,9 @@ public class TbWebSocketHandler extends TextWebSocketHandler implements WebSocke } catch (InvalidParameterException e) { log.warn("[{}] Failed to start session", session.getId(), e); session.close(CloseStatus.BAD_DATA.withReason(e.getMessage())); + } catch (JwtExpiredTokenException e) { + log.trace("[{}] Failed to start session", session.getId(), e); + session.close(CloseStatus.SERVER_ERROR.withReason(e.getMessage())); } catch (Exception e) { log.warn("[{}] Failed to start session", session.getId(), e); session.close(CloseStatus.SERVER_ERROR.withReason(e.getMessage())); From e58906dd7ab16025c41f2b229c78e6c79f4430c0 Mon Sep 17 00:00:00 2001 From: rusikv Date: Thu, 14 Mar 2024 17:00:13 +0200 Subject: [PATCH 354/397] UI: added sorting to 'Originator' column for alarm talbe --- .../home/models/entity/entities-table-config.models.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/models/entity/entities-table-config.models.ts b/ui-ngx/src/app/modules/home/models/entity/entities-table-config.models.ts index e1a7700d67..9dd434101d 100644 --- a/ui-ngx/src/app/modules/home/models/entity/entities-table-config.models.ts +++ b/ui-ngx/src/app/modules/home/models/entity/entities-table-config.models.ts @@ -120,8 +120,9 @@ export class EntityLinkTableColumn> extends BaseEntity public title: string, public width: string = '0px', public cellContentFunction: CellContentFunction = (entity, property) => entity[property] ? entity[property] : '', - public entityURL: (entity) => string) { - super('link', key, title, width, false); + public entityURL: (entity) => string, + public sortable: boolean = true) { + super('link', key, title, width, sortable); } } From 8ef012bfda08843d4b9701de42b559e6f5d113f6 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 15 Mar 2024 10:51:32 +0200 Subject: [PATCH 355/397] UI: Fixed expand notification delivery template when editing --- ...ation-template-configuration.component.html | 14 +++++++------- ...ication-template-configuration.component.ts | 18 +++++++++++++++++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html index 21b660010d..88d31996ca 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html @@ -30,7 +30,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.WEB).icon }} @@ -83,7 +83,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.MOBILE_APP).icon }} @@ -138,7 +138,7 @@
    @@ -148,7 +148,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.SMS).icon }} @@ -180,7 +180,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.EMAIL).icon }} @@ -210,7 +210,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.SLACK).icon }} @@ -236,7 +236,7 @@
    - + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.MICROSOFT_TEAMS).icon }} diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts index 0adb1a557f..eac2dc5a7e 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.ts @@ -66,6 +66,7 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co if (isDefinedAndNotNull(value)) { this.templateConfigurationForm.patchValue(value, {emitEvent: false}); this.updateDisabledForms(); + this.updateExpandedForm(); this.templateConfigurationForm.updateValueAndValidity(); } } @@ -96,6 +97,7 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co private propagateChange = (v: any) => { }; private readonly destroy$ = new Subject(); + private expendedBlocks: NotificationDeliveryMethod[]; constructor(private fb: FormBuilder, private translate: TranslateService) { @@ -122,6 +124,7 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co } } this.templateConfigurationForm.patchValue(settings, {emitEvent: false}); + this.updateExpandedForm(); } registerOnChange(fn: any): void { @@ -147,7 +150,7 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co }; } - get hotificationTapActionHint(): string { + get notificationTapActionHint(): string { switch (this.notificationType) { case NotificationType.ALARM: case NotificationType.ALARM_ASSIGNMENT: @@ -157,6 +160,19 @@ export class NotificationTemplateConfigurationComponent implements OnDestroy, Co return ''; } + expandedForm(name: NotificationDeliveryMethod): boolean { + return this.expendedBlocks.includes(name); + } + + private updateExpandedForm() { + this.expendedBlocks = []; + Object.keys(this.templateConfigurationForm.controls).forEach((name: NotificationDeliveryMethod) => { + if (this.templateConfigurationForm.get(name).invalid) { + this.expendedBlocks.push(name); + } + }); + } + private updateDisabledForms(){ Object.values(NotificationDeliveryMethod).forEach((method) => { const form = this.templateConfigurationForm.get(method); From 883eebe43025fa5ceaa5e8d7369b6a7995a4d67b Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 15 Mar 2024 15:28:00 +0200 Subject: [PATCH 356/397] Add APNS config for push notification in mobile phone --- .../notification/provider/DefaultFirebaseService.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java b/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java index a1a02d52f1..b64d0b586d 100644 --- a/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java +++ b/application/src/main/java/org/thingsboard/server/service/notification/provider/DefaultFirebaseService.java @@ -22,6 +22,8 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; import com.google.firebase.messaging.AndroidConfig; +import com.google.firebase.messaging.ApnsConfig; +import com.google.firebase.messaging.Aps; import com.google.firebase.messaging.FirebaseMessaging; import com.google.firebase.messaging.FirebaseMessagingException; import com.google.firebase.messaging.Message; @@ -71,6 +73,11 @@ public class DefaultFirebaseService implements FirebaseService { .setAndroidConfig(AndroidConfig.builder() .setPriority(AndroidConfig.Priority.HIGH) .build()) + .setApnsConfig(ApnsConfig.builder() + .setAps(Aps.builder() + .setContentAvailable(true) + .build()) + .build()) .putAllData(data) .build(); firebaseContext.getMessaging().send(message); From 50f89510727155aaa620492ae90f62abc449ca4a Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Fri, 15 Mar 2024 15:49:29 +0200 Subject: [PATCH 357/397] Add callback executor for device state service --- .../service/state/DefaultDeviceStateService.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java index 30c59b3da8..f1bf10e2a2 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultDeviceStateService.java @@ -191,6 +191,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService deviceStates = new ConcurrentHashMap<>(); @@ -199,6 +200,8 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService future; if (persistToTelemetry) { ListenableFuture> tsData = tsService.findLatest(TenantId.SYS_TENANT_ID, device.getId(), PERSISTENT_ATTRIBUTES); - future = Futures.transform(tsData, extractDeviceStateData(device), deviceStateExecutor); + future = Futures.transform(tsData, extractDeviceStateData(device), MoreExecutors.directExecutor()); } else { ListenableFuture> attrData = attributesService.find(TenantId.SYS_TENANT_ID, device.getId(), SERVER_SCOPE, PERSISTENT_ATTRIBUTES); - future = Futures.transform(attrData, extractDeviceStateData(device), deviceStateExecutor); + future = Futures.transform(attrData, extractDeviceStateData(device), MoreExecutors.directExecutor()); } return transformInactivityTimeout(future); } @@ -656,8 +662,8 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService Function, DeviceStateData> extractDeviceStateData(Device device) { From 53071ebaecdbc387f2471bb6eeb2e147f5e6cedf Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 15 Mar 2024 17:43:04 +0200 Subject: [PATCH 358/397] UI: Improve time series charts stack handling. Decrease default animation duration parameter to 500ms. --- .../json/system/widget_types/bar_chart.json | 2 +- .../json/system/widget_types/line_chart.json | 2 +- .../json/system/widget_types/point_chart.json | 2 +- .../widget_types/time_series_chart.json | 2 +- ui-ngx/patches/echarts+5.5.0.patch | 96 +++++++++++++++++-- .../widget/lib/chart/echarts-widget.models.ts | 3 + .../lib/chart/time-series-chart.models.ts | 30 +++--- .../widget/lib/chart/time-series-chart.ts | 18 ++-- 8 files changed, 116 insertions(+), 39 deletions(-) diff --git a/application/src/main/data/json/system/widget_types/bar_chart.json b/application/src/main/data/json/system/widget_types/bar_chart.json index b3791f53a1..264c314686 100644 --- a/application/src/main/data/json/system/widget_types/bar_chart.json +++ b/application/src/main/data/json/system/widget_types/bar_chart.json @@ -20,7 +20,7 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-time-series-chart-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":1000,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Bar chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":500,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Bar chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, "tags": [ "chart", diff --git a/application/src/main/data/json/system/widget_types/line_chart.json b/application/src/main/data/json/system/widget_types/line_chart.json index 273281e17a..f5b123231c 100644 --- a/application/src/main/data/json/system/widget_types/line_chart.json +++ b/application/src/main/data/json/system/widget_types/line_chart.json @@ -20,7 +20,7 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-time-series-chart-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"opacity\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.3409583261715494,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"decimals\":null,\"aggregationType\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":1000,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Line chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"opacity\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":true,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":false,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"emptyCircle\",\"pointSize\":4,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.3409583261715494,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"decimals\":null,\"aggregationType\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":500,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Line chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, "tags": [ "chart", diff --git a/application/src/main/data/json/system/widget_types/point_chart.json b/application/src/main/data/json/system/widget_types/point_chart.json index d692570136..beb99116c9 100644 --- a/application/src/main/data/json/system/widget_types/point_chart.json +++ b/application/src/main/data/json/system/widget_types/point_chart.json @@ -20,7 +20,7 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-time-series-chart-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":1000,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Point chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"showInLegend\":true,\"dataHiddenByDefault\":false,\"type\":\"line\",\"lineSettings\":{\"showLine\":false,\"step\":false,\"stepType\":\"start\",\"smooth\":false,\"lineType\":\"solid\",\"lineWidth\":2,\"showPoints\":true,\"showPointLabel\":false,\"pointLabelPosition\":\"top\",\"pointLabelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"pointLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"pointShape\":\"circle\",\"pointSize\":8,\"fillAreaSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}},\"barSettings\":{\"showBorder\":false,\"borderWidth\":2,\"borderRadius\":0,\"showLabel\":false,\"labelPosition\":\"top\",\"labelFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.76)\",\"backgroundSettings\":{\"type\":\"none\",\"opacity\":0.4,\"gradient\":{\"start\":100,\"end\":0}}}},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":500,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Point chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, "tags": [ "chart", diff --git a/application/src/main/data/json/system/widget_types/time_series_chart.json b/application/src/main/data/json/system/widget_types/time_series_chart.json index 1c215e21c8..9b2069ca6b 100644 --- a/application/src/main/data/json/system/widget_types/time_series_chart.json +++ b/application/src/main/data/json/system/widget_types/time_series_chart.json @@ -20,7 +20,7 @@ "latestDataKeySettingsDirective": "", "hasBasicMode": true, "basicModeDirective": "tb-time-series-chart-basic-config", - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":1000,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Time series chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#FFC107\",\"settings\":{\"type\":\"bar\"},\"_hash\":0.5534217244004682,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\",\"aggregationType\":null,\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null}],\"alarmFilterConfig\":{\"statusList\":[\"ACTIVE\"]},\"latestDataKeys\":null}],\"timewindow\":{\"hideInterval\":false,\"hideLastInterval\":false,\"hideQuickInterval\":false,\"hideAggregation\":false,\"hideAggInterval\":false,\"hideTimezone\":false,\"selectedTab\":0,\"realtime\":{\"realtimeType\":0,\"timewindowMs\":60000,\"quickInterval\":\"CURRENT_DAY\",\"interval\":1000},\"aggregation\":{\"type\":\"AVG\",\"limit\":25000},\"timezone\":null},\"showTitle\":true,\"backgroundColor\":\"rgba(0, 0, 0, 0)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"showLegend\":true,\"legendConfig\":{\"direction\":\"column\",\"position\":\"top\",\"sortDataKeys\":false,\"showMin\":false,\"showMax\":false,\"showAvg\":true,\"showTotal\":false,\"showLatest\":false},\"thresholds\":[],\"dataZoom\":true,\"stack\":false,\"yAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"xAxis\":{\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"bottom\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":10,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormat\":{},\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\"},\"legendLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"legendLabelColor\":\"rgba(0, 0, 0, 0.76)\",\"showTooltip\":true,\"tooltipTrigger\":\"axis\",\"tooltipValueFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"500\",\"lineHeight\":\"16px\"},\"tooltipValueColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipShowDate\":true,\"tooltipDateFormat\":{\"format\":null,\"lastUpdateAgo\":false,\"custom\":false,\"auto\":true,\"autoDateFormatSettings\":{}},\"tooltipDateFont\":{\"family\":\"Roboto\",\"size\":11,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"16px\"},\"tooltipDateColor\":\"rgba(0, 0, 0, 0.76)\",\"tooltipDateInterval\":true,\"tooltipBackgroundColor\":\"rgba(255, 255, 255, 0.76)\",\"tooltipBackgroundBlur\":4,\"background\":{\"type\":\"color\",\"color\":\"#fff\",\"overlay\":{\"enabled\":false,\"color\":\"rgba(255,255,255,0.72)\",\"blur\":3}},\"yAxes\":{\"default\":{\"units\":null,\"decimals\":0,\"show\":true,\"label\":\"\",\"labelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"600\",\"lineHeight\":\"1\"},\"labelColor\":\"rgba(0, 0, 0, 0.54)\",\"position\":\"left\",\"showTickLabels\":true,\"tickLabelFont\":{\"family\":\"Roboto\",\"size\":12,\"sizeUnit\":\"px\",\"style\":\"normal\",\"weight\":\"400\",\"lineHeight\":\"1\"},\"tickLabelColor\":\"rgba(0, 0, 0, 0.54)\",\"ticksFormatter\":null,\"showTicks\":true,\"ticksColor\":\"rgba(0, 0, 0, 0.54)\",\"showLine\":true,\"lineColor\":\"rgba(0, 0, 0, 0.54)\",\"showSplitLines\":true,\"splitLinesColor\":\"rgba(0, 0, 0, 0.12)\",\"id\":\"default\",\"order\":0}},\"noAggregationBarWidthSettings\":{\"strategy\":\"group\",\"groupWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000},\"barWidth\":{\"relative\":true,\"relativeWidth\":2,\"absoluteWidth\":1000}},\"animation\":{\"animation\":true,\"animationThreshold\":2000,\"animationDuration\":500,\"animationEasing\":\"cubicOut\",\"animationDelay\":0,\"animationDurationUpdate\":300,\"animationEasingUpdate\":\"cubicOut\",\"animationDelayUpdate\":0},\"padding\":\"12px\"},\"title\":\"Time series chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":null,\"mobileHeight\":null,\"configMode\":\"basic\",\"actions\":{},\"showTitleIcon\":false,\"titleIcon\":\"thermostat\",\"iconColor\":\"#1F6BDD\",\"useDashboardTimewindow\":false,\"displayTimewindow\":true,\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":\"normal\",\"lineHeight\":\"24px\"},\"titleColor\":\"rgba(0, 0, 0, 0.87)\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"widgetCss\":\"\",\"pageSize\":1024,\"units\":\"\",\"decimals\":null,\"noDataDisplayMessage\":\"\",\"timewindowStyle\":{\"showIcon\":false,\"iconSize\":\"24px\",\"icon\":null,\"iconPosition\":\"left\",\"font\":{\"size\":12,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"400\",\"style\":\"normal\",\"lineHeight\":\"16px\"},\"color\":\"rgba(0, 0, 0, 0.38)\",\"displayTypePrefix\":true},\"margin\":\"0px\",\"borderRadius\":\"0px\",\"iconSize\":\"0px\"}" }, "tags": [ "chart", diff --git a/ui-ngx/patches/echarts+5.5.0.patch b/ui-ngx/patches/echarts+5.5.0.patch index f74beb7ea8..4f1ebed81a 100644 --- a/ui-ngx/patches/echarts+5.5.0.patch +++ b/ui-ngx/patches/echarts+5.5.0.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js b/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js -index d6c05f3..d09baed 100644 +index d6c05f3..aafb0b8 100644 --- a/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js +++ b/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js @@ -362,7 +362,10 @@ var DataZoomModel = /** @class */function (_super) { @@ -28,7 +28,7 @@ index d6c05f3..d09baed 100644 } } diff --git a/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js b/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js -index 06469b2..ccfbfa6 100644 +index 06469b2..cf0b2ea 100644 --- a/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js +++ b/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js @@ -96,11 +96,14 @@ var getRangeHandlers = { @@ -52,7 +52,7 @@ index 06469b2..ccfbfa6 100644 }, pan: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e) { diff --git a/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js b/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js -index 98912e0..2e809af 100644 +index 98912e0..0cda6be 100644 --- a/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js +++ b/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js @@ -64,7 +64,7 @@ var DEFAULT_MOVE_HANDLE_SIZE = 7; @@ -147,7 +147,7 @@ index 98912e0..2e809af 100644 SliderZoomView.prototype._updateView = function (nonRealtime) { var displaybles = this._displayables; diff --git a/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js b/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js -index ce98fed..361b138 100644 +index ce98fed..e154118 100644 --- a/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js +++ b/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js @@ -90,7 +90,10 @@ var dataZoomProcessor = { @@ -175,7 +175,7 @@ index ce98fed..361b138 100644 }); ecModel.eachComponent('dataZoom', function (dataZoomModel) { diff --git a/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js b/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js -index cf8d6bc..9b30ec1 100644 +index cf8d6bc..f9b9f90 100644 --- a/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js +++ b/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js @@ -109,9 +109,12 @@ var DataZoomFeature = /** @class */function (_super) { @@ -195,7 +195,7 @@ index cf8d6bc..9b30ec1 100644 dataZoomModel && (snapshot[dataZoomModel.id] = { dataZoomId: dataZoomModel.id, diff --git a/node_modules/echarts/lib/component/tooltip/TooltipView.js b/node_modules/echarts/lib/component/tooltip/TooltipView.js -index b8a9b95..8e4cb2f 100644 +index b8a9b95..11e49c0 100644 --- a/node_modules/echarts/lib/component/tooltip/TooltipView.js +++ b/node_modules/echarts/lib/component/tooltip/TooltipView.js @@ -360,7 +360,7 @@ var TooltipView = /** @class */function (_super) { @@ -208,7 +208,7 @@ index b8a9b95..8e4cb2f 100644 } var axisValueLabel = axisPointerViewHelper.getValueLabel(axisValue, axisModel.axis, ecModel, axisItem.seriesDataIndices, axisItem.valueLabelOpt); diff --git a/node_modules/echarts/lib/coord/axisHelper.js b/node_modules/echarts/lib/coord/axisHelper.js -index a76c66b..be22cb0 100644 +index a76c66b..e5b7ee5 100644 --- a/node_modules/echarts/lib/coord/axisHelper.js +++ b/node_modules/echarts/lib/coord/axisHelper.js @@ -187,7 +187,9 @@ export function createScaleByModel(model, axisType) { @@ -223,7 +223,7 @@ index a76c66b..be22cb0 100644 } } diff --git a/node_modules/echarts/lib/coord/cartesian/Grid.js b/node_modules/echarts/lib/coord/cartesian/Grid.js -index 5b18f02..4960e67 100644 +index 5b18f02..39a57f8 100644 --- a/node_modules/echarts/lib/coord/cartesian/Grid.js +++ b/node_modules/echarts/lib/coord/cartesian/Grid.js @@ -91,11 +91,11 @@ var Grid = /** @class */function () { @@ -259,8 +259,76 @@ index 5b18f02..4960e67 100644 each(axisNeedsAlign, function (axis) { alignScaleTicks(axis.scale, axis.model, alignTo.scale); }); +diff --git a/node_modules/echarts/lib/data/SeriesData.js b/node_modules/echarts/lib/data/SeriesData.js +index 98d5ce8..1c293a6 100644 +--- a/node_modules/echarts/lib/data/SeriesData.js ++++ b/node_modules/echarts/lib/data/SeriesData.js +@@ -900,13 +900,16 @@ var SeriesData = /** @class */function () { + var dimInfo = data._dimInfos[dim]; + // Currently, only dimensions that has ordinalMeta can create inverted indices. + var ordinalMeta = dimInfo.ordinalMeta; ++ var stack = dimInfo.stack; + var store = data._store; +- if (ordinalMeta) { +- invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array(ordinalMeta.categories.length); +- // The default value of TypedArray is 0. To avoid miss +- // mapping to 0, we should set it as INDEX_NOT_FOUND. +- for (var i = 0; i < invertedIndices.length; i++) { +- invertedIndices[i] = INDEX_NOT_FOUND; ++ if (ordinalMeta || stack) { ++ invertedIndices = invertedIndicesMap[dim] = stack ? new Array(store.count()) : new CtorInt32Array(ordinalMeta.categories.length); ++ if (ordinalMeta) { ++ // The default value of TypedArray is 0. To avoid miss ++ // mapping to 0, we should set it as INDEX_NOT_FOUND. ++ for (var i = 0; i < invertedIndices.length; i++) { ++ invertedIndices[i] = INDEX_NOT_FOUND; ++ } + } + for (var i = 0; i < store.count(); i++) { + // Only support the case that all values are distinct. +diff --git a/node_modules/echarts/lib/data/Source.js b/node_modules/echarts/lib/data/Source.js +index 7dda49b..2dd2b98 100644 +--- a/node_modules/echarts/lib/data/Source.js ++++ b/node_modules/echarts/lib/data/Source.js +@@ -252,7 +252,8 @@ function normalizeDimensionsOption(dimensionsDefine) { + var item = { + name: rawItem.name, + displayName: rawItem.displayName, +- type: rawItem.type ++ type: rawItem.type, ++ stack: rawItem.stack + }; + // User can set null in dimensions. + // We don't auto specify name, otherwise a given name may +diff --git a/node_modules/echarts/lib/data/helper/createDimensions.js b/node_modules/echarts/lib/data/helper/createDimensions.js +index 00d7eb7..dd514b1 100644 +--- a/node_modules/echarts/lib/data/helper/createDimensions.js ++++ b/node_modules/echarts/lib/data/helper/createDimensions.js +@@ -110,6 +110,9 @@ source, opt) { + } + dimDefItem.type != null && (resultItem.type = dimDefItem.type); + dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName); ++ if (dimDefItem.stack) { ++ resultItem.stack = true; ++ } + var newIdx = resultList.length; + indicesMap[dimIdx] = newIdx; + resultItem.storeDimIndex = dimIdx; +diff --git a/node_modules/echarts/lib/data/helper/dataStackHelper.js b/node_modules/echarts/lib/data/helper/dataStackHelper.js +index c25de1b..ea8300d 100644 +--- a/node_modules/echarts/lib/data/helper/dataStackHelper.js ++++ b/node_modules/echarts/lib/data/helper/dataStackHelper.js +@@ -91,7 +91,7 @@ export function enableDataStack(seriesModel, dimensionsInput, opt) { + } + if (mayStack && !dimensionInfo.isExtraCoord) { + // Find the first ordinal dimension as the stackedByDimInfo. +- if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) { ++ if (!byIndex && !stackedByDimInfo && (dimensionInfo.ordinalMeta || dimensionInfo.stack)) { + stackedByDimInfo = dimensionInfo; + } + // Find the first stackable dimension as the stackedDimInfo. diff --git a/node_modules/echarts/lib/scale/Interval.js b/node_modules/echarts/lib/scale/Interval.js -index 1094662..8f4e07a 100644 +index 1094662..363c0a5 100644 --- a/node_modules/echarts/lib/scale/Interval.js +++ b/node_modules/echarts/lib/scale/Interval.js @@ -46,12 +46,17 @@ import * as numberUtil from '../util/number.js'; @@ -303,7 +371,7 @@ index 1094662..8f4e07a 100644 if (!interval) { return ticks; diff --git a/node_modules/echarts/types/dist/shared.d.ts b/node_modules/echarts/types/dist/shared.d.ts -index ca74097..98f8b18 100644 +index ca74097..ef41ce2 100644 --- a/node_modules/echarts/types/dist/shared.d.ts +++ b/node_modules/echarts/types/dist/shared.d.ts @@ -2422,6 +2422,9 @@ interface AxisBaseOptionCommon extends ComponentOption, AnimationOptionMixin { @@ -325,6 +393,14 @@ index ca74097..98f8b18 100644 } interface CategoryAxisBaseOption extends AxisBaseOptionCommon { type?: 'category'; +@@ -6412,6 +6417,7 @@ declare type DimensionDefinition = { + type?: DataStoreDimensionType; + name?: DimensionName; + displayName?: string; ++ stack?: boolean; + }; + declare type DimensionDefinitionLoose = DimensionDefinition['name'] | DimensionDefinition; + declare const SOURCE_FORMAT_ORIGINAL: "original"; diff --git a/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts b/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts index c5c2792..d524b70 100644 --- a/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts index bac5616506..7fdd1fbfff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts @@ -340,6 +340,9 @@ export const echartsTooltipFormatter = (renderer: Renderer2, return null; } const firstParam = Array.isArray(params) ? params[0] : params; + if (!firstParam.value) { + return null; + } const tooltipElement: HTMLElement = renderer.createElement('div'); renderer.setStyle(tooltipElement, 'display', 'flex'); renderer.setStyle(tooltipElement, 'flex-direction', 'column'); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index fba1a9f8e2..6f985466c4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -615,7 +615,7 @@ export const timeSeriesChartDefaultSettings: TimeSeriesChartSettings = { animation: { animation: true, animationThreshold: 2000, - animationDuration: 1000, + animationDuration: 500, animationEasing: TimeSeriesChartAnimationEasing.cubicOut, animationDelay: 0, animationDurationUpdate: 300, @@ -1023,7 +1023,7 @@ const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[], let seriesOption = item.option; if (!item.option) { const thresholdLabelStyle = createChartTextStyle(item.settings.labelFont, - item.settings.labelColor, darkMode, 'threshold.label'); + item.settings.labelColor, false, 'threshold.label'); seriesOption = { type: 'line', id: item.id, @@ -1036,7 +1036,7 @@ const generateChartThresholds = (thresholdItems: TimeSeriesChartThresholdItem[], }, lineStyle: { width: item.settings.lineWidth, - color: prepareChartThemeColor(item.settings.lineColor, darkMode, 'threshold.line'), + color: prepareChartThemeColor(item.settings.lineColor, false, 'threshold.line'), type: item.settings.lineType }, label: { @@ -1175,17 +1175,6 @@ export const updateDarkMode = (options: EChartsOption, settings: TimeSeriesChart } } } - for (const item of thresholdDataItems) { - if (Array.isArray(options.series)) { - const series = options.series.find(s => s.id === item.id); - if (series) { - series.markLine.lineStyle.color = prepareChartThemeColor(item.settings.lineColor, darkMode, 'threshold.line'); - if (series.markLine?.label?.show) { - series.markLine.label.color = prepareChartThemeColor(item.settings.labelColor, darkMode, 'threshold.label'); - } - } - } - } return options; }; @@ -1209,12 +1198,14 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem, focus: 'series' }, dimensions: [ - {name: 'intervalStart', type: 'number'}, - {name: 'intervalEnd', type: 'number'} + {name: 'x', type: 'time', stack}, + {name: 'y', type: 'float'}, + {name: 'intervalStart', type: 'time'}, + {name: 'intervalEnd', type: 'time'} ], encode: { - intervalStart: 2, - intervalEnd: 3 + x: [0, 2, 3], + y: [1] } }; item.option = seriesOption; @@ -1226,6 +1217,9 @@ const createTimeSeriesChartSeries = (item: TimeSeriesChartDataItem, lineSettings.pointLabelFont, lineSettings.pointLabelColor, lineSettings.pointLabelPosition, darkMode); lineSeriesOption.step = lineSettings.step ? lineSettings.stepType : false; lineSeriesOption.smooth = lineSettings.smooth; + if (lineSettings.smooth) { + lineSeriesOption.smoothMonotone = 'x'; + } lineSeriesOption.lineStyle = { width: lineSettings.showLine ? lineSettings.lineWidth : 0, type: lineSettings.lineType diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index cbb6c2e3e0..462825087e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -117,7 +117,7 @@ export class TbTimeSeriesChart { private darkMode = false; - private messageChannel = new BroadcastChannel('tbMessageChannel'); + private darkModeObserver: MutationObserver; private topPointLabels = false; @@ -139,7 +139,8 @@ export class TbTimeSeriesChart { this.settings = mergeDeep({} as TimeSeriesChartSettings, timeSeriesChartDefaultSettings, this.inputSettings as TimeSeriesChartSettings); - this.darkMode = this.settings.darkMode; + const dashboardPageElement = this.ctx.$containerParent.parents('.tb-dashboard-page'); + this.darkMode = this.settings.darkMode || dashboardPageElement.hasClass('dark'); this.setupYAxes(); this.setupData(); this.setupThresholds(); @@ -153,12 +154,15 @@ export class TbTimeSeriesChart { }); this.shapeResize$.observe(this.chartElement); } - this.messageChannel.addEventListener('message', (event) => { - if (event?.data?.type === 'tbDarkMode') { - const darkMode = !!event?.data?.darkMode; - this.setDarkMode(darkMode); + this.darkModeObserver = new MutationObserver(mutations => { + for(let mutation of mutations) { + if (mutation.type === 'attributes' && mutation.attributeName === 'class') { + const darkMode = dashboardPageElement.hasClass('dark'); + this.setDarkMode(darkMode); + } } }); + this.darkModeObserver.observe(dashboardPageElement[0], { attributes: true }); } public update(): void { @@ -265,7 +269,7 @@ export class TbTimeSeriesChart { } this.yMinSubject.complete(); this.yMaxSubject.complete(); - this.messageChannel.close(); + this.darkModeObserver.disconnect(); } public resize(): void { From 544c9b260c0d6b36268803e50118ef00632cdee3 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Mon, 18 Mar 2024 10:35:20 +0100 Subject: [PATCH 359/397] fixed NPE related to the entity service registry initialization --- .../server/dao/entity/BaseEntityService.java | 2 ++ .../dao/entity/DefaultEntityServiceRegistry.java | 14 +++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java index 4ee812a26b..b91e2ed96d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.entity; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.thingsboard.server.common.data.HasCustomerId; @@ -60,6 +61,7 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe private EntityQueryDao entityQueryDao; @Autowired + @Lazy EntityServiceRegistry entityServiceRegistry; @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java b/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java index 6e6233b1b2..ed0f14ad6d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java @@ -17,15 +17,12 @@ package org.thingsboard.server.dao.entity; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.ApplicationContext; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.context.event.EventListener; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; +import javax.annotation.PostConstruct; import java.util.HashMap; +import java.util.List; import java.util.Map; @Service @@ -33,14 +30,13 @@ import java.util.Map; @Slf4j public class DefaultEntityServiceRegistry implements EntityServiceRegistry { - private final ApplicationContext applicationContext; + private final List entityDaoServices; private final Map entityDaoServicesMap = new HashMap<>(); - @EventListener(ContextRefreshedEvent.class) - @Order(Ordered.HIGHEST_PRECEDENCE) + @PostConstruct public void init() { log.debug("Initializing EntityServiceRegistry on ContextRefreshedEvent"); - applicationContext.getBeansOfType(EntityDaoService.class).values().forEach(entityDaoService -> { + entityDaoServices.forEach(entityDaoService -> { EntityType entityType = entityDaoService.getEntityType(); entityDaoServicesMap.put(entityType, entityDaoService); if (EntityType.RULE_CHAIN.equals(entityType)) { From 59a2f771c6252b1e8800e24a4fcd3db21f0959b4 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 18 Mar 2024 12:20:42 +0200 Subject: [PATCH 360/397] Update UI help link --- application/src/main/resources/thingsboard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index fd006fe801..8664eaa054 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -193,7 +193,7 @@ ui: # Help parameters help: # Base URL for UI help assets - base-url: "${UI_HELP_BASE_URL:https://raw.githubusercontent.com/thingsboard/thingsboard-ui-help/release-3.6.2}" + base-url: "${UI_HELP_BASE_URL:https://raw.githubusercontent.com/thingsboard/thingsboard-ui-help/release-3.6.3}" # Database telemetry parameters database: From 5da95a15a27cf90b21a0c65c703a7ae99a9cc84f Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 18 Mar 2024 12:29:57 +0200 Subject: [PATCH 361/397] Update rule nodes UI --- .../static/rulenode/rulenode-core-config.js | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js index 7e161bb6ba..2e50246059 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -1,25 +1,25 @@ -System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/checkbox","@angular/material/input","@angular/material/form-field","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/select","@angular/material/core","@angular/material/slide-toggle","@shared/components/hint-tooltip-icon.component","@core/public-api","@shared/components/js-func.component","@angular/material/button","@angular/material/icon","@angular/material/tooltip","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/chips","@shared/pipe/safe.pipe","@shared/components/entity/entity-type-select.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","rxjs","@shared/components/help-popup.component","@shared/components/entity/entity-subtype-list.component","@shared/components/relation/relation-type-autocomplete.component","@home/components/relation/relation-filters.component","@angular/material/expansion","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,f,g,y,x,b,h,v,C,F,k,L,T,I,N,S,q,A,M,E,G,D,w,V,P,R,O,_,B,K,z,U,H,j,$,Q,J,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,fe,ge,ye,xe,be,he,ve,Ce,Fe,ke,Le,Te,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,De,we,Ve,Pe,Re,Oe,_e,Be,Ke,ze,Ue,He,je,$e,Qe,Je,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.EventEmitter,o=e.ViewChild,a=e.forwardRef,i=e.Input,l=e.InjectionToken,s=e.Injectable,m=e.Inject,p=e.Optional,d=e.Directive,u=e.Output,c=e.NgModule},function(e){f=e.RuleNodeConfigurationComponent,g=e.AttributeScope,y=e.telemetryTypeTranslations,x=e.ScriptLanguage,b=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.entitySearchDirectionTranslations,F=e.EntityType,k=e.entityFields,L=e.PageComponent,T=e.messageTypeNames,I=e.MessageType,N=e.coerceBoolean,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,D=e.NotificationType,w=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,U=e.FormGroup},function(e){H=e,j=e.DOCUMENT,$=e.CommonModule},function(e){Q=e},function(e){J=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e.getCurrentAuthState,oe=e,ae=e.isDefinedAndNotNull,ie=e.isEqual,le=e.deepTrim,se=e.isObject,me=e.isNotEmptyStr},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e},function(e){fe=e},function(e){ge=e.ENTER,ye=e.COMMA,xe=e.SEMICOLON},function(e){be=e},function(e){he=e},function(e){ve=e},function(e){Ce=e},function(e){Fe=e},function(e){ke=e},function(e){Le=e.coerceBooleanProperty,Te=e.coerceElement,Ie=e.coerceNumberProperty},function(e){Ne=e},function(e){Se=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e.tap,Ee=e.map,Ge=e.startWith,De=e.mergeMap,we=e.share,Ve=e.takeUntil,Pe=e.auditTime},function(e){Re=e},function(e){Oe=e},function(e){_e=e.HomeComponentsModule},function(e){Be=e.__decorate},function(e){Ke=e.Subject,ze=e.takeUntil,Ue=e.of,He=e.EMPTY,je=e.fromEvent},function(e){$e=e},function(e){Qe=e},function(e){Je=e},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
    ",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
    "}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ct extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===g.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ct),ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ct,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ft extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===x.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===x.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",ft),ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ft,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gt extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.alarmSeverities=Object.keys(b),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[ge,ye,xe],this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==x.TBEL||this.tbelEnabled||(r=x.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===x.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===x.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",gt),gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),gt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gt,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class yt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["entityType"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==F.DEVICE&&t!==F.ASSET?this.createRelationConfigForm.get("entityTypePattern").setValidators([]):this.createRelationConfigForm.get("entityTypePattern").setValidators([O.required,O.pattern(/.*\S.*/)]),this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",yt),yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yt,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bt extends f{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,O.required],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart,O.required]})}}e("DeviceProfileConfigComponent",bt),bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n',dependencies:[{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ht extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}var vt;e("GeneratorConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(vt||(vt={}));const Ct=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer"],[vt.TENANT,"tb.rulenode.originator-tenant"],[vt.RELATED,"tb.rulenode.originator-related"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[vt.ENTITY,"tb.rulenode.originator-entity"]]),Ft=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer-desc"],[vt.TENANT,"tb.rulenode.originator-tenant-desc"],[vt.RELATED,"tb.rulenode.originator-related-entity-desc"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[vt.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),kt=[k.createdTime,k.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},k.firstName,k.lastName,k.email,k.title,k.country,k.state,k.city,k.address,k.address2,k.zip,k.phone,k.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],Lt=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 Tt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Tt||(Tt={}));const It=new Map([[Tt.CIRCLE,"tb.rulenode.perimeter-circle"],[Tt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Nt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Nt||(Nt={}));const St=new Map([[Nt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Nt.SECONDS,"tb.rulenode.time-unit-seconds"],[Nt.MINUTES,"tb.rulenode.time-unit-minutes"],[Nt.HOURS,"tb.rulenode.time-unit-hours"],[Nt.DAYS,"tb.rulenode.time-unit-days"]]);var qt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(qt||(qt={}));const At=new Map([[qt.METER,"tb.rulenode.range-unit-meter"],[qt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[qt.FOOT,"tb.rulenode.range-unit-foot"],[qt.MILE,"tb.rulenode.range-unit-mile"],[qt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Mt;!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"}(Mt||(Mt={}));const Et=new Map([[Mt.ID,"tb.rulenode.entity-details-id"],[Mt.TITLE,"tb.rulenode.entity-details-title"],[Mt.COUNTRY,"tb.rulenode.entity-details-country"],[Mt.STATE,"tb.rulenode.entity-details-state"],[Mt.CITY,"tb.rulenode.entity-details-city"],[Mt.ZIP,"tb.rulenode.entity-details-zip"],[Mt.ADDRESS,"tb.rulenode.entity-details-address"],[Mt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Mt.PHONE,"tb.rulenode.entity-details-phone"],[Mt.EMAIL,"tb.rulenode.entity-details-email"],[Mt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Gt;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Gt||(Gt={}));const Dt=new Map([[Gt.FIRST,"tb.rulenode.first"],[Gt.LAST,"tb.rulenode.last"],[Gt.ALL,"tb.rulenode.all"]]),wt=new Map([[Gt.FIRST,"tb.rulenode.first-mode-hint"],[Gt.LAST,"tb.rulenode.last-mode-hint"],[Gt.ALL,"tb.rulenode.all-mode-hint"]]);var Vt,Pt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Vt||(Vt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(Pt||(Pt={}));const Rt=new Map([[Pt.ATTRIBUTES,"tb.rulenode.attributes"],[Pt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[Pt.FIELDS,"tb.rulenode.fields"]]),Ot=new Map([[Pt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[Pt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[Pt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),_t=new Map([[Vt.ASC,"tb.rulenode.ascending"],[Vt.DESC,"tb.rulenode.descending"]]);var Bt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Bt||(Bt={}));const Kt=new Map([[Bt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Bt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),zt=["anonymous","basic","cert.PEM"],Ut=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Ht=["sas","cert.PEM"],jt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var $t;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}($t||($t={}));const Qt=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],Jt=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 Yt;!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"}(Yt||(Yt={}));const Wt=new Map([[Yt.CUSTOM,{value:Yt.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[Yt.ADD,{value:Yt.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[Yt.SUB,{value:Yt.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[Yt.MULT,{value:Yt.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[Yt.DIV,{value:Yt.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[Yt.SIN,{value:Yt.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.SINH,{value:Yt.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[Yt.COS,{value:Yt.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.COSH,{value:Yt.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[Yt.TAN,{value:Yt.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[Yt.TANH,{value:Yt.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ACOS,{value:Yt.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[Yt.ASIN,{value:Yt.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN,{value:Yt.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN2,{value:Yt.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}],[Yt.EXP,{value:Yt.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[Yt.EXPM1,{value:Yt.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[Yt.SQRT,{value:Yt.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[Yt.CBRT,{value:Yt.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[Yt.GET_EXP,{value:Yt.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[Yt.HYPOT,{value:Yt.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[Yt.LOG,{value:Yt.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG10,{value:Yt.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG1P,{value:Yt.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[Yt.CEIL,{value:Yt.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR,{value:Yt.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR_DIV,{value:Yt.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[Yt.FLOOR_MOD,{value:Yt.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[Yt.ABS,{value:Yt.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[Yt.MIN,{value:Yt.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[Yt.MAX,{value:Yt.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[Yt.POW,{value:Yt.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}],[Yt.SIGNUM,{value:Yt.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[Yt.RAD,{value:Yt.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[Yt.DEG,{value:Yt.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var Zt,Xt,en;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(Zt||(Zt={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(Xt||(Xt={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(en||(en={}));const tn=new Map([[en.DATA,"tb.rulenode.message-to-metadata"],[en.METADATA,"tb.rulenode.metadata-to-message"]]),nn=(new Map([[en.DATA,"tb.rulenode.from-message"],[en.METADATA,"tb.rulenode.from-metadata"]]),new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.metadata"]])),rn=new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.message-metadata"]]),on=new Map([[Zt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[Zt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[Zt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[Zt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[Zt.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),an=new Map([[Xt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[Xt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[Xt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[Xt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),ln=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var sn,mn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(sn||(sn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(mn||(mn={}));const pn=new Map([[sn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[sn.SERVER_SCOPE,"tb.rulenode.server-scope"],[sn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var dn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(dn||(dn={}));const un=new Map([[dn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[dn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.keys(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.keys(qt),this.rangeUnitTranslationMap=At,this.presenceMonitoringStrategies=un,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Nt),this.timeUnitsTranslationMap=St,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[O.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",cn),cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n
    \n
    \n
    {{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
    \n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
    \n
    {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
    \n
    \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n
    \n
    \n
    {{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
    \n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
    \n
    {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
    \n
    \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fn extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",fn),fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",gn),gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",yn),yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",xn),xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",bn),bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:a((()=>Cn)),multi:!0},{provide:K,useExisting:a((()=>Cn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Se.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:a((()=>Cn)),multi:!0},{provide:K,useExisting:a((()=>Cn)),multi:!0}],template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],required:[{type:i}]}});class Fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ln extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:o,args:["attributeChipList"]}]}});class In extends L{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=Wt,this.ArgumentType=Zt,this.attributeScopeMap=pn,this.argumentTypeMap=on,this.arguments=Object.values(Zt),this.attributeScope=Object.values(sn),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===Yt.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===Zt.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==Zt.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(ln[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:a((()=>In)),multi:!0},{provide:K,useExisting:a((()=>In)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:qe.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:qe.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Ae.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Ae.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Ae.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Se.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:a((()=>In)),multi:!0},{provide:K,useExisting:a((()=>In)),multi:!0}],template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],function:[{type:i}]}});class Nn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(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=[...Wt.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(Me((e=>{let t;t="string"==typeof e&&Yt[e]?Yt[e]:null,this.updateView(t)})),Ee((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=Wt.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Nn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Re.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Re.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Oe.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:a((()=>Nn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:i}],disabled:[{type:i}],operationInput:[{type:o,args:["operationInput",{static:!0}]}]}});class Sn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=Yt,this.ArgumentTypeResult=Xt,this.argumentTypeResultMap=an,this.attributeScopeMap=pn,this.argumentsResult=Object.values(Xt),this.attributeScopeResult=Object.values(mn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===Yt.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===Xt.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:In,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:Nn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class qn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=T,this.eventOptions=[I.CONNECT_EVENT,I.ACTIVITY_EVENT,I.DISCONNECT_EVENT,I.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:ae(e?.event)?e.event:I.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[O.required]]})}}e("DeviceStateConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-action-node-device-state-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-action-node-device-state-config",template:'
    \n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class An{constructor(){this.textAlign="left"}}e("ExampleHintComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:i}],popupHelpLink:[{type:i}],textAlign:[{type:i}]}});class Mn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new Ke,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ie(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(ze(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0},{provide:K,useExisting:a((()=>Mn)),multi:!0}],ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([N()],Mn.prototype,"disabled",void 0),Be([N()],Mn.prototype,"uniqueKeyValuePairValidator",void 0),Be([N()],Mn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0},{provide:K,useExisting:a((()=>Mn)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class En extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.entityType=F,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>En)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Qe.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:Je.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:a((()=>En)),multi:!0}],template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Gn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Gn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Ye.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:a((()=>Gn)),multi:!0}],template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Dn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(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=[ge,ye,xe],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(I))this.messageTypesList.push({name:T.get(I[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Ge(""),Ee((e=>e||"")),De((e=>this.fetchMessageTypes(e))),we())}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 Ue(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return Ue(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Dn)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Re.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Re.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:Re.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Oe.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:a((()=>Dn)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],label:[{type:i}],placeholder:[{type:i}],disabled:[{type:i}],chipList:[{type:o,args:["chipList",{static:!1}]}],matAutocomplete:[{type:o,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:o,args:["messageTypeInput",{static:!1}]}]}});class wn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=zt,this.credentialsTypeTranslationsMap=Ut,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){ae(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",wn),wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:a((()=>wn)),multi:!0},{provide:K,useExisting:a((()=>wn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:We.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:We.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:a((()=>wn)),multi:!0},{provide:K,useExisting:a((()=>wn)),multi:!0}],template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],disableCertPemCredentials:[{type:i}],passwordFieldRequired:[{type:i}]}});const Vn=new l("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class Pn{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new Ke,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,deps:[{token:t.NgZone},{token:j},{token:Vn,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),Pn.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:m,args:[j]}]},{type:void 0,decorators:[{type:p},{type:m,args:[Vn]}]}]}});class Rn{constructor(e,t,n,o){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=o,this.cbOnSuccess=new r,this.cbOnError=new r,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Rn,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:Pn}],target:t.ɵɵFactoryTarget.Directive}),Rn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:Rn,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Rn,decorators:[{type:d,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:Pn}]},propDecorators:{targetElm:[{type:i,args:["ngxClipboard"]}],container:[{type:i}],cbContent:[{type:i}],cbSuccessMsg:[{type:i}],cbOnSuccess:[{type:u}],cbOnError:[{type:u}]}});class On{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,deps:[{token:Pn},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),On.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:On,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,decorators:[{type:d,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:Pn},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class _n{}_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,deps:[],target:t.ɵɵFactoryTarget.NgModule}),_n.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,declarations:[Rn,On],imports:[$],exports:[Rn,On]}),_n.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,decorators:[{type:c,args:[{imports:[$],declarations:[Rn,On],exports:[Rn,On]}]}]});class Bn{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 Ke,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(ze(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(ze(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0},{provide:K,useExisting:a((()=>Bn)),multi:!0}],ngImport:t,template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Rn,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([N()],Bn.prototype,"disabled",void 0),Be([N()],Bn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0},{provide:K,useExisting:a((()=>Bn)),multi:!0}],template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:i}],disabled:[{type:i}],required:[{type:i}]}});class Kn{constructor(e,t){this.fb=e,this.translate=t,this.translation=nn,this.propagateChange=()=>{},this.destroy$=new Ke,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0}],ngImport:t,template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0}],template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:i}],translation:[{type:i}]}});class zn extends L{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new Ke,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ie(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(Ve(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)ae(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(Ve(this.destroy$)).subscribe((t=>{const n=Lt.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>zn)),multi:!0},{provide:K,useExisting:a((()=>zn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Se.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([N()],zn.prototype,"disabled",void 0),Be([N()],zn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0},{provide:K,useExisting:a((()=>zn)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:i}],disabled:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],targetKeyPrefix:[{type:i}],selectText:[{type:i}],selectRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class Un extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Un)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ye.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:a((()=>Un)),multi:!0}],template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Hn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new Ke,this.separatorKeysCodes=[ge,ye,xe],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||ae(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:a((()=>Hn)),multi:!0},{provide:K,useExisting:Hn,multi:!0}],ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:a((()=>Hn)),multi:!0},{provide:K,useExisting:Hn,multi:!0}],template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:i}]}});class jn extends L{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new Ke,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>jn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>jn)),multi:!0}],template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class $n{}e("RulenodeCoreConfigCommonModule",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[],target:t.ɵɵFactoryTarget.NgModule}),$n.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$n,declarations:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An],imports:[$,M,_e],exports:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An]}),$n.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,imports:[$,M,_e]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:c,args:[{declarations:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An],imports:[$,M,_e],exports:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An]}]}]});class Qn{}e("RuleNodeCoreConfigActionModule",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Qn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Qn,declarations:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn],imports:[$,M,_e,$n],exports:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn]}),Qn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,imports:[$,M,_e,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:c,args:[{declarations:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn],imports:[$,M,_e,$n],exports:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn]}]}]});class Jn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]]})}prepareInputConfig(e){return{inputValueKey:ae(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:ae(e?.outputValueKey)?e.outputValueKey:null,useCache:!ae(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!ae(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:ae(e?.periodValueKey)?e.periodValueKey:null,round:ae(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!ae(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative}}prepareOutputConfig(e){return le(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Yn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.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,le(e)}prepareInputConfig(e){let t,n;return t=ae(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ae(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ae(e?.attrMapping)?e.attrMapping:ae(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Wn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return se(e)&&(e.attributesControl={clientAttributeNames:ae(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ae(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ae(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ae(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ae(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:ae(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!ae(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:En,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Zn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Mt))this.predefinedValues.push({value:Mt[e],name:this.translate.instant(Et.get(Mt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=ae(e?.addToMetadata)?e.addToMetadata?en.METADATA:en.DATA:e?.fetchTo?e.fetchTo:en.DATA,{detailsList:ae(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Xn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Gt,this.samplingOrders=Object.values(Vt),this.samplingOrdersTranslate=_t,this.timeUnits=Object.values(Nt),this.timeUnitsTranslationMap=St,this.deduplicationStrategiesHintTranslations=wt,this.headerOptions=[],this.timeUnitMap={[Nt.MILLISECONDS]:1,[Nt.SECONDS]:1e3,[Nt.MINUTES]:6e4,[Nt.HOURS]:36e5,[Nt.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 Dt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Dt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,le(e)}prepareInputConfig(e){return se(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:ae(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:ae(e?.aggregation)?e.aggregation:E.NONE,fetchMode:ae(e?.fetchMode)?e.fetchMode:Gt.FIRST,orderBy:ae(e?.orderBy)?e.orderBy:Vt.ASC,limit:ae(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!ae(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:ae(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:ae(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Nt.MINUTES,endInterval:ae(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:ae(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Nt.MINUTES},startIntervalPattern:ae(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:ae(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Gt.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Gt.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class er extends f{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 se(e)&&(e.attributesControl={clientAttributeNames:ae(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ae(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ae(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ae(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ae(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA,tellFailureIfAbsent:!!ae(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:ae(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class tr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of kt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return le(e)}prepareInputConfig(e){return{dataMapping:ae(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:ae(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:zn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class nr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=Pt,this.msgMetadataLabelTranslations=Ot,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(kt))this.originatorFields.push({value:kt[e].value,name:this.translate.instant(kt[e].name)});for(const e of Rt.keys())this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===Pt.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,le(e)}prepareInputConfig(e){let t,n,r={[k.name.value]:`relatedEntity${this.translate.instant(k.name.name)}`},o={serialNumber:"sn"};return t=ae(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ae(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ae(e?.attrMapping)?e.attrMapping:ae(e?.dataMapping)?e.dataMapping:null,t===Pt.FIELDS?r=n:o=n,{relationsQuery:ae(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Gn,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:zn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class rr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=ae(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ae(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ae(e?.attrMapping)?e.attrMapping:ae(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class or extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class ar{}e("RulenodeCoreConfigEnrichmentModule",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[],target:t.ɵɵFactoryTarget.NgModule}),ar.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:ar,declarations:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or],imports:[$,M,$n],exports:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or]}),ar.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:c,args:[{declarations:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or],imports:[$,M,$n],exports:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or]}]}]});class ir extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Ht,this.azureIotHubCredentialsTypeTranslationsMap=jt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ir,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:We.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:We.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=Qt,this.ToByteStandartCharsetTypeTranslationMap=Jt}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&me(e.clientId))},[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){me(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:wn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=D,this.entityType=F}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
    \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class dr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys($t)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],useRedisQueueForMsgPersistence:[!!e&&e.useRedisQueueForMsgPersistence,[]],trimQueue:[!!e&&e.trimQueue,[]],maxQueueSize:[e?e.maxQueueSize:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","useRedisQueueForMsgPersistence","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("useRedisQueueForMsgPersistence").value,r=this.restApiCallConfigForm.get("enableProxy").value,o=this.restApiCallConfigForm.get("useSystemProxyProperties").value;r&&!o?(this.restApiCallConfigForm.get("proxyHost").setValidators(r?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(r?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),n?this.restApiCallConfigForm.get("maxQueueSize").setValidators([O.min(0)]):this.restApiCallConfigForm.get("maxQueueSize").setValidators([]),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("maxQueueSize").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:wn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(w),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class yr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Bt,this.sqsQueueTypes=Object.keys(Bt),this.sqsQueueTypeTranslationsMap=Kt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class br{}e("RulenodeCoreConfigExternalModule",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[],target:t.ɵɵFactoryTarget.NgModule}),br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:br,declarations:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr],imports:[$,M,_e,$n],exports:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr]}),br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,imports:[$,M,_e,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:c,args:[{declarations:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr],imports:[$,M,_e,$n],exports:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr]}]}]});class hr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ae(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:jn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class vr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ae(e?.messageNames)?e.messageNames:[],metadataNames:ae(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!ae(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:ae(e?.messageNames)?e.messageNames:[],metadataNames:ae(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=C}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ae(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ae(e?.direction)?e.direction:null,entityType:ae(e?.entityType)?e.entityType:null,entityId:ae(e?.entityId)?e.entityId:null,relationType:ae(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Je.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.values(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.values(qt),this.rangeUnitTranslationMap=At,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ae(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ae(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ae(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ae(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ae(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ae(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ae(e?.centerLongitude)?e.centerLongitude:null,range:ae(e?.range)?e.range:null,rangeUnit:ae(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ae(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class kr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ae(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Dn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.TENANT,F.CUSTOMER,F.USER,F.DASHBOARD,F.RULE_CHAIN,F.RULE_NODE,F.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ae(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ae(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ae(e?.jsScript)?e.jsScript:null,tbelScript:ae(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Ir extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ae(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ae(e?.jsScript)?e.jsScript:null,tbelScript:ae(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Nr{}e("RuleNodeCoreConfigFilterModule",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Nr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Nr,declarations:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr],imports:[$,M,$n],exports:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr]}),Nr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:c,args:[{declarations:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr],imports:[$,M,$n],exports:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr]}]}]});class Sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=vt,this.originatorSources=Object.keys(vt),this.originatorSourceTranslationMap=Ct,this.originatorSourceDescTranslationMap=Ft,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.USER,F.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===vt.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===vt.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:qe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:qe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Gn,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class qr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",qr),qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,deps:[{token:P.Store},{token:R.FormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),qr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qr,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - const Ar=mt({passive:!0});class Mr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return He;const t=Te(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new Ke,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Ar),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Ar)}}),r}stopMonitoring(e){const t=Te(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Mr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class Er{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new r}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}Er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Er,deps:[{token:t.ElementRef},{token:Mr}],target:t.ɵɵFactoryTarget.Directive}),Er.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Er,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Er,decorators:[{type:d,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Mr}]},propDecorators:{cdkAutofill:[{type:u}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Gr{get minRows(){return this._minRows}set minRows(e){this._minRows=Ie(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=Ie(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Le(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new Ke,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();je(e,"resize").pipe(Pe(16),Ve(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Gr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Gr,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:d,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:p},{type:m,args:[j]}]}]},propDecorators:{minRows:[{type:i,args:["cdkAutosizeMinRows"]}],maxRows:[{type:i,args:["cdkAutosizeMaxRows"]}],enabled:[{type:i,args:["cdkTextareaAutosize"]}],placeholder:[{type:i}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Dr{}Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Dr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,declarations:[Er,Gr],exports:[Er,Gr]}),Dr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,decorators:[{type:c,args:[{declarations:[Er,Gr],exports:[Er,Gr]}]}]});class wr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:ae(e?.fromTemplate)?e.fromTemplate:null,toTemplate:ae(e?.toTemplate)?e.toTemplate:null,ccTemplate:ae(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:ae(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:ae(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:ae(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:ae(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:ae(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",wr),wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),wr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Gr,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:qe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:qe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Vr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=tn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=ae(e?.fromMetadata)?e.copyFrom?en.METADATA:en.DATA:ae(e?.copyFrom)?e.copyFrom:en.DATA,{keys:ae(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Vr),Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Pr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=rn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=ae(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ae(e?.renameIn)?e?.renameIn:en.DATA,{renameKeysMapping:ae(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Rr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Or extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=nn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=ae(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ae(e?.deleteFrom)?e?.deleteFrom:en.DATA,{keys:ae(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class _r extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Gt,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Dt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[ae(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[ae(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[ae(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[ae(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[ae(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Bn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Br{}e("RulenodeCoreConfigTransformModule",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Br,declarations:[Sr,qr,wr,Vr,Pr,Rr,Or,_r],imports:[$,M,$n],exports:[Sr,qr,wr,Vr,Pr,Rr,Or,_r]}),Br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:c,args:[{declarations:[Sr,qr,wr,Vr,Pr,Rr,Or,_r],imports:[$,M,$n],exports:[Sr,qr,wr,Vr,Pr,Rr,Or,_r]}]}]});class Kr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=F}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class zr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),zr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zr,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ur{}e("RuleNodeCoreConfigFlowModule",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Ur.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Ur,declarations:[Kr,zr],imports:[$,M,$n],exports:[Kr,zr]}),Ur.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:c,args:[{declarations:[Kr,zr],imports:[$,M,$n],exports:[Kr,zr]}]}]});class Hr{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 not exists","create-entity-if-not-exists-hint":"Create a new entity set above if it does not exist.","select-device-connectivity-event":"Select device connectivity event","entity-name-pattern":"Name pattern","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 name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","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","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":"Timeseries keys","timeseries-keys-required":"At least one timeseries key should be selected.","add-timeseries-key":"Add timeseries key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-to-specific-entity":"Delete relation to specific entity","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"use-redis-queue":"Use redis queue for message persistence","ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","trim-redis-queue":"Trim redis queue","redis-queue-max-size":"Redis queue max size","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.","persist-alarm-rules":"Persist state of alarm rules","fetch-alarm-rules":"Fetch state of alarm rules","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","use-server-ts":"Use server ts","use-server-ts-hint":"Enable this setting to use the timestamp of the 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.","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":"timeseries 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 timeseries from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch timeseries 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 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."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",Hr),Hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),Hr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Hr,declarations:[dt],imports:[$,M],exports:[Qn,Nr,ar,br,Br,Ur,dt]}),Hr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,imports:[$,M,Qn,Nr,ar,br,Br,Ur]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,decorators:[{type:c,args:[{declarations:[dt],imports:[$,M],exports:[Qn,Nr,ar,br,Br,Ur,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map +System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/checkbox","@angular/material/input","@angular/material/form-field","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/select","@angular/material/core","@angular/material/slide-toggle","@shared/components/hint-tooltip-icon.component","@core/public-api","@shared/components/js-func.component","@angular/material/button","@angular/material/icon","@angular/material/tooltip","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/chips","@shared/pipe/safe.pipe","@shared/components/entity/entity-type-select.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","rxjs","@shared/components/help-popup.component","@shared/components/entity/entity-subtype-list.component","@shared/components/relation/relation-type-autocomplete.component","@home/components/relation/relation-filters.component","@angular/material/expansion","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,f,g,y,x,b,h,v,C,F,k,L,T,I,N,S,q,A,M,E,G,D,w,V,P,R,O,_,B,K,z,U,H,j,$,Q,J,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,fe,ge,ye,xe,be,he,ve,Ce,Fe,ke,Le,Te,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,De,we,Ve,Pe,Re,Oe,_e,Be,Ke,ze,Ue,He,je,$e,Qe,Je,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.EventEmitter,o=e.ViewChild,a=e.forwardRef,i=e.Input,l=e.InjectionToken,s=e.Injectable,m=e.Inject,p=e.Optional,d=e.Directive,u=e.Output,c=e.NgModule},function(e){f=e.RuleNodeConfigurationComponent,g=e.AttributeScope,y=e.telemetryTypeTranslations,x=e.ScriptLanguage,b=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.entitySearchDirectionTranslations,F=e.EntityType,k=e.entityFields,L=e.PageComponent,T=e.messageTypeNames,I=e.MessageType,N=e.coerceBoolean,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,D=e.NotificationType,w=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,U=e.FormGroup},function(e){H=e,j=e.DOCUMENT,$=e.CommonModule},function(e){Q=e},function(e){J=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e.getCurrentAuthState,oe=e,ae=e.isDefinedAndNotNull,ie=e.isEqual,le=e.deepTrim,se=e.isObject,me=e.isNotEmptyStr},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e},function(e){fe=e},function(e){ge=e.ENTER,ye=e.COMMA,xe=e.SEMICOLON},function(e){be=e},function(e){he=e},function(e){ve=e},function(e){Ce=e},function(e){Fe=e},function(e){ke=e},function(e){Le=e.coerceBooleanProperty,Te=e.coerceElement,Ie=e.coerceNumberProperty},function(e){Ne=e},function(e){Se=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e.tap,Ee=e.map,Ge=e.startWith,De=e.mergeMap,we=e.share,Ve=e.takeUntil,Pe=e.auditTime},function(e){Re=e},function(e){Oe=e},function(e){_e=e.HomeComponentsModule},function(e){Be=e.__decorate},function(e){Ke=e.Subject,ze=e.takeUntil,Ue=e.of,He=e.EMPTY,je=e.fromEvent},function(e){$e=e},function(e){Qe=e},function(e){Je=e},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
    ",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
    "}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ct extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===g.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ct),ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ct,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ft extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===x.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===x.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",ft),ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ft,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gt extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.alarmSeverities=Object.keys(b),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[ge,ye,xe],this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==x.TBEL||this.tbelEnabled||(r=x.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===x.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===x.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",gt),gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),gt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gt,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class yt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["entityType"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==F.DEVICE&&t!==F.ASSET?this.createRelationConfigForm.get("entityTypePattern").setValidators([]):this.createRelationConfigForm.get("entityTypePattern").setValidators([O.required,O.pattern(/.*\S.*/)]),this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",yt),yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yt,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bt extends f{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,O.required],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart,O.required]})}}e("DeviceProfileConfigComponent",bt),bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n',dependencies:[{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ht extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}var vt;e("GeneratorConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(vt||(vt={}));const Ct=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer"],[vt.TENANT,"tb.rulenode.originator-tenant"],[vt.RELATED,"tb.rulenode.originator-related"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[vt.ENTITY,"tb.rulenode.originator-entity"]]),Ft=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer-desc"],[vt.TENANT,"tb.rulenode.originator-tenant-desc"],[vt.RELATED,"tb.rulenode.originator-related-entity-desc"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[vt.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),kt=[k.createdTime,k.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},k.firstName,k.lastName,k.email,k.title,k.country,k.state,k.city,k.address,k.address2,k.zip,k.phone,k.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],Lt=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 Tt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Tt||(Tt={}));const It=new Map([[Tt.CIRCLE,"tb.rulenode.perimeter-circle"],[Tt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Nt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Nt||(Nt={}));const St=new Map([[Nt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Nt.SECONDS,"tb.rulenode.time-unit-seconds"],[Nt.MINUTES,"tb.rulenode.time-unit-minutes"],[Nt.HOURS,"tb.rulenode.time-unit-hours"],[Nt.DAYS,"tb.rulenode.time-unit-days"]]);var qt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(qt||(qt={}));const At=new Map([[qt.METER,"tb.rulenode.range-unit-meter"],[qt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[qt.FOOT,"tb.rulenode.range-unit-foot"],[qt.MILE,"tb.rulenode.range-unit-mile"],[qt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Mt;!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"}(Mt||(Mt={}));const Et=new Map([[Mt.ID,"tb.rulenode.entity-details-id"],[Mt.TITLE,"tb.rulenode.entity-details-title"],[Mt.COUNTRY,"tb.rulenode.entity-details-country"],[Mt.STATE,"tb.rulenode.entity-details-state"],[Mt.CITY,"tb.rulenode.entity-details-city"],[Mt.ZIP,"tb.rulenode.entity-details-zip"],[Mt.ADDRESS,"tb.rulenode.entity-details-address"],[Mt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Mt.PHONE,"tb.rulenode.entity-details-phone"],[Mt.EMAIL,"tb.rulenode.entity-details-email"],[Mt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Gt;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Gt||(Gt={}));const Dt=new Map([[Gt.FIRST,"tb.rulenode.first"],[Gt.LAST,"tb.rulenode.last"],[Gt.ALL,"tb.rulenode.all"]]),wt=new Map([[Gt.FIRST,"tb.rulenode.first-mode-hint"],[Gt.LAST,"tb.rulenode.last-mode-hint"],[Gt.ALL,"tb.rulenode.all-mode-hint"]]);var Vt,Pt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Vt||(Vt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(Pt||(Pt={}));const Rt=new Map([[Pt.ATTRIBUTES,"tb.rulenode.attributes"],[Pt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[Pt.FIELDS,"tb.rulenode.fields"]]),Ot=new Map([[Pt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[Pt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[Pt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),_t=new Map([[Vt.ASC,"tb.rulenode.ascending"],[Vt.DESC,"tb.rulenode.descending"]]);var Bt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Bt||(Bt={}));const Kt=new Map([[Bt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Bt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),zt=["anonymous","basic","cert.PEM"],Ut=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Ht=["sas","cert.PEM"],jt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var $t;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}($t||($t={}));const Qt=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],Jt=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 Yt;!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"}(Yt||(Yt={}));const Wt=new Map([[Yt.CUSTOM,{value:Yt.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[Yt.ADD,{value:Yt.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[Yt.SUB,{value:Yt.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[Yt.MULT,{value:Yt.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[Yt.DIV,{value:Yt.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[Yt.SIN,{value:Yt.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.SINH,{value:Yt.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[Yt.COS,{value:Yt.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.COSH,{value:Yt.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[Yt.TAN,{value:Yt.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[Yt.TANH,{value:Yt.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ACOS,{value:Yt.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[Yt.ASIN,{value:Yt.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN,{value:Yt.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN2,{value:Yt.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}],[Yt.EXP,{value:Yt.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[Yt.EXPM1,{value:Yt.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[Yt.SQRT,{value:Yt.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[Yt.CBRT,{value:Yt.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[Yt.GET_EXP,{value:Yt.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[Yt.HYPOT,{value:Yt.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[Yt.LOG,{value:Yt.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG10,{value:Yt.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG1P,{value:Yt.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[Yt.CEIL,{value:Yt.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR,{value:Yt.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR_DIV,{value:Yt.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[Yt.FLOOR_MOD,{value:Yt.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[Yt.ABS,{value:Yt.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[Yt.MIN,{value:Yt.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[Yt.MAX,{value:Yt.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[Yt.POW,{value:Yt.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}],[Yt.SIGNUM,{value:Yt.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[Yt.RAD,{value:Yt.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[Yt.DEG,{value:Yt.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var Zt,Xt,en;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(Zt||(Zt={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(Xt||(Xt={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(en||(en={}));const tn=new Map([[en.DATA,"tb.rulenode.message-to-metadata"],[en.METADATA,"tb.rulenode.metadata-to-message"]]),nn=(new Map([[en.DATA,"tb.rulenode.from-message"],[en.METADATA,"tb.rulenode.from-metadata"]]),new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.metadata"]])),rn=new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.message-metadata"]]),on=new Map([[Zt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[Zt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[Zt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[Zt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[Zt.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),an=new Map([[Xt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[Xt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[Xt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[Xt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),ln=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var sn,mn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(sn||(sn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(mn||(mn={}));const pn=new Map([[sn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[sn.SERVER_SCOPE,"tb.rulenode.server-scope"],[sn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var dn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(dn||(dn={}));const un=new Map([[dn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[dn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.keys(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.keys(qt),this.rangeUnitTranslationMap=At,this.presenceMonitoringStrategies=un,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Nt),this.timeUnitsTranslationMap=St,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[O.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",cn),cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n
    \n
    \n
    {{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
    \n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
    \n
    {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
    \n
    \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n
    \n
    \n
    {{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
    \n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
    \n
    {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
    \n
    \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fn extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",fn),fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",gn),gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",yn),yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",xn),xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",bn),bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:a((()=>Cn)),multi:!0},{provide:K,useExisting:a((()=>Cn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Se.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:a((()=>Cn)),multi:!0},{provide:K,useExisting:a((()=>Cn)),multi:!0}],template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],required:[{type:i}]}});class Fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ln extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:o,args:["attributeChipList"]}]}});class In extends L{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=Wt,this.ArgumentType=Zt,this.attributeScopeMap=pn,this.argumentTypeMap=on,this.arguments=Object.values(Zt),this.attributeScope=Object.values(sn),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===Yt.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===Zt.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==Zt.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(ln[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:a((()=>In)),multi:!0},{provide:K,useExisting:a((()=>In)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:qe.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:qe.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Ae.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Ae.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Ae.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Se.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:a((()=>In)),multi:!0},{provide:K,useExisting:a((()=>In)),multi:!0}],template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],function:[{type:i}]}});class Nn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(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=[...Wt.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(Me((e=>{let t;t="string"==typeof e&&Yt[e]?Yt[e]:null,this.updateView(t)})),Ee((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=Wt.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Nn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Re.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Re.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Oe.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:a((()=>Nn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:i}],disabled:[{type:i}],operationInput:[{type:o,args:["operationInput",{static:!0}]}]}});class Sn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=Yt,this.ArgumentTypeResult=Xt,this.argumentTypeResultMap=an,this.attributeScopeMap=pn,this.argumentsResult=Object.values(Xt),this.attributeScopeResult=Object.values(mn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===Yt.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===Xt.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:In,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:Nn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class qn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=T,this.eventOptions=[I.CONNECT_EVENT,I.ACTIVITY_EVENT,I.DISCONNECT_EVENT,I.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:ae(e?.event)?e.event:I.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[O.required]]})}}e("DeviceStateConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-action-node-device-state-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-action-node-device-state-config",template:'
    \n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class An{constructor(){this.textAlign="left"}}e("ExampleHintComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:i}],popupHelpLink:[{type:i}],textAlign:[{type:i}]}});class Mn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new Ke,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ie(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(ze(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0},{provide:K,useExisting:a((()=>Mn)),multi:!0}],ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([N()],Mn.prototype,"disabled",void 0),Be([N()],Mn.prototype,"uniqueKeyValuePairValidator",void 0),Be([N()],Mn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0},{provide:K,useExisting:a((()=>Mn)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class En extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.entityType=F,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>En)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Qe.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:Je.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:a((()=>En)),multi:!0}],template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Gn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Gn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Ye.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:a((()=>Gn)),multi:!0}],template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Dn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(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=[ge,ye,xe],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(I))this.messageTypesList.push({name:T.get(I[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Ge(""),Ee((e=>e||"")),De((e=>this.fetchMessageTypes(e))),we())}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 Ue(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return Ue(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Dn)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Re.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Re.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:Re.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Oe.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:a((()=>Dn)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],label:[{type:i}],placeholder:[{type:i}],disabled:[{type:i}],chipList:[{type:o,args:["chipList",{static:!1}]}],matAutocomplete:[{type:o,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:o,args:["messageTypeInput",{static:!1}]}]}});class wn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=zt,this.credentialsTypeTranslationsMap=Ut,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){ae(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",wn),wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:a((()=>wn)),multi:!0},{provide:K,useExisting:a((()=>wn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:We.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:We.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:a((()=>wn)),multi:!0},{provide:K,useExisting:a((()=>wn)),multi:!0}],template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],disableCertPemCredentials:[{type:i}],passwordFieldRequired:[{type:i}]}});const Vn=new l("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class Pn{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new Ke,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,deps:[{token:t.NgZone},{token:j},{token:Vn,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),Pn.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:m,args:[j]}]},{type:void 0,decorators:[{type:p},{type:m,args:[Vn]}]}]}});class Rn{constructor(e,t,n,o){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=o,this.cbOnSuccess=new r,this.cbOnError=new r,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Rn,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:Pn}],target:t.ɵɵFactoryTarget.Directive}),Rn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:Rn,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Rn,decorators:[{type:d,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:Pn}]},propDecorators:{targetElm:[{type:i,args:["ngxClipboard"]}],container:[{type:i}],cbContent:[{type:i}],cbSuccessMsg:[{type:i}],cbOnSuccess:[{type:u}],cbOnError:[{type:u}]}});class On{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,deps:[{token:Pn},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),On.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:On,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,decorators:[{type:d,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:Pn},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class _n{}_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,deps:[],target:t.ɵɵFactoryTarget.NgModule}),_n.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,declarations:[Rn,On],imports:[$],exports:[Rn,On]}),_n.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,decorators:[{type:c,args:[{imports:[$],declarations:[Rn,On],exports:[Rn,On]}]}]});class Bn{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 Ke,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(ze(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(ze(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0},{provide:K,useExisting:a((()=>Bn)),multi:!0}],ngImport:t,template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Rn,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([N()],Bn.prototype,"disabled",void 0),Be([N()],Bn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0},{provide:K,useExisting:a((()=>Bn)),multi:!0}],template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:i}],disabled:[{type:i}],required:[{type:i}]}});class Kn{constructor(e,t){this.fb=e,this.translate=t,this.translation=nn,this.propagateChange=()=>{},this.destroy$=new Ke,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0}],ngImport:t,template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0}],template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:i}],translation:[{type:i}]}});class zn extends L{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new Ke,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ie(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(Ve(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)ae(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(Ve(this.destroy$)).subscribe((t=>{const n=Lt.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>zn)),multi:!0},{provide:K,useExisting:a((()=>zn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Se.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([N()],zn.prototype,"disabled",void 0),Be([N()],zn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0},{provide:K,useExisting:a((()=>zn)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:i}],disabled:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],targetKeyPrefix:[{type:i}],selectText:[{type:i}],selectRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class Un extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Un)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ye.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:a((()=>Un)),multi:!0}],template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Hn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new Ke,this.separatorKeysCodes=[ge,ye,xe],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||ae(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:a((()=>Hn)),multi:!0},{provide:K,useExisting:Hn,multi:!0}],ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:a((()=>Hn)),multi:!0},{provide:K,useExisting:Hn,multi:!0}],template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:i}]}});class jn extends L{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new Ke,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>jn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>jn)),multi:!0}],template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class $n{}e("RulenodeCoreConfigCommonModule",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[],target:t.ɵɵFactoryTarget.NgModule}),$n.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$n,declarations:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An],imports:[$,M,_e],exports:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An]}),$n.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,imports:[$,M,_e]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:c,args:[{declarations:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An],imports:[$,M,_e],exports:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An]}]}]});class Qn{}e("RuleNodeCoreConfigActionModule",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Qn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Qn,declarations:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn],imports:[$,M,_e,$n],exports:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn]}),Qn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,imports:[$,M,_e,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:c,args:[{declarations:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn],imports:[$,M,_e,$n],exports:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn]}]}]});class Jn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]]})}prepareInputConfig(e){return{inputValueKey:ae(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:ae(e?.outputValueKey)?e.outputValueKey:null,useCache:!ae(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!ae(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:ae(e?.periodValueKey)?e.periodValueKey:null,round:ae(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!ae(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative}}prepareOutputConfig(e){return le(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Yn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.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,le(e)}prepareInputConfig(e){let t,n;return t=ae(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ae(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ae(e?.attrMapping)?e.attrMapping:ae(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Wn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return se(e)&&(e.attributesControl={clientAttributeNames:ae(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ae(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ae(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ae(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ae(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:ae(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!ae(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:En,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Zn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Mt))this.predefinedValues.push({value:Mt[e],name:this.translate.instant(Et.get(Mt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=ae(e?.addToMetadata)?e.addToMetadata?en.METADATA:en.DATA:e?.fetchTo?e.fetchTo:en.DATA,{detailsList:ae(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Xn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Gt,this.samplingOrders=Object.values(Vt),this.samplingOrdersTranslate=_t,this.timeUnits=Object.values(Nt),this.timeUnitsTranslationMap=St,this.deduplicationStrategiesHintTranslations=wt,this.headerOptions=[],this.timeUnitMap={[Nt.MILLISECONDS]:1,[Nt.SECONDS]:1e3,[Nt.MINUTES]:6e4,[Nt.HOURS]:36e5,[Nt.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 Dt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Dt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,le(e)}prepareInputConfig(e){return se(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:ae(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:ae(e?.aggregation)?e.aggregation:E.NONE,fetchMode:ae(e?.fetchMode)?e.fetchMode:Gt.FIRST,orderBy:ae(e?.orderBy)?e.orderBy:Vt.ASC,limit:ae(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!ae(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:ae(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:ae(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Nt.MINUTES,endInterval:ae(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:ae(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Nt.MINUTES},startIntervalPattern:ae(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:ae(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Gt.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Gt.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class er extends f{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 se(e)&&(e.attributesControl={clientAttributeNames:ae(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ae(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ae(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ae(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ae(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA,tellFailureIfAbsent:!!ae(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:ae(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class tr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of kt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return le(e)}prepareInputConfig(e){return{dataMapping:ae(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:ae(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:zn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class nr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=Pt,this.msgMetadataLabelTranslations=Ot,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(kt))this.originatorFields.push({value:kt[e].value,name:this.translate.instant(kt[e].name)});for(const e of Rt.keys())this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===Pt.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,le(e)}prepareInputConfig(e){let t,n,r={[k.name.value]:`relatedEntity${this.translate.instant(k.name.name)}`},o={serialNumber:"sn"};return t=ae(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ae(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ae(e?.attrMapping)?e.attrMapping:ae(e?.dataMapping)?e.dataMapping:null,t===Pt.FIELDS?r=n:o=n,{relationsQuery:ae(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Gn,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:zn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class rr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=ae(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ae(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ae(e?.attrMapping)?e.attrMapping:ae(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class or extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class ar{}e("RulenodeCoreConfigEnrichmentModule",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[],target:t.ɵɵFactoryTarget.NgModule}),ar.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:ar,declarations:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or],imports:[$,M,$n],exports:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or]}),ar.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:c,args:[{declarations:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or],imports:[$,M,$n],exports:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or]}]}]});class ir extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Ht,this.azureIotHubCredentialsTypeTranslationsMap=jt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ir,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:We.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:We.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=Qt,this.ToByteStandartCharsetTypeTranslationMap=Jt}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&me(e.clientId))},[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){me(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:wn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=D,this.entityType=F}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
    \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class dr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys($t)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],useRedisQueueForMsgPersistence:[!!e&&e.useRedisQueueForMsgPersistence,[]],trimQueue:[!!e&&e.trimQueue,[]],maxQueueSize:[e?e.maxQueueSize:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","useRedisQueueForMsgPersistence","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("useRedisQueueForMsgPersistence").value,r=this.restApiCallConfigForm.get("enableProxy").value,o=this.restApiCallConfigForm.get("useSystemProxyProperties").value;r&&!o?(this.restApiCallConfigForm.get("proxyHost").setValidators(r?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(r?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),n?this.restApiCallConfigForm.get("maxQueueSize").setValidators([O.min(0)]):this.restApiCallConfigForm.get("maxQueueSize").setValidators([]),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("maxQueueSize").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:wn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(w),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class yr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Bt,this.sqsQueueTypes=Object.keys(Bt),this.sqsQueueTypeTranslationsMap=Kt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class br{}e("RulenodeCoreConfigExternalModule",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[],target:t.ɵɵFactoryTarget.NgModule}),br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:br,declarations:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr],imports:[$,M,_e,$n],exports:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr]}),br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,imports:[$,M,_e,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:c,args:[{declarations:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr],imports:[$,M,_e,$n],exports:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr]}]}]});class hr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ae(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:jn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class vr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ae(e?.messageNames)?e.messageNames:[],metadataNames:ae(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!ae(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:ae(e?.messageNames)?e.messageNames:[],metadataNames:ae(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=C}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ae(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ae(e?.direction)?e.direction:null,entityType:ae(e?.entityType)?e.entityType:null,entityId:ae(e?.entityId)?e.entityId:null,relationType:ae(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Je.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.values(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.values(qt),this.rangeUnitTranslationMap=At,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ae(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ae(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ae(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ae(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ae(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ae(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ae(e?.centerLongitude)?e.centerLongitude:null,range:ae(e?.range)?e.range:null,rangeUnit:ae(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ae(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class kr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ae(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Dn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.TENANT,F.CUSTOMER,F.USER,F.DASHBOARD,F.RULE_CHAIN,F.RULE_NODE,F.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ae(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ae(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ae(e?.jsScript)?e.jsScript:null,tbelScript:ae(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Ir extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ae(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ae(e?.jsScript)?e.jsScript:null,tbelScript:ae(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Nr{}e("RuleNodeCoreConfigFilterModule",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Nr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Nr,declarations:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr],imports:[$,M,$n],exports:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr]}),Nr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:c,args:[{declarations:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr],imports:[$,M,$n],exports:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr]}]}]});class Sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=vt,this.originatorSources=Object.keys(vt),this.originatorSourceTranslationMap=Ct,this.originatorSourceDescTranslationMap=Ft,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.USER,F.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===vt.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===vt.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:qe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:qe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Gn,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class qr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",qr),qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,deps:[{token:P.Store},{token:R.FormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),qr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qr,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +const Ar=mt({passive:!0});class Mr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return He;const t=Te(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new Ke,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Ar),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Ar)}}),r}stopMonitoring(e){const t=Te(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Mr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class Er{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new r}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}Er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Er,deps:[{token:t.ElementRef},{token:Mr}],target:t.ɵɵFactoryTarget.Directive}),Er.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Er,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Er,decorators:[{type:d,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Mr}]},propDecorators:{cdkAutofill:[{type:u}]}}); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +class Gr{get minRows(){return this._minRows}set minRows(e){this._minRows=Ie(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=Ie(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Le(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new Ke,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();je(e,"resize").pipe(Pe(16),Ve(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Gr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Gr,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:d,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:p},{type:m,args:[j]}]}]},propDecorators:{minRows:[{type:i,args:["cdkAutosizeMinRows"]}],maxRows:[{type:i,args:["cdkAutosizeMaxRows"]}],enabled:[{type:i,args:["cdkTextareaAutosize"]}],placeholder:[{type:i}]}}); +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +class Dr{}Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Dr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,declarations:[Er,Gr],exports:[Er,Gr]}),Dr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,decorators:[{type:c,args:[{declarations:[Er,Gr],exports:[Er,Gr]}]}]});class wr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:ae(e?.fromTemplate)?e.fromTemplate:null,toTemplate:ae(e?.toTemplate)?e.toTemplate:null,ccTemplate:ae(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:ae(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:ae(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:ae(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:ae(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:ae(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",wr),wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),wr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Gr,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:qe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:qe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Vr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=tn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=ae(e?.fromMetadata)?e.copyFrom?en.METADATA:en.DATA:ae(e?.copyFrom)?e.copyFrom:en.DATA,{keys:ae(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Vr),Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Pr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=rn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=ae(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ae(e?.renameIn)?e?.renameIn:en.DATA,{renameKeysMapping:ae(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Rr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Or extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=nn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=ae(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ae(e?.deleteFrom)?e?.deleteFrom:en.DATA,{keys:ae(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class _r extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Gt,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Dt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[ae(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[ae(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[ae(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[ae(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[ae(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Bn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Br{}e("RulenodeCoreConfigTransformModule",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Br,declarations:[Sr,qr,wr,Vr,Pr,Rr,Or,_r],imports:[$,M,$n],exports:[Sr,qr,wr,Vr,Pr,Rr,Or,_r]}),Br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:c,args:[{declarations:[Sr,qr,wr,Vr,Pr,Rr,Or,_r],imports:[$,M,$n],exports:[Sr,qr,wr,Vr,Pr,Rr,Or,_r]}]}]});class Kr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=F}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class zr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),zr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zr,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ur{}e("RuleNodeCoreConfigFlowModule",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Ur.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Ur,declarations:[Kr,zr],imports:[$,M,$n],exports:[Kr,zr]}),Ur.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:c,args:[{declarations:[Kr,zr],imports:[$,M,$n],exports:[Kr,zr]}]}]});class Hr{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 not exists","create-entity-if-not-exists-hint":"Create a new entity set above if it does not exist.","select-device-connectivity-event":"Select device connectivity event","entity-name-pattern":"Name pattern","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 name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","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","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":"Timeseries keys","timeseries-keys-required":"At least one timeseries key should be selected.","add-timeseries-key":"Add timeseries key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-to-specific-entity":"Delete relation to specific entity","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"use-redis-queue":"Use redis queue for message persistence","ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","trim-redis-queue":"Trim redis queue","redis-queue-max-size":"Redis queue max size","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.","persist-alarm-rules":"Persist state of alarm rules","fetch-alarm-rules":"Fetch state of alarm rules","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","use-server-ts":"Use server ts","use-server-ts-hint":"Enable this setting to use the timestamp of the 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.","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":"timeseries 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 timeseries from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch timeseries 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 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."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",Hr),Hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),Hr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Hr,declarations:[dt],imports:[$,M],exports:[Qn,Nr,ar,br,Br,Ur,dt]}),Hr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,imports:[$,M,Qn,Nr,ar,br,Br,Ur]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,decorators:[{type:c,args:[{declarations:[dt],imports:[$,M],exports:[Qn,Nr,ar,br,Br,Ur,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map From f4c2791eb035fb809e908582032d98d3050dc55b Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 18 Mar 2024 12:36:36 +0200 Subject: [PATCH 362/397] UI: update yarn.lock --- ....2.9.patch => @angular+core+15.2.10.patch} | 2 +- ui-ngx/pom.xml | 2 +- ui-ngx/yarn.lock | 4382 ++++++++++------- 3 files changed, 2541 insertions(+), 1845 deletions(-) rename ui-ngx/patches/{@angular+core+15.2.9.patch => @angular+core+15.2.10.patch} (97%) diff --git a/ui-ngx/patches/@angular+core+15.2.9.patch b/ui-ngx/patches/@angular+core+15.2.10.patch similarity index 97% rename from ui-ngx/patches/@angular+core+15.2.9.patch rename to ui-ngx/patches/@angular+core+15.2.10.patch index 3797e6b48c..3265415263 100644 --- a/ui-ngx/patches/@angular+core+15.2.9.patch +++ b/ui-ngx/patches/@angular+core+15.2.10.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/@angular/core/fesm2020/core.mjs b/node_modules/@angular/core/fesm2020/core.mjs -index 3e93015..9efcb96 100755 +index e9a9b75..17044d9 100755 --- a/node_modules/@angular/core/fesm2020/core.mjs +++ b/node_modules/@angular/core/fesm2020/core.mjs @@ -11053,13 +11053,13 @@ function findDirectiveDefMatches(tView, tNode) { diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index 944ca04846..750a303dfb 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -56,7 +56,7 @@ install-node-and-yarn - v16.20.2 + v20.11.1 v1.22.17 diff --git a/ui-ngx/yarn.lock b/ui-ngx/yarn.lock index 4317883a2b..892b959e06 100644 --- a/ui-ngx/yarn.lock +++ b/ui-ngx/yarn.lock @@ -2,7 +2,12 @@ # yarn lockfile v1 -"@ampproject/remapping@2.2.0", "@ampproject/remapping@^2.1.0", "@ampproject/remapping@^2.2.0": +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@ampproject/remapping@2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== @@ -10,6 +15,14 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" +"@ampproject/remapping@^2.1.0", "@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@angular-builders/custom-webpack@~15.0.0": version "15.0.0" resolved "https://registry.yarnpkg.com/@angular-builders/custom-webpack/-/custom-webpack-15.0.0.tgz#bc05c5fdc1153ae2f48417f6529034282398940d" @@ -23,31 +36,23 @@ tsconfig-paths "^4.1.0" webpack-merge "^5.7.3" -"@angular-devkit/architect@0.1502.1", "@angular-devkit/architect@>=0.1500.0 < 0.1600.0": - version "0.1502.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1502.1.tgz#0ab9919638f61eaa962b1863d99581c52ccfa2a9" - integrity sha512-/rtR0U4TJCplpnIfenoTOIn4omPUDDL8iAl6le0qelL2CXdEl6UjMBYF1ILS8OVMLfpEGUXfMLeZgRn0yb7DjA== +"@angular-devkit/architect@0.1502.10", "@angular-devkit/architect@>=0.1500.0 < 0.1600.0": + version "0.1502.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1502.10.tgz#4c25ba881635937d922b18e7959b38a476badc82" + integrity sha512-S8lN73WYCfpEpw1Q41ZcUinw7JfDeSM8LyGs797OVshnW75QcOkOecWj/3CKR23G44IgFrHN6sqtzWxKmMxLig== dependencies: - "@angular-devkit/core" "15.2.1" + "@angular-devkit/core" "15.2.10" rxjs "6.6.7" -"@angular-devkit/architect@0.1502.8": - version "0.1502.8" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1502.8.tgz#9fd3fd27b3a7fc5f8eb65c92500b4d9d15b879e8" - integrity sha512-rTltw2ABHrcKc8EGimALvXmrDTP5hlNbEy6nYolJoXEI9EwHgriWrVLVPs3OEF+/ed47dbJi9EGOXUOgzgpB5A== - dependencies: - "@angular-devkit/core" "15.2.8" - rxjs "6.6.7" - -"@angular-devkit/build-angular@^15.0.0": - version "15.2.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-15.2.1.tgz#11dacec9f651e4491bb5d914e8b84dc2e245c955" - integrity sha512-EgJqlrig9iuMvqySb4h8h2AAd8OwhBqY2JMMvs+hIASZvJi3n+Qd12BdlqLuAzykRyIAdy3OeLSAaXZrmeSk0A== +"@angular-devkit/build-angular@^15.0.0", "@angular-devkit/build-angular@^15.2.8": + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-15.2.10.tgz#af4080a4811461bd1cab4f3b1b10edef53f31da8" + integrity sha512-3pCPVEJilVwHIJC6Su1/PIEqvFfU1Lxew9yItxX4s6dud8HY+fuKrsDnao4NNMFNqCLqL4el5QbSBKnnpWH1sg== dependencies: "@ampproject/remapping" "2.2.0" - "@angular-devkit/architect" "0.1502.1" - "@angular-devkit/build-webpack" "0.1502.1" - "@angular-devkit/core" "15.2.1" + "@angular-devkit/architect" "0.1502.10" + "@angular-devkit/build-webpack" "0.1502.10" + "@angular-devkit/core" "15.2.10" "@babel/core" "7.20.12" "@babel/generator" "7.20.14" "@babel/helper-annotate-as-pure" "7.18.6" @@ -59,7 +64,7 @@ "@babel/runtime" "7.20.13" "@babel/template" "7.20.7" "@discoveryjs/json-ext" "0.5.7" - "@ngtools/webpack" "15.2.1" + "@ngtools/webpack" "15.2.10" ansi-colors "4.1.3" autoprefixer "10.4.13" babel-loader "9.1.2" @@ -86,81 +91,13 @@ ora "5.4.1" parse5-html-rewriting-stream "7.0.0" piscina "3.2.0" - postcss "8.4.21" + postcss "8.4.31" postcss-loader "7.0.2" resolve-url-loader "5.0.0" rxjs "6.6.7" sass "1.58.1" sass-loader "13.2.0" - semver "7.3.8" - source-map-loader "4.0.1" - source-map-support "0.5.21" - terser "5.16.3" - text-table "0.2.0" - tree-kill "1.2.2" - tslib "2.5.0" - webpack "5.75.0" - webpack-dev-middleware "6.0.1" - webpack-dev-server "4.11.1" - webpack-merge "5.8.0" - webpack-subresource-integrity "5.1.0" - optionalDependencies: - esbuild "0.17.8" - -"@angular-devkit/build-angular@^15.2.8": - version "15.2.8" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-15.2.8.tgz#5412125b810fee084eb8afc20b9911606ad66170" - integrity sha512-TGDnXhhOG6h6TOrWWzfnkha7wYBOXi7iJc1o1w1VKCayE3T6TZZdF847aK66vL9KG7AKYVdGhWEGw2WBHUBUpg== - dependencies: - "@ampproject/remapping" "2.2.0" - "@angular-devkit/architect" "0.1502.8" - "@angular-devkit/build-webpack" "0.1502.8" - "@angular-devkit/core" "15.2.8" - "@babel/core" "7.20.12" - "@babel/generator" "7.20.14" - "@babel/helper-annotate-as-pure" "7.18.6" - "@babel/helper-split-export-declaration" "7.18.6" - "@babel/plugin-proposal-async-generator-functions" "7.20.7" - "@babel/plugin-transform-async-to-generator" "7.20.7" - "@babel/plugin-transform-runtime" "7.19.6" - "@babel/preset-env" "7.20.2" - "@babel/runtime" "7.20.13" - "@babel/template" "7.20.7" - "@discoveryjs/json-ext" "0.5.7" - "@ngtools/webpack" "15.2.8" - ansi-colors "4.1.3" - autoprefixer "10.4.13" - babel-loader "9.1.2" - babel-plugin-istanbul "6.1.1" - browserslist "4.21.5" - cacache "17.0.4" - chokidar "3.5.3" - copy-webpack-plugin "11.0.0" - critters "0.0.16" - css-loader "6.7.3" - esbuild-wasm "0.17.8" - glob "8.1.0" - https-proxy-agent "5.0.1" - inquirer "8.2.4" - jsonc-parser "3.2.0" - karma-source-map-support "1.4.0" - less "4.1.3" - less-loader "11.1.0" - license-webpack-plugin "4.0.2" - loader-utils "3.2.1" - magic-string "0.29.0" - mini-css-extract-plugin "2.7.2" - open "8.4.1" - ora "5.4.1" - parse5-html-rewriting-stream "7.0.0" - piscina "3.2.0" - postcss "8.4.21" - postcss-loader "7.0.2" - resolve-url-loader "5.0.0" - rxjs "6.6.7" - sass "1.58.1" - sass-loader "13.2.0" - semver "7.3.8" + semver "7.5.3" source-map-loader "4.0.1" source-map-support "0.5.21" terser "5.16.3" @@ -175,26 +112,18 @@ optionalDependencies: esbuild "0.17.8" -"@angular-devkit/build-webpack@0.1502.1": - version "0.1502.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1502.1.tgz#d0332b620a24a37ce132ef3fb771af3f991c6413" - integrity sha512-mQ9dbuoy0U2+caQCRMhUx88fA/WmBt+JkYt8nvtTUyhVTXm5XIVckTlIfqdVk0BCA1lT8AM4yFKmy97bFXuZeQ== +"@angular-devkit/build-webpack@0.1502.10": + version "0.1502.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1502.10.tgz#665dfa76a0c6548821fa372356e2c9b55e8eebac" + integrity sha512-55b9WZIGU4DNgiIV2lkkN6iQxJrgWY5CDaNu0kJC/qazotJgBbcN/8jgBx2DD8HNE1V3iXxWk66pt1h946Po+Q== dependencies: - "@angular-devkit/architect" "0.1502.1" + "@angular-devkit/architect" "0.1502.10" rxjs "6.6.7" -"@angular-devkit/build-webpack@0.1502.8": - version "0.1502.8" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1502.8.tgz#1b375480deef1b0920e1a63d952795bd33bbfb38" - integrity sha512-jWtNv+S03FFLDe/C8SPCcRvkz3bSb2R+919IT086Q9axIPQ1VowOEwzt2k3qXPSSrC7GSYuASM+X92dB47NTQQ== - dependencies: - "@angular-devkit/architect" "0.1502.8" - rxjs "6.6.7" - -"@angular-devkit/core@15.2.1", "@angular-devkit/core@^15.0.0": - version "15.2.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-15.2.1.tgz#78b03a134d354df6646a29c718bef6721ac9365e" - integrity sha512-m6lj5vvA/L21rUVm4PokK2SXZQE1Hjsw8AMNEaj+RlyVW36ISLm2TeeCdb441siBpLJkW+yA47bC2FUJ8HgsQQ== +"@angular-devkit/core@15.2.10", "@angular-devkit/core@^15.0.0": + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-15.2.10.tgz#e2c1fadaaa87ae62b3f3c752fa6fafc31197151b" + integrity sha512-bFPm7wjvfBds9km2rCJxUhzkqe4h3h/199yJtzC1bNvwRr2LMHvtyoQAzftda+gs7Ulqac5wzUEZX/cVV3WrsA== dependencies: ajv "8.12.0" ajv-formats "2.1.1" @@ -202,23 +131,12 @@ rxjs "6.6.7" source-map "0.7.4" -"@angular-devkit/core@15.2.8": - version "15.2.8" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-15.2.8.tgz#ff494ae7af137b0f0109deb8ee34f1550ed5cc1d" - integrity sha512-Lo4XrbDMtXarKnMrFgWLmQdSX+3QPNAg4otG8cmp/U4jJyjV4dAYKEAsb1sCNGUSM4h4v09EQU/5ugVjDU29lQ== +"@angular-devkit/schematics@15.2.10": + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-15.2.10.tgz#72ea6ac84082995221781bcb72df3143b4ffddc3" + integrity sha512-EeoDs4oKFpLZNa21G/8dqBdclEc4U2piI9EeXCVTaN6z5DYXIZ0G1WtCXU8nhD+GckS47rmfZ4/3lMaXAvED+g== dependencies: - ajv "8.12.0" - ajv-formats "2.1.1" - jsonc-parser "3.2.0" - rxjs "6.6.7" - source-map "0.7.4" - -"@angular-devkit/schematics@15.2.8": - version "15.2.8" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-15.2.8.tgz#c7dfc692e3f54e43085a8845d8c9f390a2519aa3" - integrity sha512-w6EUGC96kVsH9f8sEzajzbONMawezyVBiSo+JYp5r25rQArAz/a+KZntbuETWHQ0rQOEsKmUNKxwmr11BaptSQ== - dependencies: - "@angular-devkit/core" "15.2.8" + "@angular-devkit/core" "15.2.10" jsonc-parser "3.2.0" magic-string "0.29.0" ora "5.4.1" @@ -282,9 +200,9 @@ "@typescript-eslint/utils" "5.48.2" "@angular/animations@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-15.2.9.tgz#f0773d2071a5a17c03478d5838029b03bbab9a03" - integrity sha512-GQujLhI0cQFcl4Q8y0oSYKSRnW23GIeSL+Arl4eFufziJ9hGAAQNuesaNs/7i+9UlTHDMkPH3kd5ScXuYYz6wg== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-15.2.10.tgz#c9194ba9a2b9b4e466e9c76e18591cde096a28e8" + integrity sha512-yxfN8qQpMaukRU5LjFkJBmy85rqrOp86tYVCsf+hmPEFRiXBMUj6xYLeCMcpk3Mt1JtnWGBR34ivGx+7bNeAow== dependencies: tslib "^2.3.0" @@ -298,14 +216,14 @@ parse5 "^7.1.2" "@angular/cli@^15.2.8": - version "15.2.8" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-15.2.8.tgz#612ffd69591aea0109db0a6dd8faec8044a4b80d" - integrity sha512-3VlTfm6DUZfFHBY43vQSAaqmFTxy3VtRd/iDBCHcEPhHwYLWBvNwReJuJfNja8O105QQ6DBiYVBExEBtPmjQ4w== - dependencies: - "@angular-devkit/architect" "0.1502.8" - "@angular-devkit/core" "15.2.8" - "@angular-devkit/schematics" "15.2.8" - "@schematics/angular" "15.2.8" + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-15.2.10.tgz#4035a64510e11894be2ff695e48ee0ef6badb494" + integrity sha512-/TSnm/ZQML6A4lvunyN2tjTB5utuvk3d1Pnfyehp/FXtV6YfZm6+EZrOpKkKPCxTuAgW6c9KK4yQtt3RuNVpwQ== + dependencies: + "@angular-devkit/architect" "0.1502.10" + "@angular-devkit/core" "15.2.10" + "@angular-devkit/schematics" "15.2.10" + "@schematics/angular" "15.2.10" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.3" ini "3.0.1" @@ -317,21 +235,21 @@ ora "5.4.1" pacote "15.1.0" resolve "1.22.1" - semver "7.3.8" + semver "7.5.3" symbol-observable "4.0.0" yargs "17.6.2" "@angular/common@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-15.2.9.tgz#5e1d47ce831935bcf545b172f88307aedacf1535" - integrity sha512-LM9/UHG2dRrOzlu2KovrFwWIziFMjRxHzSP3Igw6Symw/wIl0kXGq8Fn6RpFP78zmLqnv+IQOoRiby9MCXsI4g== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-15.2.10.tgz#897923023c8ca4a361ce218bdee9a3f09060df75" + integrity sha512-jdBn3fctkqoNrJn9VLsUHpcCEhCxWSczdsR+BBbD6T0oLl6vMrAVNjPwfBejnlgfWN1KoRU9kgOYsMxa5apIWQ== dependencies: tslib "^2.3.0" "@angular/compiler-cli@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-15.2.9.tgz#d9e6013d6a8658e4a210aca7997e70d06f6976a8" - integrity sha512-zsbI8G2xHOeYWI0hjFzrI//ZhZV9il/uQW5dAimfwJp06KZDeXZ3PdwY9JQslf6F+saLwOObxy6QMrIVvfjy9w== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-15.2.10.tgz#e51013aa0f3da303fc74f8e1948c550d8e74ead5" + integrity sha512-mCFIxrs60XicKfA2o42hA7LrQvhybi9BQveWuZn/2iIEOXx7R62Iemz8E21pLWftAZHGxEW3NECfBrY1d3gVmA== dependencies: "@babel/core" "7.19.3" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -345,16 +263,16 @@ yargs "^17.2.1" "@angular/compiler@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-15.2.9.tgz#3f55e206b0e380c28336d2a233b7132f21d72644" - integrity sha512-MoKugbjk+E0wRBj12uvIyDLELlVLonnqjA2+XiF+7FxALIeyds3/qQeEoMmYIqAbN3NnTT5pV92RxWwG4tHFwA== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-15.2.10.tgz#bd78f327d12eb5978f9dd05440aa23d4b5b925a9" + integrity sha512-M0XkeU0O73UlJZwDvOyp8/apetz9UKj78eTFDseMYJDLcxe6MpkbkxqpsGZnKYDj7LIep8PmCAKEkhtenE82zw== dependencies: tslib "^2.3.0" "@angular/core@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-15.2.9.tgz#7cb12cc83fcc92f23196ceac82e07b67b2e02203" - integrity sha512-w46Z1yUXCQfKV7XfnamOoLA2VD0MVUUYVrUjO73mHSskDXSXxfZAEHO9kfUS71Cj35PvhP3mbkqWscpea2WeYg== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-15.2.10.tgz#93c1e0d460d21711654c578d2709a402e1822023" + integrity sha512-meGGidnitQJGDxYd9/LrqYiVlId+vGaLoiLgJdKBz+o2ZO6OmXQGuNw2VBqf17/Cc0/UjzrOY7+kILNFKkk/WQ== dependencies: tslib "^2.3.0" @@ -366,16 +284,16 @@ tslib "^2.3.0" "@angular/forms@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-15.2.9.tgz#c3b4b0108f4eb4966ddc5a7ec9913c2ca2c94f00" - integrity sha512-sk0pC2EFi2Ohg5J0q0NYptbT+2WOkoiERSMYA39ncDvlSZBWsNlxpkbGUSck7NIxjK2QfcVN1ldGbHlZTFvtqg== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-15.2.10.tgz#09308e887df2fa4d349300c9d1f05cadfb3872b3" + integrity sha512-NIntGsNcN6o8L1txsbWXOf6f3K/CUBizdKsxsYVYGJIXEW5qU6UnWmfAZffNNXsT/XvbgUCjgDwT0cAwcqZPuQ== dependencies: tslib "^2.3.0" "@angular/language-service@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-15.2.9.tgz#7a94e3394093a425c757f7b385b4a94edb09178a" - integrity sha512-B7lP4q/eHge2lZezOXS96EYzVf4stMCWfOnz7+pUUi0HbF+A5QCV65SWQddS/M+NM2jj8N2L/j+6UCH8lJjTQA== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-15.2.10.tgz#829a802aaf40bfab21d71463023a3b517500ffa9" + integrity sha512-G0g0teF4pBqLTgfyLcoBl55g91sCZvBK+V4VgTD/hXGpXyMNlNpOsgECSMliGQoJlsRLEugFsSlBNqy7CRoBtw== "@angular/material@^15.2.9": version "15.2.9" @@ -432,23 +350,23 @@ tslib "^2.3.0" "@angular/platform-browser-dynamic@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-15.2.9.tgz#aa31ba63d535ee49fdf3a60fe771503565b4e3c9" - integrity sha512-ZIYDM6MShblb8OyV1m4+18lJJ2LCeICmeg2uSbpFYptYBSOClrTiYOOFVDJvn7HLvNzljLs16XPrgyaYVqNpcw== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-15.2.10.tgz#cc9ad3dcded6cb945ee8c4eef14db081dc6c3dfd" + integrity sha512-JHP6W+FX715Qv7DhqvfZLuBZXSDJrboiQsR06gUAgDSjAUyhbqmpVg/2YOtgeWpPkzNDtXdPU2PhcRdIv5J3Yg== dependencies: tslib "^2.3.0" "@angular/platform-browser@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-15.2.9.tgz#9150645843cc18b084fb5bf7025e6e320c2abe1e" - integrity sha512-ufCHeSX+U6d43YOMkn3igwfqtlozoCXADcbyfUEG8m2y9XASobqmCKvdSk/zfl62oyiA8msntWBJVBE2l4xKXg== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-15.2.10.tgz#ca5a904b4da9e0cf719414db89514ee4221cb93d" + integrity sha512-9tbgVGSJqwfrOzT8aA/kWBLNhJSQ9gUg0CJxwFBSJm8VkBUJrszoBlDsnSvlxx8/W2ejNULKHFTXeUzq0O/+RQ== dependencies: tslib "^2.3.0" "@angular/router@^15.2.9": - version "15.2.9" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-15.2.9.tgz#c3879be22bda236eacf97a18a1e8619b51a53d47" - integrity sha512-UCbh5DLSDhybv0xKYT7kGQMfOVdyhHIHOZz5EYVebbhste6S+W1LE57vTHq7QtxJsyKBa/WSkaUkCLXD6ntCAg== + version "15.2.10" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-15.2.10.tgz#a5d32d769b930e905582ed6c7aa8122e63655738" + integrity sha512-LmuqEg0iIXSw7bli6HKJ19cbxP91v37GtRwbGKswyLihqzTgvjBYpvcfMnB5FRQ5LWkTwq5JclkX03dZw290Yg== dependencies: tslib "^2.3.0" @@ -458,23 +376,24 @@ integrity sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg== "@auth0/angular-jwt@^5.1.2": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@auth0/angular-jwt/-/angular-jwt-5.1.2.tgz#e89ece98b0f6ef6407f35b8b64bcb77c53b0d8e5" - integrity sha512-8ulz24cPpEkZb9/AdAaWfYIkomQDbZqvB9LproF/48Klnr30EJx09AYF9sbKTN4qLSgIZSlCb/Y7XQJZ51vSzA== + version "5.2.0" + resolved "https://registry.yarnpkg.com/@auth0/angular-jwt/-/angular-jwt-5.2.0.tgz#3a734be51f7f4b1bb85ac2535e987b7e6e706481" + integrity sha512-9FS2L0QwGNlxA/zgeehCcsR9CZscouyXkoIj1fODM36A8BLfdzg9k9DWAXUQ2Drjk0AypGAFzeNZR4vsLMhdeQ== dependencies: tslib "^2.0.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.0.tgz#c241dc454e5b5917e40d37e525e2f4530c399298" - integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g== +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== "@babel/core@7.19.3": version "7.19.3" @@ -519,25 +438,25 @@ semver "^6.3.0" "@babel/core@^7.12.3": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" - integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.0.tgz#56cbda6b185ae9d9bed369816a8f4423c5f2ff1b" + integrity sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.0" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-module-transforms" "^7.21.0" - "@babel/helpers" "^7.21.0" - "@babel/parser" "^7.21.0" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.0" - "@babel/types" "^7.21.0" - convert-source-map "^1.7.0" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.24.0" + "@babel/parser" "^7.24.0" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.0" + "@babel/types" "^7.24.0" + convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.2" - semver "^6.3.0" + json5 "^2.2.3" + semver "^6.3.1" "@babel/generator@7.20.14": version "7.20.14" @@ -548,63 +467,71 @@ "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" -"@babel/generator@^7.19.3", "@babel/generator@^7.20.7", "@babel/generator@^7.21.0", "@babel/generator@^7.21.1": - version "7.21.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" - integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== +"@babel/generator@^7.19.3", "@babel/generator@^7.20.7", "@babel/generator@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== dependencies: - "@babel/types" "^7.21.0" + "@babel/types" "^7.23.6" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@7.18.6", "@babel/helper-annotate-as-pure@^7.18.6": +"@babel/helper-annotate-as-pure@7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== dependencies: "@babel/types" "^7.18.6" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" - integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== +"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== dependencies: - "@babel/helper-explode-assignable-expression" "^7.18.6" - "@babel/types" "^7.18.9" + "@babel/types" "^7.22.5" -"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.3", "@babel/helper-compilation-targets@^7.20.0", "@babel/helper-compilation-targets@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz#a6cd33e93629f5eb473b021aac05df62c4cd09bb" - integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" + integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== dependencies: - "@babel/compat-data" "^7.20.5" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.21.3" - lru-cache "^5.1.1" - semver "^6.3.0" + "@babel/types" "^7.22.15" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz#64f49ecb0020532f19b1d014b03bccaa1ab85fb9" - integrity sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ== +"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.19.3", "@babel/helper-compilation-targets@^7.20.0", "@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-member-expression-to-functions" "^7.21.0" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-replace-supers" "^7.20.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz#53ff78472e5ce10a52664272a239787107603ebb" - integrity sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.0.tgz#fc7554141bdbfa2d17f7b4b80153b9b090e5d158" + integrity sha512-QAH+vfvts51BCsNZ2PhY6HAggnlS6omLLFTsIpeqZk/MmJ6cW7tgz5yRv0fMJThcr6FmbMrENh1RgrWPTYA76g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-member-expression-to-functions" "^7.23.0" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" + integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" regexpu-core "^5.3.1" + semver "^6.3.1" "@babel/helper-define-polyfill-provider@^0.3.3": version "0.3.3" @@ -618,179 +545,171 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== +"@babel/helper-environment-visitor@^7.18.9", "@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== -"@babel/helper-explode-assignable-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" - integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== +"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: - "@babel/types" "^7.18.6" + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" -"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" - integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== dependencies: - "@babel/template" "^7.20.7" - "@babel/types" "^7.21.0" + "@babel/types" "^7.22.5" -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== +"@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" + integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.23.0" -"@babel/helper-member-expression-to-functions@^7.20.7", "@babel/helper-member-expression-to-functions@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz#319c6a940431a133897148515877d2f3269c3ba5" - integrity sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q== +"@babel/helper-module-imports@^7.18.6", "@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== dependencies: - "@babel/types" "^7.21.0" + "@babel/types" "^7.22.15" -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== +"@babel/helper-module-transforms@^7.19.0", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== dependencies: - "@babel/types" "^7.18.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" -"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.0", "@babel/helper-module-transforms@^7.21.2": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2" - integrity sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ== +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.20.2" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.2" - "@babel/types" "^7.21.2" + "@babel/types" "^7.22.5" -"@babel/helper-optimise-call-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" - integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" - integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" + integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== -"@babel/helper-remap-async-to-generator@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" - integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== +"@babel/helper-remap-async-to-generator@^7.18.9", "@babel/helper-remap-async-to-generator@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" + integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-wrap-function" "^7.18.9" - "@babel/types" "^7.18.9" + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-wrap-function" "^7.22.20" -"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz#243ecd2724d2071532b2c8ad2f0f9f083bcae331" - integrity sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A== +"@babel/helper-replace-supers@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" + integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-member-expression-to-functions" "^7.20.7" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.7" - "@babel/types" "^7.20.7" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" -"@babel/helper-simple-access@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" - integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== dependencies: - "@babel/types" "^7.20.2" + "@babel/types" "^7.22.5" -"@babel/helper-skip-transparent-expression-wrappers@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" - integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== +"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== dependencies: - "@babel/types" "^7.20.0" + "@babel/types" "^7.22.5" -"@babel/helper-split-export-declaration@7.18.6", "@babel/helper-split-export-declaration@^7.18.6": +"@babel/helper-split-export-declaration@7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== dependencies: "@babel/types" "^7.18.6" -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" -"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== -"@babel/helper-validator-option@^7.18.6": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" - integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== -"@babel/helper-wrap-function@^7.18.9": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3" - integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q== +"@babel/helper-validator-option@^7.18.6", "@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== + +"@babel/helper-wrap-function@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" + integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== dependencies: - "@babel/helper-function-name" "^7.19.0" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.5" - "@babel/types" "^7.20.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/types" "^7.22.19" -"@babel/helpers@^7.19.0", "@babel/helpers@^7.20.7", "@babel/helpers@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.0.tgz#9dd184fb5599862037917cdc9eecb84577dc4e7e" - integrity sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA== +"@babel/helpers@^7.19.0", "@babel/helpers@^7.20.7", "@babel/helpers@^7.24.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.0.tgz#a3dd462b41769c95db8091e49cfe019389a9409b" + integrity sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA== dependencies: - "@babel/template" "^7.20.7" - "@babel/traverse" "^7.21.0" - "@babel/types" "^7.21.0" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.0" + "@babel/types" "^7.24.0" -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.14.7", "@babel/parser@^7.19.3", "@babel/parser@^7.20.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.2": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" - integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== +"@babel/parser@^7.14.7", "@babel/parser@^7.19.3", "@babel/parser@^7.20.7", "@babel/parser@^7.24.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" + integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" - integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz#5cd1c87ba9380d0afb78469292c954fee5d2411a" + integrity sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz#d9c85589258539a22a901033853101a6198d4ef1" - integrity sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz#f6652bb16b94f8f9c20c50941e16e9756898dc5d" + integrity sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" - "@babel/plugin-proposal-optional-chaining" "^7.20.7" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-optional-chaining" "^7.23.3" "@babel/plugin-proposal-async-generator-functions@7.20.7", "@babel/plugin-proposal-async-generator-functions@^7.20.1": version "7.20.7" @@ -886,7 +805,7 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.18.9", "@babel/plugin-proposal-optional-chaining@^7.20.7": +"@babel/plugin-proposal-optional-chaining@^7.18.9": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== @@ -904,9 +823,9 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-proposal-private-property-in-object@^7.18.6": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz#19496bd9883dd83c23c7d7fc45dcd9ad02dfa1dc" - integrity sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw== + version "7.21.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c" + integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-create-class-features-plugin" "^7.21.0" @@ -957,11 +876,11 @@ "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-import-assertions@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" - integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz#9c05a7f592982aff1a2768260ad84bcd3f0c77fc" + integrity sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" @@ -1027,13 +946,13 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-transform-arrow-functions@^7.18.6": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz#bea332b0e8b2dab3dafe55a163d8227531ab0551" - integrity sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz#94c6dcfd731af90f27a79509f9ab7fb2120fc38b" + integrity sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-async-to-generator@7.20.7", "@babel/plugin-transform-async-to-generator@^7.18.6": +"@babel/plugin-transform-async-to-generator@7.20.7": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz#dfee18623c8cb31deb796aa3ca84dda9cea94354" integrity sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q== @@ -1042,189 +961,207 @@ "@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-remap-async-to-generator" "^7.18.9" +"@babel/plugin-transform-async-to-generator@^7.18.6": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz#d1f513c7a8a506d43f47df2bf25f9254b0b051fa" + integrity sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw== + dependencies: + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/plugin-transform-block-scoped-functions@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" - integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz#fe1177d715fb569663095e04f3598525d98e8c77" + integrity sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-block-scoping@^7.20.2": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz#e737b91037e5186ee16b76e7ae093358a5634f02" - integrity sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ== + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz#b2d38589531c6c80fbe25e6b58e763622d2d3cf5" + integrity sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-classes@^7.20.2": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz#f469d0b07a4c5a7dbb21afad9e27e57b47031665" - integrity sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-replace-supers" "^7.20.7" - "@babel/helper-split-export-declaration" "^7.18.6" + version "7.23.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz#d08ae096c240347badd68cdf1b6d1624a6435d92" + integrity sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-split-export-declaration" "^7.22.6" globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.18.9": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz#704cc2fd155d1c996551db8276d55b9d46e4d0aa" - integrity sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474" + integrity sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/template" "^7.20.7" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/template" "^7.22.15" "@babel/plugin-transform-destructuring@^7.20.2": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz#8bda578f71620c7de7c93af590154ba331415454" - integrity sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz#8c9ee68228b12ae3dff986e56ed1ba4f3c446311" + integrity sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" - integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz#3f7af6054882ede89c378d0cf889b854a993da50" + integrity sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-duplicate-keys@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" - integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz#664706ca0a5dfe8d066537f99032fc1dc8b720ce" + integrity sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-exponentiation-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" - integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz#ea0d978f6b9232ba4722f3dbecdd18f450babd18" + integrity sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-for-of@^7.18.8": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz#964108c9988de1a60b4be2354a7d7e245f36e86e" - integrity sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ== + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e" + integrity sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-transform-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" - integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc" + integrity sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw== dependencies: - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" - integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz#8214665f00506ead73de157eba233e7381f3beb4" + integrity sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-member-expression-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" - integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz#e37b3f0502289f477ac0e776b05a833d853cabcc" + integrity sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-modules-amd@^7.19.6": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz#3daccca8e4cc309f03c3a0c4b41dc4b26f55214a" - integrity sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz#e19b55436a1416829df0a1afc495deedfae17f7d" + integrity sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw== dependencies: - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-modules-commonjs@^7.19.6": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz#6ff5070e71e3192ef2b7e39820a06fb78e3058e7" - integrity sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4" + integrity sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA== dependencies: - "@babel/helper-module-transforms" "^7.21.2" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" "@babel/plugin-transform-modules-systemjs@^7.19.6": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz#467ec6bba6b6a50634eea61c9c232654d8a4696e" - integrity sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw== + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz#105d3ed46e4a21d257f83a2f9e2ee4203ceda6be" + integrity sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw== dependencies: - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" "@babel/plugin-transform-modules-umd@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" - integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz#5d4395fccd071dfefe6585a4411aa7d6b7d769e9" + integrity sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg== dependencies: - "@babel/helper-module-transforms" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz#626298dd62ea51d452c3be58b285d23195ba69a8" - integrity sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA== + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" + integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.20.5" - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-new-target@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" - integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz#5491bb78ed6ac87e990957cea367eab781c4d980" + integrity sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-object-super@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" - integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz#81fdb636dcb306dd2e4e8fd80db5b2362ed2ebcd" + integrity sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + +"@babel/plugin-transform-optional-chaining@^7.23.3": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz#6acf61203bdfc4de9d4e52e64490aeb3e52bd017" + integrity sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-transform-parameters@^7.20.1", "@babel/plugin-transform-parameters@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz#0ee349e9d1bc96e78e3b37a7af423a4078a7083f" - integrity sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af" + integrity sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-property-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" - integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz#54518f14ac4755d22b92162e4a852d308a560875" + integrity sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-regenerator@^7.18.6": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz#57cda588c7ffb7f4f8483cc83bdcea02a907f04d" - integrity sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz#141afd4a2057298602069fce7f2dc5173e6c561c" + integrity sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - regenerator-transform "^0.15.1" + "@babel/helper-plugin-utils" "^7.22.5" + regenerator-transform "^0.15.2" "@babel/plugin-transform-reserved-words@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" - integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz#4130dcee12bd3dd5705c587947eb715da12efac8" + integrity sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-runtime@7.19.6": version "7.19.6" @@ -1239,55 +1176,55 @@ semver "^6.3.0" "@babel/plugin-transform-shorthand-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" - integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz#97d82a39b0e0c24f8a981568a8ed851745f59210" + integrity sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-spread@^7.19.0": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz#c2d83e0b99d3bf83e07b11995ee24bf7ca09401e" - integrity sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz#41d17aacb12bde55168403c6f2d6bdca563d362c" + integrity sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-transform-sticky-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" - integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz#dec45588ab4a723cb579c609b294a3d1bd22ff04" + integrity sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-template-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" - integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz#5f0f028eb14e50b5d0f76be57f90045757539d07" + integrity sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-typeof-symbol@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" - integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz#9dfab97acc87495c0c449014eb9c547d8966bca4" + integrity sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-unicode-escapes@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" - integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz#1f66d16cab01fab98d784867d24f70c1ca65b925" + integrity sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-unicode-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" - integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz#26897708d8f42654ca4ce1b73e96140fbad879dc" + integrity sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" "@babel/preset-env@7.20.2": version "7.20.2" @@ -1371,9 +1308,9 @@ semver "^6.3.0" "@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + version "0.1.6" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6.tgz#31bcdd8f19538437339d17af00d177d854d9d458" + integrity sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -1394,13 +1331,13 @@ regenerator-runtime "^0.13.11" "@babel/runtime@^7.10.1", "@babel/runtime@^7.11.1", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" - integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.0.tgz#584c450063ffda59697021430cb47101b085951e" + integrity sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw== dependencies: - regenerator-runtime "^0.13.11" + regenerator-runtime "^0.14.0" -"@babel/template@7.20.7", "@babel/template@^7.18.10", "@babel/template@^7.20.7": +"@babel/template@7.20.7": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== @@ -1409,35 +1346,44 @@ "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" -"@babel/traverse@^7.19.3", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.2.tgz#ac7e1f27658750892e815e60ae90f382a46d8e75" - integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.21.1" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.21.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.21.2" - "@babel/types" "^7.21.2" - debug "^4.1.0" +"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.22.15", "@babel/template@^7.24.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" + integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.24.0" + "@babel/types" "^7.24.0" + +"@babel/traverse@^7.19.3", "@babel/traverse@^7.20.12", "@babel/traverse@^7.24.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e" + integrity sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.24.0" + "@babel/types" "^7.24.0" + debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.3", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.4.4": - version "7.21.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1" - integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw== +"@babel/types@^7.18.6", "@babel/types@^7.19.3", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.24.0", "@babel/types@^7.4.4": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" + integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" "@braintree/sanitize-url@^6.0.0": - version "6.0.2" - resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz#6110f918d273fe2af8ea1c4398a88774bb9fc12f" - integrity sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg== + version "6.0.4" + resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" + integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A== "@colors/colors@1.5.0": version "1.5.0" @@ -1473,14 +1419,14 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== -"@es-joy/jsdoccomment@~0.36.1": - version "0.36.1" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.36.1.tgz#c37db40da36e4b848da5fd427a74bae3b004a30f" - integrity sha512-922xqFsTpHs6D0BUiG4toiyPOMc8/jafnWKxz1KWgS4XzKPy2qXf1Pe6UFuNSCQqt6tOuhAWXBNuuyUhJmw9Vg== +"@es-joy/jsdoccomment@~0.42.0": + version "0.42.0" + resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz#59e878708336aaee88c2b34c894f73dbf77ae2b0" + integrity sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw== dependencies: - comment-parser "1.3.1" - esquery "^1.4.0" - jsdoc-type-pratt-parser "~3.1.0" + comment-parser "1.4.1" + esquery "^1.5.0" + jsdoc-type-pratt-parser "~4.0.0" "@esbuild/android-arm64@0.17.8": version "0.17.8" @@ -1599,19 +1545,19 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.4.0": - version "4.5.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.0.tgz#f6f729b02feee2c749f57e334b7a1b5f40a81724" - integrity sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ== +"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== -"@eslint/eslintrc@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.2.tgz#01575e38707add677cf73ca1589abba8da899a02" - integrity sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ== +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.5.1" + espree "^9.6.0" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -1619,10 +1565,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.37.0": - version "8.37.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.37.0.tgz#cf1b5fa24217fe007f6487a26d765274925efa7d" - integrity sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A== +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== "@flowjs/flow.js@^2.14.1": version "2.14.1" @@ -1642,9 +1588,9 @@ integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== "@geoman-io/leaflet-geoman-free@^2.13.0": - version "2.14.2" - resolved "https://registry.yarnpkg.com/@geoman-io/leaflet-geoman-free/-/leaflet-geoman-free-2.14.2.tgz#c84c2115c263f34d11dc0b43859551639fe3d56b" - integrity sha512-6lIyG8RvSVdFjVjiQgBPyNASjymSyqzsiUeBW0pA+q41lB5fAg4SDC6SfJvWdEyDHa81Jb5FWjUkCc9O+u0gbg== + version "2.16.0" + resolved "https://registry.yarnpkg.com/@geoman-io/leaflet-geoman-free/-/leaflet-geoman-free-2.16.0.tgz#c8a92fcc2cdd5770ebf43f8ef9f03cc8ef842359" + integrity sha512-BnKAAoTXraWVFfhX/0gT/iBgAz1BPfpbdQ9dJamEFI4lIku9UNXXluu/E0k7YkZETq0tENX2GPnKLB4p+VgrSw== dependencies: "@turf/boolean-contains" "^6.5.0" "@turf/kinks" "^6.5.0" @@ -1653,13 +1599,13 @@ lodash "4.17.21" polygon-clipping "0.15.3" -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" minimatch "^3.0.5" "@humanwhocodes/module-importer@^1.0.1": @@ -1667,18 +1613,30 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" + integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== "@iplab/ngx-color-picker@^15.0.2": - version "15.0.2" - resolved "https://registry.yarnpkg.com/@iplab/ngx-color-picker/-/ngx-color-picker-15.0.2.tgz#856bf2571378e792e5e42b566ac1aa79a9262763" - integrity sha512-wum0Hg4Ky/6mhvzolEpFpjGckOjN8L2nkXvy3mWUVclFHP9MZqqgpJaxghtax7/tMdEWQnwQI3PYsNyKfF15ug== + version "15.1.0" + resolved "https://registry.yarnpkg.com/@iplab/ngx-color-picker/-/ngx-color-picker-15.1.0.tgz#7520cb4c58f06ec68006b103214f9a649d14b15f" + integrity sha512-pL/GxDcMQpOe5CVoRa2iNgpnYS4N+S6Gr/7RkCnOJsWEm+OOcf4K4X2BxhKZK+uF6jBFata+u8pwJv9VgCitnQ== dependencies: tslib "^2.3.0" +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1708,37 +1666,37 @@ "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== +"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: - "@jridgewell/set-array" "^1.0.1" + "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== -"@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== +"@jridgewell/source-map@^0.3.2", "@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" -"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -1748,13 +1706,13 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" "@juggle/resize-observer@^3.4.0": version "3.4.0" @@ -2558,18 +2516,18 @@ tslib "^2.1.0" "@mdi/svg@^7.2.96": - version "7.2.96" - resolved "https://registry.yarnpkg.com/@mdi/svg/-/svg-7.2.96.tgz#6c182628ed722a85055c3795e7d4ca6d4f2f139c" - integrity sha512-rxzuSL2RSt/pWWnFnUFQi5GJArm2tHMhx20Gee3Ydn+xT2bqbR4syfgdPrq2b+j+n5LjC7C8Fb1QDM6LKeF0cA== + version "7.4.47" + resolved "https://registry.yarnpkg.com/@mdi/svg/-/svg-7.4.47.tgz#f8e5516aae129764a76d1bb2f27e55bee03e6e90" + integrity sha512-WQ2gDll12T9WD34fdRFgQVgO8bag3gavrAgJ0frN4phlwdJARpE6gO1YvLEMJR0KKgoc+/Ea/A0Pp11I00xBvw== "@messageformat/core@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@messageformat/core/-/core-3.1.0.tgz#d4d2f5c3555228a6b5980b122a02b53dfc6458bd" - integrity sha512-UxAnjecnRG4u2iaggwIyylYPHmk5BTErJcKmWyAKTXqYgSW1bFLp4D7fIzuh6bk17Qfcmf3qtufdrstCB23nBA== + version "3.3.0" + resolved "https://registry.yarnpkg.com/@messageformat/core/-/core-3.3.0.tgz#31edd52a5f7d017adad85c929809f07741dcfd3f" + integrity sha512-YcXd3remTDdeMxAlbvW6oV9d/01/DZ8DHUFwSttO3LMzIZj3iO0NRw+u1xlsNNORFI+u0EQzD52ZX3+Udi0T3g== dependencies: "@messageformat/date-skeleton" "^1.0.0" "@messageformat/number-skeleton" "^1.0.0" - "@messageformat/parser" "^5.0.0" + "@messageformat/parser" "^5.1.0" "@messageformat/runtime" "^3.0.1" make-plural "^7.0.0" safe-identifier "^0.4.1" @@ -2580,14 +2538,14 @@ integrity sha512-jPXy8fg+WMPIgmGjxSlnGJn68h/2InfT0TNSkVx0IGXgp4ynnvYkbZ51dGWmGySEK+pBiYUttbQdu5XEqX5CRg== "@messageformat/number-skeleton@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@messageformat/number-skeleton/-/number-skeleton-1.1.0.tgz#eb636738da8abbd35ccbeb84f7d84d63302aeb61" - integrity sha512-F0Io+GOSvFFxvp9Ze3L5kAoZ2NnOAT0Mr/jpGNd3fqo8A0t4NxNIAcCdggtl2B/gN2ErkIKSBVPrF7xcW1IGvA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/@messageformat/number-skeleton/-/number-skeleton-1.2.0.tgz#e7c245c41a1b2722bc59dad68f4d454f761bc9b4" + integrity sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg== -"@messageformat/parser@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@messageformat/parser/-/parser-5.0.0.tgz#5737e69d7d4a469998b527710f1891174fc1b262" - integrity sha512-WiDKhi8F0zQaFU8cXgqq69eYFarCnTVxKcvhAONufKf0oUxbqLMW6JX6rV4Hqh+BEQWGyKKKHY4g1XA6bCLylA== +"@messageformat/parser@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@messageformat/parser/-/parser-5.1.0.tgz#05e4851c782d633ad735791dd0a68ee65d2a7201" + integrity sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ== dependencies: moo "^0.5.1" @@ -2624,10 +2582,10 @@ resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-15.2.1.tgz#439ac075b2dcb9f304f0b7009182cc5049c7988a" integrity sha512-YtA8rWAglPuf4CSStrFAxaprTSYE+DREGrJFc3WvZLcF5XrwVK+H4CC4Pmz07iYsG1TXShR4bWp1fbGw1cmBKw== -"@ngtools/webpack@15.2.8": - version "15.2.8" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-15.2.8.tgz#df8fb9300ccf94cab8f8ad69fb16fd31181e6c82" - integrity sha512-BJexeT4FxMtToVBGa3wdl6rrkYXgilP0kkSH4Qzu4MPlLPbeBSr4XQalQriewlpC2uzG0r2SJfrAe2eDhtSykA== +"@ngtools/webpack@15.2.10": + version "15.2.10" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-15.2.10.tgz#8118450206ae9398d81ca2eebe1b369321ac5583" + integrity sha512-ZExB4rKh/Saad31O/Ofd2XvRuILuCNTYs0+qJL697Be2pzeewvzBhE4Xe1Mm7Jg13aWSPeuIdzSGOqCdwxxxFQ== "@ngx-translate/core@^14.0.0": version "14.0.0" @@ -2680,13 +2638,12 @@ semver "^7.3.5" "@npmcli/git@^4.0.0": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-4.0.3.tgz#354db5fe1f29696303638e191d8538ee9b01b4bb" - integrity sha512-8cXNkDIbnXPVbhXMmQ7/bklCAjtmPaXfI9aEM4iH+xSuEHINLMHhlfESvVwdqmHJRJkR48vNJTSUvoF6GRPSFA== + version "4.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-4.1.0.tgz#ab0ad3fd82bc4d8c1351b6c62f0fa56e8fe6afa6" + integrity sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ== dependencies: "@npmcli/promise-spawn" "^6.0.0" lru-cache "^7.4.4" - mkdirp "^1.0.4" npm-pick-manifest "^8.0.0" proc-log "^3.0.0" promise-inflight "^1.0.1" @@ -2723,9 +2680,9 @@ which "^3.0.0" "@npmcli/run-script@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-6.0.0.tgz#f89e322c729e26ae29db6cc8cc76559074aac208" - integrity sha512-ql+AbRur1TeOdl1FY+RAwGW9fcr4ZwiVKabdvm93mujGREVuVLbdkXRJDrkTXSdCjaxYydr1wlA2v67jxWG5BQ== + version "6.0.2" + resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-6.0.2.tgz#a25452d45ee7f7fb8c16dfaf9624423c0c0eb885" + integrity sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA== dependencies: "@npmcli/node-gyp" "^3.0.0" "@npmcli/promise-spawn" "^6.0.0" @@ -2733,15 +2690,54 @@ read-package-json-fast "^3.0.0" which "^3.0.0" -"@schematics/angular@15.2.8": - version "15.2.8" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-15.2.8.tgz#d845903f1cc477d299f968eb5bc40a9855cfd911" - integrity sha512-F49IEzCFxQlpaMIgTO/wF1l/CLQKif7VaiDdyiTKOeT22IMmyd61FUmWDyZYfCBqMlvBmvDGx64HaHWes1HYCg== +"@one-ini/wasm@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@one-ini/wasm/-/wasm-0.1.1.tgz#6013659736c9dbfccc96e8a9c2b3de317df39323" + integrity sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@schematics/angular@15.2.10": + version "15.2.10" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-15.2.10.tgz#fa6c05f37ba82422abd6b3f13a2fc78ec7a4eb3d" + integrity sha512-eLdyP+T1TueNQ8FCP7sP+tt8z+YQ1BINsJsyAyoJT/XZjcCV7LUxgDIU94/kuvIotmJ2xTuFWHFPfAY+CN3duQ== dependencies: - "@angular-devkit/core" "15.2.8" - "@angular-devkit/schematics" "15.2.8" + "@angular-devkit/core" "15.2.10" + "@angular-devkit/schematics" "15.2.10" jsonc-parser "3.2.0" +"@sigstore/bundle@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@sigstore/bundle/-/bundle-1.1.0.tgz#17f8d813b09348b16eeed66a8cf1c3d6bd3d04f1" + integrity sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog== + dependencies: + "@sigstore/protobuf-specs" "^0.2.0" + +"@sigstore/protobuf-specs@^0.2.0": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz#be9ef4f3c38052c43bd399d3f792c97ff9e2277b" + integrity sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A== + +"@sigstore/sign@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@sigstore/sign/-/sign-1.0.0.tgz#6b08ebc2f6c92aa5acb07a49784cb6738796f7b4" + integrity sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA== + dependencies: + "@sigstore/bundle" "^1.1.0" + "@sigstore/protobuf-specs" "^0.2.0" + make-fetch-happen "^11.0.1" + +"@sigstore/tuf@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@sigstore/tuf/-/tuf-1.0.3.tgz#2a65986772ede996485728f027b0514c0b70b160" + integrity sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg== + dependencies: + "@sigstore/protobuf-specs" "^0.2.0" + tuf-js "^1.1.7" + "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" @@ -2788,16 +2784,22 @@ integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" - integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@tufjs/models@1.0.0": +"@tufjs/canonical-json@1.0.0": version "1.0.0" - resolved "https://registry.yarnpkg.com/@tufjs/models/-/models-1.0.0.tgz#5a5784e8770b7d014b5f87bff35af1f71fdebf1f" - integrity sha512-RRMu4uMxWnZlxaIBxahSb2IssFZiu188sndesZflWOe1cA/qUqtemSIoBWbuVKPvvdktapImWNnKpBcc+VrCQw== + resolved "https://registry.yarnpkg.com/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz#eade9fd1f537993bc1f0949f3aea276ecc4fab31" + integrity sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ== + +"@tufjs/models@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tufjs/models/-/models-1.0.4.tgz#5a689630f6b9dbda338d4b208019336562f176ef" + integrity sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A== dependencies: - minimatch "^6.1.0" + "@tufjs/canonical-json" "1.0.0" + minimatch "^9.0.0" "@turf/bbox@*", "@turf/bbox@^6.5.0": version "6.5.0" @@ -2950,42 +2952,42 @@ "@turf/meta" "^6.5.0" "@types/ace-diff@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@types/ace-diff/-/ace-diff-2.1.1.tgz#1c08919aae8f9c429fcb139dc564c89dd093cbee" - integrity sha512-O27fCo2Y0njNslOFSewyRhTyXfLhVhleEU5aTI6ZqFTKENJ8L/LA+Y+ZfcHsHTtwrTWjBXqORmqEHH6Qytqw1w== + version "2.1.4" + resolved "https://registry.yarnpkg.com/@types/ace-diff/-/ace-diff-2.1.4.tgz#0bf9952c9b23fb3cb6f5cf96f1e8bbed8f603fcd" + integrity sha512-Jd9J35hi9PdsQzAAXWzPlXTuxRxnxuaNBMzBNts3EUDoQ8yuWp4Y36GjPASke8D6yVwKrapOnAaVp3km/CxPRw== "@types/body-parser@*": - version "1.19.2" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" - integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + version "1.19.5" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== dependencies: "@types/connect" "*" "@types/node" "*" "@types/bonjour@^3.5.9": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" - integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" + integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== dependencies: "@types/node" "*" "@types/canvas-gauges@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@types/canvas-gauges/-/canvas-gauges-2.1.4.tgz#063881264597d098e78cf5ad921e8ed20ae2ad16" - integrity sha512-JTvqQWrqcrgzCp/9+uzwUvPef2qAEnBJvm+bL9kvulzhXapDeNaGQXCIAZp+hOryusjOyndvP1za2HZooUV0XA== + version "2.1.8" + resolved "https://registry.yarnpkg.com/@types/canvas-gauges/-/canvas-gauges-2.1.8.tgz#5bdd199c598fd45f8618127bec2e2f4e49d7477f" + integrity sha512-sbxlEPEPnEYfvzC/yPIJZNkxKfAJaI45dxnQrkg3g2l3+1lWX6lwduRo8+hrsDw7VdJ5ijuRi1sQ7XBFu1R2qg== "@types/connect-history-api-fallback@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" - integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" + integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" "@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== dependencies: "@types/node" "*" @@ -2995,32 +2997,32 @@ integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== "@types/cors@^2.8.12": - version "2.8.13" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.13.tgz#b8ade22ba455a1b8cb3b5d3f35910fd204f84f94" - integrity sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA== + version "2.8.17" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" + integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== dependencies: "@types/node" "*" "@types/eslint-scope@^3.7.3": - version "3.7.4" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" - integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "8.21.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.1.tgz#110b441a210d53ab47795124dbc3e9bb993d1e7c" - integrity sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ== + version "8.56.5" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.5.tgz#94b88cab77588fcecdd0771a6d576fa1c0af9d02" + integrity sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" - integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== +"@types/estree@*", "@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/estree@^0.0.51": version "0.0.51" @@ -3028,18 +3030,19 @@ integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": - version "4.17.33" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz#de35d30a9d637dc1450ad18dd583d75d5733d543" - integrity sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA== + version "4.17.43" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz#10d8444be560cb789c4735aea5eac6e5af45df54" + integrity sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" + "@types/send" "*" "@types/express@*", "@types/express@^4.17.13": - version "4.17.17" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" - integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.33" @@ -3054,14 +3057,14 @@ "@types/jquery" "*" "@types/flowjs@^2.13.9": - version "2.13.9" - resolved "https://registry.yarnpkg.com/@types/flowjs/-/flowjs-2.13.9.tgz#b280e977a7b9d8e26d4a09ceab43e23ad2f148e5" - integrity sha512-iItTP2tOL9NalAR3C9o+psuvoBLwmEFPf1xr9BlDojyynizLBTtLw2aqrlaiZJW4z/QUwz7ryXFm4FjxjWatTQ== + version "2.13.13" + resolved "https://registry.yarnpkg.com/@types/flowjs/-/flowjs-2.13.13.tgz#91bb164ad4d63be6b9ad569171122c761526dc4b" + integrity sha512-wDAWxKbtsCXzlIqKMyy+lN3co9PIhJyQBRvx0tUefG0FDRAdFd4hvL8RFyLj8NxvBNoORWZ2exzNH5Gg+QpaAQ== "@types/geojson@*": - version "7946.0.10" - resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.10.tgz#6dfbf5ea17142f7f9a043809f1cd4c448cb68249" - integrity sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA== + version "7946.0.14" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" + integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg== "@types/geojson@7946.0.8": version "7946.0.8" @@ -3069,50 +3072,55 @@ integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA== "@types/hammerjs@^2.0.40": - version "2.0.41" - resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.41.tgz#f6ecf57d1b12d2befcce00e928a6a097c22980aa" - integrity sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA== + version "2.0.45" + resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.45.tgz#ffa764bb68a66c08db6efb9c816eb7be850577b1" + integrity sha512-qkcUlZmX6c4J8q45taBKTL3p+LbITgyx7qhlPYOdOHZB7B31K0mXbP5YA7i7SgDeEGuI9MnumiKPEMrxg8j3KQ== + +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== "@types/http-proxy@^1.17.8": - version "1.17.10" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.10.tgz#e576c8e4a0cc5c6a138819025a88e167ebb38d6c" - integrity sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g== + version "1.17.14" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" + integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== dependencies: "@types/node" "*" "@types/jasmine@*": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-4.3.1.tgz#2d8ab5601c2fe7d9673dcb157e03f128ab5c5fff" - integrity sha512-Vu8l+UGcshYmV1VWwULgnV/2RDbBaO6i2Ptx7nd//oJPIZGhoI1YLST4VKagD2Pq/Bc2/7zvtvhM7F3p4SN7kQ== + version "5.1.4" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-5.1.4.tgz#0de3f6ca753e10d1600ce1864ae42cfd47cf9924" + integrity sha512-px7OMFO/ncXxixDe1zR13V1iycqWae0MxTaw62RpFlksUi5QuNWgQJFkTQjIOvrmutJbI7Fp2Y2N1F6D2R4G6w== "@types/jasmine@~3.10.2": - version "3.10.7" - resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.10.7.tgz#57b8c6892fa2f4696fbb56851cd99649c781376c" - integrity sha512-brLuHhITMz4YV2IxLstAJtyRJgtWfLqFKiqiJFvFWMSmydpAmn42CE4wfw7ywkSk02UrufhtzipTcehk8FctoQ== + version "3.10.18" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.10.18.tgz#d442369fd2d06d5b2c607fae51c257b2f9caa94e" + integrity sha512-jOk52a1Kz+1oU5fNWwAcNe64/GsE7r/Q6ronwDox0D3ETo/cr4ICMQyeXrj7G6FPW1n8YjRoAZA2F0XBr6GicQ== "@types/jasminewd2@^2.0.10": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@types/jasminewd2/-/jasminewd2-2.0.10.tgz#ae31c237aa6421bde30f1058b1d20f4577e54443" - integrity sha512-J7mDz7ovjwjc+Y9rR9rY53hFWKATcIkrr9DwQWmOas4/pnIPJTXawnzjwpHm3RSxz/e3ZVUvQ7cRbd5UQLo10g== + version "2.0.13" + resolved "https://registry.yarnpkg.com/@types/jasminewd2/-/jasminewd2-2.0.13.tgz#0b60c1fcd06277ea97efbbad5a02e0c1a4a8996a" + integrity sha512-aJ3wj8tXMpBrzQ5ghIaqMisD8C3FIrcO6sDKHqFbuqAsI7yOxj0fA7MrRCPLZHIVUjERIwsMmGn/vB0UQ9u0Hg== dependencies: "@types/jasmine" "*" -"@types/jquery@*", "@types/jquery@^3.5.14", "@types/jquery@^3.5.16": - version "3.5.16" - resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.16.tgz#632131baf30951915b0317d48c98e9890bdf051d" - integrity sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw== +"@types/jquery@*", "@types/jquery@^3.5.16", "@types/jquery@^3.5.29": + version "3.5.29" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.29.tgz#3c06a1f519cd5fc3a7a108971436c00685b5dcea" + integrity sha512-oXQQC9X9MOPRrMhPHHOsXqeQDnWeCDT3PelUIg/Oy8FAbzSZtFHRjc7IpbfFVmpLtJ+UOoywpRsuO5Jxjybyeg== dependencies: "@types/sizzle" "*" "@types/js-beautify@^1.13.3": - version "1.13.3" - resolved "https://registry.yarnpkg.com/@types/js-beautify/-/js-beautify-1.13.3.tgz#53839bb5b766d0fb45e87386100bb3bcbb7dca9d" - integrity sha512-ucIPw5gmNyvRKi6mpeojlqp+T+6ZBJeU+kqMDnIEDlijEU4QhLTon90sZ3cz9HZr+QTwXILjNsMZImzA7+zuJA== + version "1.14.3" + resolved "https://registry.yarnpkg.com/@types/js-beautify/-/js-beautify-1.14.3.tgz#6ced76f79935e37e0d613110dea369881d93c1ff" + integrity sha512-FMbQHz+qd9DoGvgLHxeqqVPaNRffpIu5ZjozwV8hf9JAGpIOzuAf4wGbRSo8LNITHqGjmmVjaMggTT5P4v4IHg== "@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/json5@^0.0.29": version "0.0.29" @@ -3120,86 +3128,93 @@ integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/leaflet-polylinedecorator@^1.6.1": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.1.tgz#b6522f9dae52146bf73da249e4bedfbab200c6e4" - integrity sha512-9etweJ2U4SWqcV/AR3i0NdWJByeMn6+zMUNlO6jVbpL8UI6qrMKybu8v9/s6UR4oXvsV4lZT6vzAsNAAMq5Ssg== + version "1.6.4" + resolved "https://registry.yarnpkg.com/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.4.tgz#2270b84585bd28bbf1fef237be8480196c44ac06" + integrity sha512-meH/jC58Drt/9aqLhuzMCUQjHgMTud+UuQBK5gT6E8M6OfM/rftz/VgvdxOCCAQC9isrp4pqahDgEswesb5X3A== dependencies: "@types/leaflet" "*" "@types/leaflet-providers@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@types/leaflet-providers/-/leaflet-providers-1.2.1.tgz#620669b828959740a2d8572e0c0288a2382d3564" - integrity sha512-uNyuXiNV2q3fmgNjQji2P6RjQISmL40bbOL91/3OAwiE3XhkLKPmSAtAcfe11MAIz45iEjdFZJWppq9QyfnPIw== + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/leaflet-providers/-/leaflet-providers-1.2.4.tgz#284e8a197d4c2dbfeda436842e03b2adb502be16" + integrity sha512-4wYEpreixp+G5t510s202eQ5eubOmxHevIfCNrzUZbzp50XQsC9lSetX7MnPl3ANRJnUBbCWOzZ9EQFiH0Jm+g== dependencies: "@types/leaflet" "*" "@types/leaflet.gridlayer.googlemutant@^0.4.6": - version "0.4.6" - resolved "https://registry.yarnpkg.com/@types/leaflet.gridlayer.googlemutant/-/leaflet.gridlayer.googlemutant-0.4.6.tgz#86d3ba9d432dec29b4796e37d815c233680e7fcb" - integrity sha512-L0J7NadcZp5bcKQrv4DVlsEbQ90xLsOKScckAMnxoghh/wogk0GVkauYOYHBKeKDkx9qkMRzTf8oO+fKeYD7oQ== + version "0.4.9" + resolved "https://registry.yarnpkg.com/@types/leaflet.gridlayer.googlemutant/-/leaflet.gridlayer.googlemutant-0.4.9.tgz#9090ddf4578ce631d22b8aafc5ed12525b4fbf90" + integrity sha512-u/5Avs1KKkeABRDixGbGp2ldFs67+fYIATpkvvFgN+LQPNfq7dFd5adkksshiQBfYJ4SaQg1VJgN2dNirIC0aQ== dependencies: "@types/leaflet" "*" "@types/leaflet.markercluster@^1.5.1": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.1.tgz#d039ada408a30bda733b19a24cba89b81f0ace4b" - integrity sha512-gzJzP10qO6Zkts5QNVmSAEDLYicQHTEBLT9HZpFrJiSww9eDAs5OWHvIskldf41MvDv1gbMukuEBQEawHn+wtA== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.4.tgz#2ab43417cf3f6a42d0f1baf4e1c8f659cf1dc3a1" + integrity sha512-tfMP8J62+wfsVLDLGh5Zh1JZxijCaBmVsMAX78MkLPwvPitmZZtSin5aWOVRhZrCS+pEOZwNzexbfWXlY+7yjg== dependencies: "@types/leaflet" "*" -"@types/leaflet@*": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.9.1.tgz#a220706b02c6024951d7fc2959d530c6941c4224" - integrity sha512-lYawM3I3lLO6rmBASaqdGgY6zUL4YHr3H79/axx7FNYyPXuj0P1DZHbkNo8Itbv0i7Y9EryLWtDXXROMygXhRA== - dependencies: - "@types/geojson" "*" - -"@types/leaflet@^1.8.0": - version "1.9.3" - resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.9.3.tgz#7aac302189eb3aa283f444316167995df42a5467" - integrity sha512-Caa1lYOgKVqDkDZVWkto2Z5JtVo09spEaUt2S69LiugbBpoqQu92HYFMGUbYezZbnBkyOxMNPXHSgRrRY5UyIA== +"@types/leaflet@*", "@types/leaflet@^1.8.0": + version "1.9.8" + resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.9.8.tgz#32162a8eaf305c63267e99470b9603b5883e63e8" + integrity sha512-EXdsL4EhoUtGm2GC2ZYtXn+Fzc6pluVgagvo2VC1RHWToLGlTRwVYoDpqS/7QXa01rmDyBjJk3Catpf60VMkwg== dependencies: "@types/geojson" "*" "@types/lodash@^4.14.192": - version "4.14.192" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.192.tgz#5790406361a2852d332d41635d927f1600811285" - integrity sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A== + version "4.17.0" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3" + integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA== "@types/marked@^4.0.8": - version "4.0.8" - resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.8.tgz#b316887ab3499d0a8f4c70b7bd8508f92d477955" - integrity sha512-HVNzMT5QlWCOdeuBsgXP8EZzKUf0+AXzN+sLmjvaB3ZlLqO+e4u0uXrdw9ub69wBKFs+c6/pA4r9sy6cCDvImw== + version "4.3.2" + resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.3.2.tgz#e2e0ad02ebf5626bd215c5bae2aff6aff0ce9eac" + integrity sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w== "@types/mime@*": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" - integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" + integrity sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw== + +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== "@types/mousetrap@^1.6.9": - version "1.6.11" - resolved "https://registry.yarnpkg.com/@types/mousetrap/-/mousetrap-1.6.11.tgz#ef9620160fdcefcb85bccda8aaa3e84d7429376d" - integrity sha512-F0oAily9Q9QQpv9JKxKn0zMKfOo36KHCW7myYsmUyf2t0g+sBTbG3UleTPoguHdE1z3GLFr3p7/wiOio52QFjQ== + version "1.6.15" + resolved "https://registry.yarnpkg.com/@types/mousetrap/-/mousetrap-1.6.15.tgz#f144a0c539a4cef553a631824651d48267e53c86" + integrity sha512-qL0hyIMNPow317QWW/63RvL1x5MVMV+Ru3NaY9f/CuEpCqrmb7WeuK2071ZY5hczOnm38qExWM2i2WtkXLSqFw== + +"@types/node-forge@^1.3.0": + version "1.3.11" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" + integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== + dependencies: + "@types/node" "*" "@types/node@*", "@types/node@>=10.0.0": - version "18.14.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.5.tgz#4a13a6445862159303fc38586598a9396fc408b3" - integrity sha512-CRT4tMK/DHYhw1fcCEBwME9CSaZNclxfzVMe7GsO6ULSwsttbj70wSiX6rZdIjGblu93sTJxLdhNIT85KKI7Qw== + version "20.11.28" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.28.tgz#4fd5b2daff2e580c12316e457473d68f15ee6f66" + integrity sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA== + dependencies: + undici-types "~5.26.4" "@types/node@~18.15.11": - version "18.15.11" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.11.tgz#b3b790f09cb1696cffcec605de025b088fa4225f" - integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q== + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== "@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== "@types/prop-types@*": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + version "15.7.11" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" + integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== "@types/q@^0.0.32": version "0.0.32" @@ -3207,19 +3222,19 @@ integrity sha512-qYi3YV9inU/REEfxwVcGZzbS3KG/Xs90lv0Pr+lDtuVjBPGd1A+eciXzVSaRvLify132BfcvhvEjeVahrUl0Ug== "@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + version "6.9.12" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.12.tgz#afa96b383a3a6fdc859453a1892d41b607fc7756" + integrity sha512-bZcOkJ6uWrL0Qb2NAWKa7TBU+mJHPzhx9jjLL1KHF+XpzEcR7EXHvjbHlGtR/IsP1vyPrehuS6XqkmaePy//mg== "@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/raphael@^2.3.2": - version "2.3.3" - resolved "https://registry.yarnpkg.com/@types/raphael/-/raphael-2.3.3.tgz#d264b148bc100ef401a5e13159fd97861cd69e17" - integrity sha512-Rhvq0q6wzyvipejki/9w87/pgapyE+s3gO66tdl1oD3qDrow+ek+4vVYAbRkeL58HCCK9EOZKwyjqYJ/TFkmtQ== + version "2.3.9" + resolved "https://registry.yarnpkg.com/@types/raphael/-/raphael-2.3.9.tgz#d53bb8930431524f42987a8a19815c0d42a61eb5" + integrity sha512-K1dZwoLNvEN+mvleFU/t2swG9Z4SE5Vub7dA5wDYojH0bVTQ8ZAP+lNsl91t1njdu/B+roSEL4QXC67I7Hpiag== "@types/react-dom@17.0.11": version "17.0.11" @@ -3229,9 +3244,9 @@ "@types/react" "*" "@types/react-transition-group@^4.2.0": - version "4.4.5" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416" - integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA== + version "4.4.10" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" + integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q== dependencies: "@types/react" "*" @@ -3250,44 +3265,53 @@ integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== "@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + version "0.16.8" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" + integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== "@types/selenium-webdriver@^3.0.0": - version "3.0.20" - resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.20.tgz#448771a0608ebf1c86cb5885914da6311e323c3a" - integrity sha512-6d8Q5fqS9DWOXEhMDiF6/2FjyHdmP/jSTAUyeQR7QwrFeNmYyzmvGxD5aLIHL445HjWgibs0eAig+KPnbaesXA== + version "3.0.26" + resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.26.tgz#fc7d87d580affa2e52685b2e881bc201819a5836" + integrity sha512-dyIGFKXfUFiwkMfNGn1+F6b80ZjR3uSYv1j6xVJSDlft5waZ2cwkHW4e7zNzvq7hiEackcgvBpmnXZrI1GltPg== "@types/semver@^7.3.12": - version "7.3.13" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" - integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + +"@types/send@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" "@types/serve-index@^1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" - integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + version "1.9.4" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" + integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== dependencies: "@types/express" "*" "@types/serve-static@*", "@types/serve-static@^1.13.10": - version "1.15.1" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.1.tgz#86b1753f0be4f9a1bee68d459fcda5be4ea52b5d" - integrity sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ== + version "1.15.5" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.5.tgz#15e67500ec40789a1e8c9defc2d32a896f05b033" + integrity sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ== dependencies: + "@types/http-errors" "*" "@types/mime" "*" "@types/node" "*" "@types/sizzle@*": - version "2.3.3" - resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" - integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== + version "2.3.8" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.8.tgz#518609aefb797da19bf222feb199e8f653ff7627" + integrity sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg== "@types/sockjs@^0.3.33": - version "0.3.33" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" - integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + version "0.3.36" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" + integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== dependencies: "@types/node" "*" @@ -3304,9 +3328,9 @@ integrity sha512-Jxo2/uif1WpkabfyvWpFmPWFPDdwKUmyL7xWzjtxNALEu2pgce+eISjbf0Vr+SsK/D9savO5kTRcf+COLK5eiQ== "@types/tinycolor2@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.3.tgz#ed4a0901f954b126e6a914b4839c77462d56e706" - integrity sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ== + version "1.4.6" + resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.6.tgz#670cbc0caf4e58dd61d1e3a6f26386e473087f06" + integrity sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw== "@types/tooltipster@^0.0.31": version "0.0.31" @@ -3316,9 +3340,9 @@ "@types/jquery" "*" "@types/ws@^8.5.1": - version "8.5.4" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" - integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg== + version "8.5.10" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" + integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== dependencies: "@types/node" "*" @@ -3464,6 +3488,11 @@ "@typescript-eslint/types" "5.57.0" eslint-visitor-keys "^3.3.0" +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -3472,21 +3501,44 @@ "@webassemblyjs/helper-numbers" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.11.5": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/floating-point-hex-parser@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + "@webassemblyjs/helper-api-error@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + "@webassemblyjs/helper-buffer@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== + "@webassemblyjs/helper-numbers@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" @@ -3496,11 +3548,25 @@ "@webassemblyjs/helper-api-error" "1.11.1" "@xtuc/long" "4.2.2" +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@xtuc/long" "4.2.2" + "@webassemblyjs/helper-wasm-bytecode@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== + "@webassemblyjs/helper-wasm-section@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" @@ -3511,6 +3577,16 @@ "@webassemblyjs/helper-wasm-bytecode" "1.11.1" "@webassemblyjs/wasm-gen" "1.11.1" +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/ieee754@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" @@ -3518,6 +3594,13 @@ dependencies: "@xtuc/ieee754" "^1.2.0" +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + "@webassemblyjs/leb128@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" @@ -3525,11 +3608,23 @@ dependencies: "@xtuc/long" "4.2.2" +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== + dependencies: + "@xtuc/long" "4.2.2" + "@webassemblyjs/utf8@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + "@webassemblyjs/wasm-edit@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" @@ -3544,6 +3639,20 @@ "@webassemblyjs/wasm-parser" "1.11.1" "@webassemblyjs/wast-printer" "1.11.1" +"@webassemblyjs/wasm-edit@^1.11.5": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + "@webassemblyjs/wasm-gen@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" @@ -3555,6 +3664,17 @@ "@webassemblyjs/leb128" "1.11.1" "@webassemblyjs/utf8" "1.11.1" +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + "@webassemblyjs/wasm-opt@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" @@ -3565,6 +3685,16 @@ "@webassemblyjs/wasm-gen" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wasm-parser@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" @@ -3577,6 +3707,18 @@ "@webassemblyjs/leb128" "1.11.1" "@webassemblyjs/utf8" "1.11.1" +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.11.5": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + "@webassemblyjs/wast-printer@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" @@ -3585,6 +3727,14 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@xtuc/long" "4.2.2" + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -3610,6 +3760,11 @@ abbrev@^1.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abbrev@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" + integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -3630,10 +3785,10 @@ ace-diff@^3.0.3: dependencies: diff-match-patch "^1.0.5" -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== +acorn-import-assertions@^1.7.6, acorn-import-assertions@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" + integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== acorn-jsx@^5.3.2: version "5.3.2" @@ -3641,14 +3796,14 @@ acorn-jsx@^5.3.2: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== -acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0: - version "8.8.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" - integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== adjust-sourcemap-loader@^4.0.0: version "4.0.0" @@ -3659,9 +3814,9 @@ adjust-sourcemap-loader@^4.0.0: regex-parser "^2.2.11" adm-zip@^0.5.2: - version "0.5.10" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.10.tgz#4a51d5ab544b1f5ce51e1b9043139b639afff45b" - integrity sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ== + version "0.5.12" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.12.tgz#87786328e91d54b37358d8a50f954c4cd73ba60b" + integrity sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ== agent-base@6, agent-base@^6.0.2: version "6.0.2" @@ -3678,12 +3833,10 @@ agent-base@^4.3.0: es6-promisify "^5.0.0" agentkeepalive@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" - integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA== + version "4.5.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== dependencies: - debug "^4.1.0" - depd "^1.1.2" humanize-ms "^1.2.1" aggregate-error@^3.0.0: @@ -3706,14 +3859,14 @@ ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv-keywords@^5.0.0: +ajv-keywords@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== dependencies: fast-deep-equal "^3.1.3" -ajv@8.12.0, ajv@^8.0.0, ajv@^8.8.0: +ajv@8.12.0, ajv@^8.0.0, ajv@^8.9.0: version "8.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== @@ -3723,7 +3876,7 @@ ajv@8.12.0, ajv@^8.0.0, ajv@^8.8.0: require-from-string "^2.0.2" uri-js "^4.2.2" -ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -3741,9 +3894,9 @@ angular-gridster2@~15.0.4: tslib "^2.4.0" angular2-hotkeys@^13.1.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/angular2-hotkeys/-/angular2-hotkeys-13.1.0.tgz#fdbb30b72dc512379e3dea5d44d98593cdfb18a9" - integrity sha512-irsQLLiHCHqz73ocDV8N5K7Zel7mJyLQHwLrRePOwUumQfyBc2TTuO+ccdQAAM7/RK+IdT6P5YoiP0FEbA19Uw== + version "13.4.0" + resolved "https://registry.yarnpkg.com/angular2-hotkeys/-/angular2-hotkeys-13.4.0.tgz#a96676466936556655cd64f92e1f5cd3aeac8e10" + integrity sha512-WvkouvdXtTYw3tpuaoEVF+ue41pvI2XSa8m4tVRPLzAblT/f7PG0uQO4npyjVw3oDIc7qnFkQR+oqGl1KM1eow== dependencies: "@types/mousetrap" "^1.6.9" mousetrap "^1.6.5" @@ -3776,6 +3929,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -3795,6 +3953,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + ansidec@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/ansidec/-/ansidec-0.3.4.tgz#e12d267d6b1f122d2da5b98fe0de1f98d14ac62b" @@ -3813,6 +3976,11 @@ anymatch@~3.1.2: resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== +are-docs-informative@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/are-docs-informative/-/are-docs-informative-0.0.2.tgz#387f0e93f5d45280373d387a59d34c96db321963" + integrity sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig== + are-we-there-yet@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" @@ -3855,25 +4023,28 @@ array-back@^4.0.1, array-back@^4.0.2: resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== +array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== + dependencies: + call-bind "^1.0.5" + is-array-buffer "^3.0.4" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-flatten@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-includes@^3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" - integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== +array-includes@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - get-intrinsic "^1.1.3" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" is-string "^1.0.7" array-union@^1.0.1: @@ -3893,26 +4064,62 @@ array-uniq@^1.0.1: resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== -array.prototype.flat@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" - integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== +array.prototype.filter@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz#423771edeb417ff5914111fff4277ea0624c0d0e" + integrity sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +array.prototype.findlastindex@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz#d1c50f0b3a9da191981ff8942a0aedd82794404f" + integrity sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ== + dependencies: + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + +array.prototype.flat@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.flatmap@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" - integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" +arraybuffer.prototype.slice@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.2.1" + get-intrinsic "^1.2.3" + is-array-buffer "^3.0.4" + is-shared-array-buffer "^1.0.2" + arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -3964,10 +4171,12 @@ autoprefixer@10.4.13: picocolors "^1.0.0" postcss-value-parser "^4.2.0" -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" aws-sign2@~0.7.0: version "0.7.0" @@ -4067,9 +4276,9 @@ big.js@^5.2.2: integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== bl@^4.1.0: version "4.1.0" @@ -4087,25 +4296,7 @@ blocking-proxy@^1.0.0: dependencies: minimist "^1.2.0" -body-parser@1.20.1: - version "1.20.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.1" - type-is "~1.6.18" - unpipe "1.0.0" - -body-parser@^1.19.0: +body-parser@1.20.2, body-parser@^1.19.0: version "1.20.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== @@ -4124,12 +4315,10 @@ body-parser@^1.19.0: unpipe "1.0.0" bonjour-service@^1.0.11: - version "1.1.0" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.0.tgz#424170268d68af26ff83a5c640b95def01803a13" - integrity sha512-LVRinRB3k1/K0XzZ2p58COnWvkQknIY6sf0zF2rpErvcJXpMBttEPQSxK+HEXSS9VmpZlDoDnQWv8ftJT20B0Q== + version "1.2.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" + integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== dependencies: - array-flatten "^2.1.2" - dns-equal "^1.0.0" fast-deep-equal "^3.1.3" multicast-dns "^7.2.5" @@ -4160,7 +4349,7 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@4.21.5, browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.21.5: +browserslist@4.21.5: version "4.21.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== @@ -4170,6 +4359,16 @@ browserslist@4.21.5, browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^4 node-releases "^2.0.8" update-browserslist-db "^1.0.10" +browserslist@^4.14.5, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.22.2, browserslist@^4.22.3: + version "4.23.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== + dependencies: + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" + browserstack@^1.5.1: version "1.6.1" resolved "https://registry.yarnpkg.com/browserstack/-/browserstack-1.6.1.tgz#e051f9733ec3b507659f395c7a4765a1b1e358b3" @@ -4190,6 +4389,11 @@ buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" +builtin-modules@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + builtins@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9" @@ -4207,7 +4411,7 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacache@17.0.4, cacache@^17.0.0: +cacache@17.0.4: version "17.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.0.4.tgz#5023ed892ba8843e3b7361c26d0ada37e146290c" integrity sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA== @@ -4250,13 +4454,34 @@ cacache@^16.1.0: tar "^6.1.11" unique-filename "^2.0.0" -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== +cacache@^17.0.0: + version "17.1.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.1.4.tgz#b3ff381580b47e85c6e64f801101508e26604b35" + integrity sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + "@npmcli/fs" "^3.1.0" + fs-minipass "^3.0.0" + glob "^10.2.2" + lru-cache "^7.7.1" + minipass "^7.0.3" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + p-map "^4.0.0" + ssri "^10.0.0" + tar "^6.1.11" + unique-filename "^3.0.0" + +call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" callsites@^3.0.0: version "3.1.0" @@ -4268,10 +4493,10 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001449: - version "1.0.30001460" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001460.tgz#31d2e26f0a2309860ed3eff154e03890d9d851a7" - integrity sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ== +caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001587: + version "1.0.30001599" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz#571cf4f3f1506df9bf41fcbb6d10d5d017817bce" + integrity sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA== canvas-gauges@^2.1.7: version "2.1.7" @@ -4294,7 +4519,7 @@ chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.4.2: +chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -4316,7 +4541,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -chokidar@3.5.3, "chokidar@>=3.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.5.1, chokidar@^3.5.3: +chokidar@3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -4331,6 +4556,21 @@ chokidar@3.5.3, "chokidar@>=3.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.5.1, cho optionalDependencies: fsevents "~2.3.2" +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.0.0, chokidar@^3.5.1, chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chownr@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" @@ -4347,9 +4587,9 @@ ci-info@^2.0.0: integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== classnames@2.x, classnames@^2.2.1, classnames@^2.2.6: - version "2.3.2" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" - integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== clean-stack@^2.0.0: version "2.2.0" @@ -4364,9 +4604,9 @@ cli-cursor@^3.1.0: restore-cursor "^3.1.0" cli-spinners@^2.5.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" - integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== cli-width@^3.0.0: version "3.0.0" @@ -4458,16 +4698,16 @@ color-support@^1.1.3: integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== colorette@^2.0.10: - version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== colors@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -combined-stream@^1.0.6, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -4499,20 +4739,25 @@ commander@7: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^2.19.0, commander@^2.20.0: +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^8.0.0: +commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== -comment-parser@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.3.1.tgz#3d7ea3adaf9345594aedee6563f422348f165c1b" - integrity sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA== +comment-parser@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.4.1.tgz#bdafead37961ac079be11eb7ec65c4d021eaf9cc" + integrity sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg== commondir@^1.0.1: version "1.0.1" @@ -4597,6 +4842,11 @@ convert-source-map@^1.5.1, convert-source-map@^1.7.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -4632,16 +4882,16 @@ copy-webpack-plugin@11.0.0: serialize-javascript "^6.0.0" core-js-compat@^3.25.1: - version "3.29.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.29.0.tgz#1b8d9eb4191ab112022e7f6364b99b65ea52f528" - integrity sha512-ScMn3uZNAFhK2DGoEfErguoiAHhV2Ju+oJo/jK08p7B3f3UhocUrCCkTvnZaiS+edl5nlIoiBXKcwMc6elv4KQ== + version "3.36.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.0.tgz#087679119bc2fdbdefad0d45d8e5d307d45ba190" + integrity sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw== dependencies: - browserslist "^4.21.5" + browserslist "^4.22.3" core-js@^3.29.1: - version "3.29.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.29.1.tgz#40ff3b41588b091aaed19ca1aa5cb111803fa9a6" - integrity sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw== + version "3.36.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.36.0.tgz#e752fa0b0b462a0787d56e9d73f80b0f7c0dde68" + integrity sha512-mt7+TUBbTFg5+GngsAxeKBTl5/VS0guFeJacYge9OmHb+m058UwwIm41SE9T4Den7ClatV57B6TYTuJ0CX1MAw== core-util-is@1.0.2: version "1.0.2" @@ -4686,6 +4936,17 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +coveralls-next@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/coveralls-next/-/coveralls-next-4.2.0.tgz#821fb802f98284a3c11c96577b7fd0eaf4d4473e" + integrity sha512-zg41a/4QDSASPtlV6gp+6owoU43U5CguxuPZR3nPZ26M5ZYdEK3MdUe7HwE+AnCZPkucudfhqqJZehCNkz2rYg== + dependencies: + form-data "4.0.0" + js-yaml "4.1.0" + lcov-parse "1.0.0" + log-driver "1.2.7" + minimist "1.2.7" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -4714,7 +4975,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -4779,9 +5040,9 @@ csstype@^2.5.2: integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w== csstype@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" - integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== custom-event@~1.0.0: version "1.0.1" @@ -4803,17 +5064,17 @@ cytoscape-fcose@^2.1.0: cose-base "^2.2.0" cytoscape@^3.23.0: - version "3.23.0" - resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.23.0.tgz#054ee05a6d0aa3b4f139382bbf2f4e5226df3c6d" - integrity sha512-gRZqJj/1kiAVPkrVFvz/GccxsXhF3Qwpptl32gKKypO4IlqnKBjTOu+HbXtEggSGzC5KCaHp3/F7GgENrtsFkA== + version "3.28.1" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.28.1.tgz#f32c3e009bdf32d47845a16a4cd2be2bbc01baf7" + integrity sha512-xyItz4O/4zp9/239wCcH8ZcFuuZooEeF8KHRmzjDfGdXsj3OG9MFSMA0pJE0uX3uCN/ygof6hHf4L7lst+JaDg== dependencies: heap "^0.2.6" lodash "^4.17.21" "d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.2.tgz#f8ac4705c5b06914a7e0025bbf8d5f1513f6a86e" - integrity sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ== + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== dependencies: internmap "1 - 2" @@ -4853,9 +5114,9 @@ d3-contour@4: d3-array "^3.2.0" d3-delaunay@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.2.tgz#7fd3717ad0eade2fc9939f4260acfb503f984e92" - integrity sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ== + version "6.0.4" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b" + integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A== dependencies: delaunator "5" @@ -4908,9 +5169,9 @@ d3-force@3: integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== d3-geo@3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.0.tgz#74fd54e1f4cebd5185ac2039217a98d39b0a4c0e" - integrity sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.1.tgz#6027cf51246f9b2ebd64f99e01dc7c3364033a4d" + integrity sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q== dependencies: d3-array "2.5.0 - 3" @@ -4947,9 +5208,9 @@ d3-random@3: integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== d3-scale-chromatic@3: - version "3.0.0" - resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a" - integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g== + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314" + integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ== dependencies: d3-color "1 - 3" d3-interpolate "1 - 3" @@ -5018,10 +5279,10 @@ d3-zoom@3: d3-selection "2 - 3" d3-transition "2 - 3" -d3@^7.0.0, d3@^7.8.2: - version "7.8.2" - resolved "https://registry.yarnpkg.com/d3/-/d3-7.8.2.tgz#2bdb3c178d095ae03b107a18837ae049838e372d" - integrity sha512-WXty7qOGSHb7HR7CfOzwN1Gw04MUOzN8qh9ZUsvwycIMb4DYMpY9xczZ6jUorGtO6bR9BPMPaueIKwiDxu9uiQ== +d3@^7.4.0, d3@^7.8.2: + version "7.9.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.9.0.tgz#579e7acb3d749caf8860bd1741ae8d371070cd5d" + integrity sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA== dependencies: d3-array "3" d3-axis "3" @@ -5054,10 +5315,10 @@ d3@^7.0.0, d3@^7.8.2: d3-transition "3" d3-zoom "3" -dagre-d3-es@7.0.8: - version "7.0.8" - resolved "https://registry.yarnpkg.com/dagre-d3-es/-/dagre-d3-es-7.0.8.tgz#14c309c3c08ba8329a7cf51000bd56a369c513d1" - integrity sha512-eykdoYQ4FwCJinEYS0gPL2f2w+BPbSLvnQSJ3Ye1vAoPjdkq6xIMKBv+UkICd3qZE26wBKIn3p+6n0QC7R1LyA== +dagre-d3-es@7.0.9: + version "7.0.9" + resolved "https://registry.yarnpkg.com/dagre-d3-es/-/dagre-d3-es-7.0.9.tgz#aca12fccd9d09955a4430029ba72ee6934542a8d" + integrity sha512-rYR4QfVmy+sR44IBDvVtcAmOReGBvRCWDpO2QjYwqgh9yijw6eSHBqaPG/LIOEy7aBsniLvtMW6pg19qJhq60w== dependencies: d3 "^7.8.2" lodash-es "^4.17.21" @@ -5067,7 +5328,34 @@ dashdash@^1.12.0: resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== dependencies: - assert-plus "^1.0.0" + assert-plus "^1.0.0" + +data-view-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" + integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" + integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" + integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" date-fns@2.0.0-alpha.27: version "2.0.0-alpha.27" @@ -5084,10 +5372,10 @@ dayjs@1.11.4: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.4.tgz#3b3c10ca378140d8917e06ebc13a4922af4f433e" integrity sha512-Zj/lPM5hOvQ1Bf7uAvewDaUcsJoI6JmNqmHhHl3nyumwe0XHwt8sWdOVAPACJzCebL8gQCi+K49w7iKWnGwX9g== -dayjs@^1.11.5: - version "1.11.7" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2" - integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ== +dayjs@^1.11.5, dayjs@^1.11.7: + version "1.11.10" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" + integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== debug@2.6.9: version "2.6.9" @@ -5096,14 +5384,14 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: +debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -5116,15 +5404,16 @@ decamelize@^1.2.0: integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== deep-equal@^2.0.5: - version "2.2.0" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.0.tgz#5caeace9c781028b9ff459f33b779346637c43e6" - integrity sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw== + version "2.2.3" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1" + integrity sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA== dependencies: - call-bind "^1.0.2" - es-get-iterator "^1.1.2" - get-intrinsic "^1.1.3" + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.5" + es-get-iterator "^1.1.3" + get-intrinsic "^1.2.2" is-arguments "^1.1.1" - is-array-buffer "^3.0.1" + is-array-buffer "^3.0.2" is-date-object "^1.0.5" is-regex "^1.1.4" is-shared-array-buffer "^1.0.2" @@ -5132,11 +5421,11 @@ deep-equal@^2.0.5: object-is "^1.1.5" object-keys "^1.1.1" object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" + regexp.prototype.flags "^1.5.1" side-channel "^1.0.4" which-boxed-primitive "^1.0.2" which-collection "^1.0.1" - which-typed-array "^1.1.9" + which-typed-array "^1.1.13" deep-extend@~0.6.0: version "0.6.0" @@ -5167,16 +5456,26 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" - integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== +define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: + define-data-property "^1.0.1" has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -5194,11 +5493,11 @@ del@^2.2.0: rimraf "^2.2.8" delaunator@5: - version "5.0.0" - resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" - integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw== + version "5.0.1" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278" + integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw== dependencies: - robust-predicates "^3.0.0" + robust-predicates "^3.0.2" delayed-stream@~1.0.0: version "1.0.0" @@ -5220,7 +5519,7 @@ depd@2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== -depd@^1.1.2, depd@~1.1.2: +depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== @@ -5256,9 +5555,9 @@ diff@^4.0.1: integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== dijkstrajs@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.2.tgz#2e48c0d3b825462afe75ab4ad5e829c8ece36257" - integrity sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" + integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA== dir-glob@^3.0.1: version "3.0.1" @@ -5275,15 +5574,10 @@ directory-tree@^3.5.1: command-line-args "^5.2.0" command-line-usage "^6.1.1" -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== - dns-packet@^5.2.2: - version "5.4.0" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" - integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g== + version "5.6.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" + integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== dependencies: "@leichtgewicht/ip-codec" "^2.0.1" @@ -5359,6 +5653,11 @@ domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -5375,25 +5674,25 @@ echarts@^5.5.0: tslib "2.3.0" zrender "5.5.0" -editorconfig@^0.15.3: - version "0.15.3" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" - integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== +editorconfig@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-1.0.4.tgz#040c9a8e9a6c5288388b87c2db07028aa89f53a3" + integrity sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q== dependencies: - commander "^2.19.0" - lru-cache "^4.1.5" - semver "^5.6.0" - sigmund "^1.0.1" + "@one-ini/wasm" "0.1.1" + commander "^10.0.0" + minimatch "9.0.1" + semver "^7.5.3" ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.284: - version "1.4.317" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.317.tgz#9a3d38a1a37f26a417d3d95dafe198ff11ed072b" - integrity sha512-JhCRm9v30FMNzQSsjl4kXaygU+qHBD0Yh7mKxyjmF0V8VwYVB6qpBRX28GyAucrM9wDCpSUctT6FpMUQxbyKuA== +electron-to-chromium@^1.4.284, electron-to-chromium@^1.4.668: + version "1.4.708" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.708.tgz#d54d3b47cb44ae6b190067439c42135456907893" + integrity sha512-iWgEEvREL4GTXXHKohhh33+6Y8XkPI5eHihDmm8zUk5Zo7HICEW+wI/j5kJ2tbuNUCXJ/sNXa03ajW635DiJXA== elkjs@^0.8.2: version "0.8.2" @@ -5405,6 +5704,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + emoji-toolkit@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/emoji-toolkit/-/emoji-toolkit-7.0.1.tgz#4ea2a78fe4b40c7cdbe7ef5725c7011299932f09" @@ -5432,15 +5736,15 @@ encoding@^0.1.13: dependencies: iconv-lite "^0.6.2" -engine.io-parser@~5.0.3: - version "5.0.6" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.6.tgz#7811244af173e157295dec9b2718dfe42a64ef45" - integrity sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw== +engine.io-parser@~5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.2.tgz#37b48e2d23116919a3453738c5720455e64e1c49" + integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== -engine.io@~6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.4.1.tgz#8056b4526a88e779f9c280d820422d4e3eeaaae5" - integrity sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw== +engine.io@~6.5.2: + version "6.5.4" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.4.tgz#6822debf324e781add2254e912f8568508850cdc" + integrity sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg== dependencies: "@types/cookie" "^0.4.1" "@types/cors" "^2.8.12" @@ -5450,13 +5754,13 @@ engine.io@~6.4.1: cookie "~0.4.1" cors "~2.8.5" debug "~4.3.1" - engine.io-parser "~5.0.3" + engine.io-parser "~5.2.1" ws "~8.11.0" -enhanced-resolve@^5.10.0: - version "5.12.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" - integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== +enhanced-resolve@^5.10.0, enhanced-resolve@^5.15.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" + integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -5472,9 +5776,9 @@ entities@^2.0.0: integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== entities@^4.3.0, entities@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" - integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== env-paths@^2.2.0: version "2.2.1" @@ -5500,46 +5804,123 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.0, es-abstract@^1.20.4: - version "1.21.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.1.tgz#e6105a099967c08377830a0c9cb589d570dd86c6" - integrity sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-set-tostringtag "^2.0.1" +es-abstract@^1.22.1, es-abstract@^1.22.3: + version "1.22.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.5.tgz#1417df4e97cc55f09bf7e58d1e614bc61cb8df46" + integrity sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" - get-symbol-description "^1.0.0" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" globalthis "^1.0.3" gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" has-symbols "^1.0.3" - internal-slot "^1.0.4" - is-array-buffer "^3.0.1" + hasown "^2.0.1" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" is-callable "^1.2.7" - is-negative-zero "^2.0.2" + is-negative-zero "^2.0.3" is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" + is-shared-array-buffer "^1.0.3" is-string "^1.0.7" - is-typed-array "^1.1.10" + is-typed-array "^1.1.13" is-weakref "^1.0.2" - object-inspect "^1.12.2" + object-inspect "^1.13.1" object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-length "^1.0.4" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.0" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.5" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.14" + +es-abstract@^1.23.0: + version "1.23.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.2.tgz#693312f3940f967b8dd3eebacb590b01712622e0" + integrity sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" + is-callable "^1.2.7" + is-data-view "^1.0.1" + is-negative-zero "^2.0.3" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.3" + is-string "^1.0.7" + is-typed-array "^1.1.13" + is-weakref "^1.0.2" + object-inspect "^1.13.1" + object-keys "^1.1.1" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.2" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.9" + string.prototype.trimend "^1.0.8" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.5" unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" + which-typed-array "^1.1.15" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.0.0, es-errors@^1.2.1, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-get-iterator@^1.1.2: +es-get-iterator@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== @@ -5559,21 +5940,33 @@ es-module-lexer@^0.9.0: resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== -es-set-tostringtag@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== - dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - has-tostringtag "^1.0.0" +es-module-lexer@^1.2.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" + integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== -es-shim-unscopables@^1.0.0: +es-object-atoms@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" - integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" + integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== dependencies: - has "^1.0.3" + get-intrinsic "^1.2.4" + has-tostringtag "^1.0.2" + hasown "^2.0.1" + +es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" es-to-primitive@^1.2.1: version "1.2.1" @@ -5630,9 +6023,9 @@ esbuild@0.17.8: "@esbuild/win32-x64" "0.17.8" escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-html@~1.0.3: version "1.0.3" @@ -5649,55 +6042,59 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-import-resolver-node@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" - integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== +eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== dependencies: debug "^3.2.7" - is-core-module "^2.11.0" - resolve "^1.22.1" + is-core-module "^2.13.0" + resolve "^1.22.4" -eslint-module-utils@^2.7.4: - version "2.7.4" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974" - integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA== +eslint-module-utils@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" + integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== dependencies: debug "^3.2.7" eslint-plugin-import@latest: - version "2.27.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" - integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== - dependencies: - array-includes "^3.1.6" - array.prototype.flat "^1.3.1" - array.prototype.flatmap "^1.3.1" + version "2.29.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" + integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== + dependencies: + array-includes "^3.1.7" + array.prototype.findlastindex "^1.2.3" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" debug "^3.2.7" doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.7" - eslint-module-utils "^2.7.4" - has "^1.0.3" - is-core-module "^2.11.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.8.0" + hasown "^2.0.0" + is-core-module "^2.13.1" is-glob "^4.0.3" minimatch "^3.1.2" - object.values "^1.1.6" - resolve "^1.22.1" - semver "^6.3.0" - tsconfig-paths "^3.14.1" + object.fromentries "^2.0.7" + object.groupby "^1.0.1" + object.values "^1.1.7" + semver "^6.3.1" + tsconfig-paths "^3.15.0" eslint-plugin-jsdoc@latest: - version "40.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-40.0.1.tgz#5f028b4928d5c77f54bfd3c42c00acb61d27bb9f" - integrity sha512-KkiRInury7YrjjV5aCHDxwsPy6XFt5p2b2CnpDMITnWs8patNPf5kj24+VXIWw45kP6z/B0GOKfrYczB56OjQQ== + version "48.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.1.tgz#9334a05555a95fdc192980627142177963b668b4" + integrity sha512-iUvbcyDZSO/9xSuRv2HQBw++8VkV/pt3UWtX9cpPH0l7GKPq78QC/6+PmyQHHvNZaTjAce6QVciEbnc6J/zH5g== dependencies: - "@es-joy/jsdoccomment" "~0.36.1" - comment-parser "1.3.1" + "@es-joy/jsdoccomment" "~0.42.0" + are-docs-informative "^0.0.2" + comment-parser "1.4.1" debug "^4.3.4" escape-string-regexp "^4.0.0" - esquery "^1.4.0" - semver "^7.3.8" - spdx-expression-parse "^3.0.1" + esquery "^1.5.0" + is-builtin-module "^3.2.1" + semver "^7.6.0" + spdx-expression-parse "^4.0.0" eslint-plugin-prefer-arrow@latest: version "1.2.3" @@ -5712,10 +6109,10 @@ eslint-scope@5.1.1, eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.0.0, eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== +eslint-scope@^7.0.0, eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -5732,37 +6129,33 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint-visitor-keys@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz#c7f0f956124ce677047ddbc192a68f999454dedc" - integrity sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ== +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^8.37.0: - version "8.37.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.37.0.tgz#1f660ef2ce49a0bfdec0b0d698e0b8b627287412" - integrity sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw== + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.4.0" - "@eslint/eslintrc" "^2.0.2" - "@eslint/js" "8.37.0" - "@humanwhocodes/config-array" "^0.11.8" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-visitor-keys "^3.4.0" - espree "^9.5.1" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -5770,39 +6163,36 @@ eslint@^8.37.0: find-up "^5.0.0" glob-parent "^6.0.2" globals "^13.19.0" - grapheme-splitter "^1.0.4" + graphemer "^1.4.0" ignore "^5.2.0" - import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" - js-sdsl "^4.1.4" js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.9.1" + optionator "^0.9.3" strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^9.5.1: - version "9.5.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.1.tgz#4f26a4d5f18905bf4f2e0bd99002aab807e96dd4" - integrity sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg== +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: - acorn "^8.8.0" + acorn "^8.9.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.0" + eslint-visitor-keys "^3.4.1" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0, esquery@^1.4.2: +esquery@^1.4.2, esquery@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== @@ -5876,14 +6266,19 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== +exponential-backoff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" + integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== + express@^4.17.3: - version "4.18.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + version "4.18.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.3.tgz#6870746f3ff904dee1819b82e4b51509afffb0d4" + integrity sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.1" + body-parser "1.20.2" content-disposition "0.5.4" content-type "~1.0.4" cookie "0.5.0" @@ -5942,10 +6337,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.11, fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== +fast-glob@^3.2.11, fast-glob@^3.2.9, fast-glob@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -5964,9 +6359,9 @@ fast-levenshtein@^2.0.6: integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" @@ -6071,17 +6466,23 @@ find-yarn-workspace-root@^2.0.0: micromatch "^4.0.2" flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== dependencies: - flatted "^3.1.0" + flatted "^3.2.9" + keyv "^4.5.3" rimraf "^3.0.2" -flatted@^3.1.0, flatted@^3.2.7: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.7, flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== "flot.curvedlines@https://github.com/MichaelZinsmaier/CurvedLines.git#master": version "1.1.1" @@ -6092,9 +6493,9 @@ flatted@^3.1.0, flatted@^3.2.7: resolved "https://github.com/thingsboard/flot.git#c2734540477d8b261d04ee18d4d38af3b0ecb81b" follow-redirects@^1.0.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== font-awesome@^4.7.0: version "4.7.0" @@ -6108,11 +6509,28 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== +form-data@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -6128,9 +6546,9 @@ forwarded@0.2.0: integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fraction.js@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" - integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== + version "4.3.7" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" + integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== fresh@0.5.2: version "0.5.2" @@ -6164,16 +6582,16 @@ fs-minipass@^2.0.0, fs-minipass@^2.1.0: minipass "^3.0.0" fs-minipass@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.1.tgz#853809af15b6d03e27638d1ab6432e6b378b085d" - integrity sha512-MhaJDcFRTuLidHrIttu0RDGyyXs/IYHVmlcxfLAEFIWjc1vdLAkdwT7Ace2u7DbitWC0toKMl5eJZRYNVreIMw== + version "3.0.3" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54" + integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== dependencies: - minipass "^4.0.0" + minipass "^7.0.3" -fs-monkey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== +fs-monkey@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788" + integrity sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew== fs.realpath@^1.0.0: version "1.0.0" @@ -6181,26 +6599,26 @@ fs.realpath@^1.0.0: integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" -functions-have-names@^1.2.2: +functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== @@ -6240,14 +6658,16 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" - integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: - function-bind "^1.1.1" - has "^1.0.3" + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" has-symbols "^1.0.3" + hasown "^2.0.0" get-package-type@^0.1.0: version "0.1.0" @@ -6259,13 +6679,14 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== +get-symbol-description@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" + call-bind "^1.0.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" getpass@^0.1.1: version "0.1.7" @@ -6293,7 +6714,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@8.1.0, glob@^8.0.1, glob@^8.0.3: +glob@8.1.0, glob@^8.0.1: version "8.1.0" resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== @@ -6304,6 +6725,17 @@ glob@8.1.0, glob@^8.0.1, glob@^8.0.3: minimatch "^5.0.1" once "^1.3.0" +glob@^10.2.2, glob@^10.3.3: + version "10.3.10" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.5" + minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry "^1.10.1" + glob@^7.0.3, glob@^7.0.6, glob@^7.1.3, glob@^7.1.4, glob@^7.1.7: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -6322,9 +6754,9 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.19.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" @@ -6348,13 +6780,13 @@ globby@^11.1.0: slash "^3.0.0" globby@^13.1.1: - version "13.1.3" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.3.tgz#f62baf5720bcb2c1330c8d4ef222ee12318563ff" - integrity sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw== + version "13.2.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" + integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== dependencies: dir-glob "^3.0.1" - fast-glob "^3.2.11" - ignore "^5.2.0" + fast-glob "^3.3.0" + ignore "^5.2.4" merge2 "^1.4.1" slash "^4.0.0" @@ -6385,15 +6817,20 @@ gopd@^1.0.1: get-intrinsic "^1.1.3" graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== grapheme-splitter@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + hammerjs@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1" @@ -6439,41 +6876,41 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: - get-intrinsic "^1.1.1" + es-define-property "^1.0.0" -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== +has-proto@^1.0.1, has-proto@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== +has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: - has-symbols "^1.0.2" + has-symbols "^1.0.3" has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== +hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: - function-bind "^1.1.1" + function-bind "^1.1.2" hdr-histogram-js@^2.0.1: version "2.0.3" @@ -6519,9 +6956,9 @@ hpack.js@^2.1.6: wbuf "^1.1.0" html-entities@^2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" - integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== html-escaper@^2.0.0: version "2.0.2" @@ -6668,17 +7105,22 @@ ieee754@^1.1.13: integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore-walk@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.1.tgz#f05e232992ebf25fef13613668fea99857e7e8cf" - integrity sha512-/c8MxUAqpRccq+LyDOecwF+9KqajueJHh8fz7g3YqjMZt+NSfJzx05zrKiXwa2sKwFCzaiZ5qUVfRj0pmxixEA== + version "6.0.4" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-6.0.4.tgz#89950be94b4f522225eb63a13c56badb639190e9" + integrity sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw== dependencies: - minimatch "^6.1.6" + minimatch "^9.0.0" -ignore@5.2.4, ignore@^5.2.0: +ignore@5.2.4: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +ignore@^5.2.0, ignore@^5.2.4: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + image-size@~0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" @@ -6690,11 +7132,11 @@ immediate@~3.0.5: integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== immutable@^4.0.0: - version "4.2.4" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.4.tgz#83260d50889526b4b531a5e293709a77f7c55a2a" - integrity sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w== + version "4.3.5" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.5.tgz#f8b436e66d59f99760dc577f5c99a4fd2a5cc5a0" + integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== -import-fresh@^3.0.0, import-fresh@^3.2.1: +import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -6766,13 +7208,13 @@ inquirer@8.2.4: through "^2.3.6" wrap-ansi "^7.0.0" -internal-slot@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" - integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== +internal-slot@^1.0.4, internal-slot@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== dependencies: - get-intrinsic "^1.2.0" - has "^1.0.3" + es-errors "^1.3.0" + hasown "^2.0.0" side-channel "^1.0.4" "internmap@1 - 2": @@ -6780,10 +7222,13 @@ internal-slot@^1.0.4: resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== -ip@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" - integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== +ip-address@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" + integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== + dependencies: + jsbn "1.1.0" + sprintf-js "^1.1.3" ipaddr.js@1.9.1: version "1.9.1" @@ -6791,9 +7236,9 @@ ipaddr.js@1.9.1: integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== ipaddr.js@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" - integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + version "2.1.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" + integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== is-arguments@^1.1.1: version "1.1.1" @@ -6803,14 +7248,13 @@ is-arguments@^1.1.1: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-array-buffer@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" - integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== +is-array-buffer@^3.0.2, is-array-buffer@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== dependencies: call-bind "^1.0.2" - get-intrinsic "^1.2.0" - is-typed-array "^1.1.10" + get-intrinsic "^1.2.1" is-arrayish@^0.2.1: version "0.2.1" @@ -6839,6 +7283,13 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-builtin-module@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" + integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== + dependencies: + builtin-modules "^3.3.0" + is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" @@ -6851,12 +7302,19 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.11.0, is-core-module@^2.8.1, is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== +is-core-module@^2.13.0, is-core-module@^2.13.1, is-core-module@^2.8.1, is-core-module@^2.9.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-data-view@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" + integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== dependencies: - has "^1.0.3" + is-typed-array "^1.1.13" is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" @@ -6902,15 +7360,15 @@ is-lambda@^1.0.1: resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== -is-map@^2.0.1, is-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" - integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== +is-map@^2.0.2, is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== is-number-object@^1.0.4: version "1.0.7" @@ -6968,17 +7426,17 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-set@^2.0.1, is-set@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" - integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== +is-set@^2.0.2, is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== +is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" + integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" is-stream@^2.0.0: version "2.0.1" @@ -6999,16 +7457,12 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== +is-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" + which-typed-array "^1.1.14" is-typedarray@~1.0.0: version "1.0.0" @@ -7020,10 +7474,10 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-weakmap@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" - integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== is-weakref@^1.0.2: version "1.0.2" @@ -7032,13 +7486,13 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -is-weakset@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d" - integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== +is-weakset@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" + integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" + call-bind "^1.0.7" + get-intrinsic "^1.2.4" is-what@^3.14.1: version "3.14.1" @@ -7088,9 +7542,9 @@ istanbul-lib-coverage@^2.0.5: integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== istanbul-lib-instrument@^5.0.4: version "5.2.1" @@ -7104,12 +7558,12 @@ istanbul-lib-instrument@^5.0.4: semver "^6.3.0" istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== dependencies: istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" + make-dir "^4.0.0" supports-color "^7.1.0" istanbul-lib-source-maps@^3.0.6: @@ -7124,13 +7578,22 @@ istanbul-lib-source-maps@^3.0.6: source-map "^0.6.1" istanbul-reports@^3.0.2: - version "3.1.5" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" - integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +jackspeak@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jasmine-core@^3.6.0: version "3.99.1" resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.99.1.tgz#5bfa4b2d76618868bfac4c8ff08bb26fffa4120d" @@ -7177,50 +7640,54 @@ jest-worker@^27.4.5: supports-color "^8.0.0" jquery.terminal@^2.35.3: - version "2.35.3" - resolved "https://registry.yarnpkg.com/jquery.terminal/-/jquery.terminal-2.35.3.tgz#64c9291c9fdfa845083a5a66c6052c96f5cb5f81" - integrity sha512-McYaOivaUB2Gubn8IBhQY7zxjGWXg4ENSofL11rt7HACWUDjqncXxakShuqq7Ma0y+BwCcYdltPl1e+WpDJkeg== + version "2.39.0" + resolved "https://registry.yarnpkg.com/jquery.terminal/-/jquery.terminal-2.39.0.tgz#defc2062dadebc41f0b97eebbfd0e5b4cd165616" + integrity sha512-5uOeJY8dxVJPdeGlaUuRFAcPlw3GzSxLLTmCSaqP9vJhSAu3Amgkr7e7LZxBvup8oQDYF8jRjQSvtIrkn1XsWw== dependencies: "@jcubic/lily" "^0.3.0" - "@types/jquery" "^3.5.14" + "@types/jquery" "^3.5.29" ansidec "^0.3.4" + coveralls-next "^4.2.0" iconv-lite "^0.6.3" - jquery "^3.6.0" + jquery "^3.7.1" prismjs "^1.27.0" wcwidth "^1.0.1" optionalDependencies: fsevents "^2.3.2" -jquery@>=1.9.1, jquery@^3.5.0, jquery@^3.6.0: - version "3.6.3" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.3.tgz#23ed2ffed8a19e048814f13391a19afcdba160e6" - integrity sha512-bZ5Sy3YzKo9Fyc8wH2iIQK4JImJ6R0GWI9kL1/k7Z91ZBNgkRXE6U0JfHIizZbort8ZunhSI3jw9I6253ahKfg== - -jquery@^3.6.3: - version "3.6.4" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.4.tgz#ba065c188142100be4833699852bf7c24dc0252f" - integrity sha512-v28EW9DWDFpzcD9O5iyJXg3R3+q+mET5JhnjJzQUZMHOv67bpSIHq81GEYpPNZHG+XXHsfSme3nxp/hndKEcsQ== +jquery@>=1.9.1, jquery@^3.5.0, jquery@^3.6.3, jquery@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" + integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== js-beautify@^1.14.7: - version "1.14.7" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.14.7.tgz#9206296de33f86dc106d3e50a35b7cf8729703b2" - integrity sha512-5SOX1KXPFKx+5f6ZrPsIPEY7NwKeQz47n3jm2i+XeHx9MoRsfQenlOP13FQhWvg8JRS0+XLO6XYUQ2GX+q+T9A== + version "1.15.1" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.15.1.tgz#4695afb508c324e1084ee0b952a102023fc65b64" + integrity sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA== dependencies: config-chain "^1.1.13" - editorconfig "^0.15.3" - glob "^8.0.3" - nopt "^6.0.0" + editorconfig "^1.0.4" + glob "^10.3.3" + js-cookie "^3.0.5" + nopt "^7.2.0" -js-sdsl@^4.1.4: - version "4.3.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711" - integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ== +js-cookie@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc" + integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@4.1.0, js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -7229,22 +7696,20 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsdoc-type-pratt-parser@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.1.0.tgz#a4a56bdc6e82e5865ffd9febc5b1a227ff28e67e" - integrity sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw== +jsdoc-type-pratt-parser@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz#136f0571a99c184d84ec84662c45c29ceff71114" + integrity sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ== jsesc@^2.5.1: version "2.5.2" @@ -7256,15 +7721,20 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-parse-even-better-errors@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz#2cb2ee33069a78870a0c7e3da560026b89669cf7" - integrity sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz#02bb29fb5da90b5444581749c22cedd3597c6cb0" + integrity sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg== json-schema-defaults@^0.4.0: version "0.4.0" @@ -7305,7 +7775,7 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.1.2, json5@^2.2.1, json5@^2.2.2: +json5@^2.1.2, json5@^2.2.1, json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -7424,9 +7894,9 @@ jstree-bootstrap-theme@^1.0.1: jquery ">=1.9.1" jstree@^3.3.15: - version "3.3.15" - resolved "https://registry.yarnpkg.com/jstree/-/jstree-3.3.15.tgz#364bfa0fc4c0b1b7b5bc122cda44a0f09e59eba4" - integrity sha512-fNK2EBgGjaJQ3cJuINX/80vDeAufYWtM0csudgYl3eJG+eRAH/1r1IJVUOvAlJIa+uSgg+Fi8uGrt+Xbs92eKg== + version "3.3.16" + resolved "https://registry.yarnpkg.com/jstree/-/jstree-3.3.16.tgz#43e3a8a1ee270ddff514317250d5e85b95d63c52" + integrity sha512-yeeIJffi2WAqyMeHufXj/Ozy7GqgKdDkxfN8L8lwbG0h1cw/TgDafWmyhroH4AKgDSk9yW1W6jiJZu4zXAqzXw== dependencies: jquery "^3.5.0" @@ -7508,16 +7978,23 @@ karma@~6.3.9: yargs "^16.1.1" katex@^0.16.0: - version "0.16.4" - resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.4.tgz#87021bc3bbd80586ef715aeb476794cba6a49ad4" - integrity sha512-WudRKUj8yyBeVDI4aYMNxhx5Vhh2PjpzQw1GRu/LVGqL4m1AxwD1GcUp0IMbdJaf5zsjtj8ghP0DOQRYhroNkw== + version "0.16.9" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.9.tgz#bc62d8f7abfea6e181250f85a56e4ef292dcb1fa" + integrity sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ== + dependencies: + commander "^8.3.0" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: - commander "^8.0.0" + json-buffer "3.0.1" khroma@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.0.0.tgz#7577de98aed9f36c7a474c4d453d94c0d6c6588b" - integrity sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g== + version "2.1.0" + resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.1.0.tgz#45f2ce94ce231a437cf5b63c2e886e6eb42bbbb1" + integrity sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw== kind-of@^6.0.2: version "6.0.3" @@ -7546,6 +8023,11 @@ layout-base@^2.0.0: resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-2.0.1.tgz#d0337913586c90f9c2c075292069f5c2da5dd285" integrity sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg== +lcov-parse@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" + integrity sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ== + leaflet-polylinedecorator@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz#9ef79fd1b5302d67b72efe959a8ecd2553f27266" @@ -7611,9 +8093,9 @@ levn@^0.4.1: type-check "~0.4.0" libphonenumber-js@^1.10.4: - version "1.10.21" - resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.21.tgz#860312cbec1389e36e28389161025c7817a3ae32" - integrity sha512-/udZhx49av2r2gZR/+xXSrwcR8smX/sDNrVpOFrvW+CA26TfYTVZfwb3MIDvmwAYMLs7pXuJjZX0VxxGpqPhsA== + version "1.10.58" + resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.58.tgz#2015877bd47fd3d32d9fbfcedd75df35be230c9a" + integrity sha512-53A0IpJFL9LdHbpeatwizf8KSwPICrqn9H0g3Y7WQ+Jgeu9cQ4Ew3WrRtrLBu/CX2lXd5+rgT01/tGlkbkzOjw== license-webpack-plugin@4.0.2: version "4.0.2" @@ -7702,6 +8184,11 @@ lodash@4.17.21, lodash@^4.0.1, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-driver@1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== + log-symbols@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -7711,9 +8198,9 @@ log-symbols@^4.1.0: is-unicode-supported "^0.1.0" log4js@^6.4.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.8.0.tgz#f0fe9b2b82725aaf97f20692e23381a5c5722448" - integrity sha512-g+V8gZyurIexrOvWQ+AcZsIvuK/lBnx2argejZxL4gVZ4Hq02kUYH6WZOnqxgBml+zzQZYdaEoTN84B6Hzm8Fg== + version "6.9.1" + resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.9.1.tgz#aba5a3ff4e7872ae34f8b4c533706753709e38b6" + integrity sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g== dependencies: date-format "^4.0.14" debug "^4.3.4" @@ -7728,14 +8215,6 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lru-cache@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -7751,9 +8230,14 @@ lru-cache@^6.0.0: yallist "^4.0.0" lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: - version "7.18.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.1.tgz#4716408dec51d5d0104732647f584d1f6738b109" - integrity sha512-8/HcIENyQnfUTCDizRu9rrDyG6XG/21M4X7/YEGZeD76ZJilFPAUVb/2zysFf7VVO1LEjCDFyHp8pMMvozIrvg== + version "7.18.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" + integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== + +"lru-cache@^9.1.1 || ^10.0.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== magic-string@0.29.0: version "0.29.0" @@ -7777,13 +8261,20 @@ make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0, make-dir@^3.0.2: +make-dir@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" @@ -7811,10 +8302,10 @@ make-fetch-happen@^10.0.3: socks-proxy-agent "^7.0.0" ssri "^9.0.0" -make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1: - version "11.0.3" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-11.0.3.tgz#ed83dd3685b97f75607156d2721848f6eca561b9" - integrity sha512-oPLh5m10lRNNZDjJ2kP8UpboUx2uFXVaVweVe/lWut4iHWcQEmfqSVJt2ihZsFI8HbpwyyocaXbCAWf0g1ukIA== +make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1, make-fetch-happen@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz#85ceb98079584a9523d4bf71d32996e7e208549f" + integrity sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w== dependencies: agentkeepalive "^4.2.1" cacache "^17.0.0" @@ -7823,7 +8314,7 @@ make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1: https-proxy-agent "^5.0.0" is-lambda "^1.0.1" lru-cache "^7.7.1" - minipass "^4.0.0" + minipass "^5.0.0" minipass-fetch "^3.0.0" minipass-flush "^1.0.5" minipass-pipeline "^1.2.4" @@ -7833,14 +8324,14 @@ make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1: ssri "^10.0.0" make-plural@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-7.2.0.tgz#93174b1419672a48a2340db6c1d3fb217530c684" - integrity sha512-WkdI+iaWaBCFM2wUXwos8Z7spg5Dt64Xe/VI6NpRaly21cDtD76N6S97K//UtzV0dHOiXX+E90TnszdXHG0aMg== + version "7.3.0" + resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-7.3.0.tgz#2889dbafca2fb097037c47967d3e3afa7e48a52c" + integrity sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw== marked@^4.0.17: - version "4.2.12" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.2.12.tgz#d69a64e21d71b06250da995dcd065c11083bebb5" - integrity sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw== + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== media-typer@0.3.0: version "0.3.0" @@ -7848,11 +8339,11 @@ media-typer@0.3.0: integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memfs@^3.4.12, memfs@^3.4.3: - version "3.4.13" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.13.tgz#248a8bd239b3c240175cd5ec548de5227fc4f345" - integrity sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg== + version "3.6.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" + integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== dependencies: - fs-monkey "^1.0.3" + fs-monkey "^1.0.4" merge-descriptors@1.0.1: version "1.0.1" @@ -7870,25 +8361,26 @@ merge2@^1.3.0, merge2@^1.4.1: integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== mermaid@^9.1.2: - version "9.4.0" - resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-9.4.0.tgz#ff9afcac9f565a358fa8fc39135dec2c842c3b8f" - integrity sha512-4PWbOND7CNRbjHrdG3WUUGBreKAFVnMhdlPjttuUkeHbCQmAHkwzSh5dGwbrKmXGRaR4uTvfFVYzUcg++h0DkA== + version "9.4.3" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-9.4.3.tgz#62cf210c246b74972ea98c19837519b6f03427f2" + integrity sha512-TLkQEtqhRSuEHSE34lh5bCa94KATCyluAXmFnNI2PRZwOpXFeqiJWwZl+d2CcemE1RS6QbbueSSq9QIg8Uxcyw== dependencies: "@braintree/sanitize-url" "^6.0.0" cytoscape "^3.23.0" cytoscape-cose-bilkent "^4.1.0" cytoscape-fcose "^2.1.0" - d3 "^7.0.0" - dagre-d3-es "7.0.8" + d3 "^7.4.0" + dagre-d3-es "7.0.9" + dayjs "^1.11.7" dompurify "2.4.3" elkjs "^0.8.2" khroma "^2.0.0" lodash-es "^4.17.21" - moment "^2.29.4" non-layered-tidy-tree-layout "^2.0.2" stylis "^4.1.2" ts-dedent "^2.2.0" uuid "^9.0.0" + web-worker "^1.2.0" methods@~1.1.2: version "1.1.2" @@ -7942,6 +8434,13 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== +minimatch@9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.1.tgz#8a555f541cf976c622daf078bb28f29fb927c253" + integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -7956,13 +8455,18 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^6.1.0, minimatch@^6.1.6: - version "6.2.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-6.2.0.tgz#2b70fd13294178c69c04dfc05aebdb97a4e79e42" - integrity sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg== +minimatch@^9.0.0, minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== dependencies: brace-expansion "^2.0.1" +minimist@1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + minimist@^1.2.0, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -7987,11 +8491,11 @@ minipass-fetch@^2.0.3: encoding "^0.1.13" minipass-fetch@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.1.tgz#bae3789f668d82ffae3ea47edc6b78b8283b3656" - integrity sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw== + version "3.0.4" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.4.tgz#4d4d9b9f34053af6c6e597a64be8e66e42bf45b7" + integrity sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg== dependencies: - minipass "^4.0.0" + minipass "^7.0.3" minipass-sized "^1.0.3" minizlib "^2.1.2" optionalDependencies: @@ -8034,9 +8538,19 @@ minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: yallist "^4.0.0" minipass@^4.0.0: - version "4.2.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.4.tgz#7d0d97434b6a19f59c5c3221698b48bbf3b2cd06" - integrity sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ== + version "4.2.8" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" + integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3: + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" @@ -8059,16 +8573,16 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== moment-timezone@^0.5.42: - version "0.5.42" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.42.tgz#c59f2aa00442d0dcd1d258d2182873d637b4e17b" - integrity sha512-tjI9goqwzkflKSTxJo+jC/W8riTFwEjjunssmFvAWlvNVApjbkJM7UHggyKO0q1Fd/kZVKY77H7C9A0XKhhAFw== + version "0.5.45" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c" + integrity sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ== dependencies: moment "^2.29.4" moment@^2.29.4: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== moo@^0.5.1: version "0.5.2" @@ -8108,10 +8622,10 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanoid@^3.3.6, nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== natural-compare-lite@^1.4.0: version "1.4.0" @@ -8124,11 +8638,10 @@ natural-compare@^1.4.0: integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== needle@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-3.2.0.tgz#07d240ebcabfd65c76c03afae7f6defe6469df44" - integrity sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ== + version "3.3.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-3.3.1.tgz#63f75aec580c2e77e209f3f324e2cdf3d29bd049" + integrity sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q== dependencies: - debug "^3.2.6" iconv-lite "^0.6.3" sax "^1.2.4" @@ -8166,9 +8679,9 @@ ngx-daterangepicker-material@^6.0.4: tslib "^2.0.0" ngx-drag-drop@^15.0.1: - version "15.0.1" - resolved "https://registry.yarnpkg.com/ngx-drag-drop/-/ngx-drag-drop-15.0.1.tgz#e751fa0f11a4c86456fbb241bc8c2c530149cee0" - integrity sha512-x0YgsVCk95x3YSNZT/EmJvo1sRjra+BtQuZMbRYKc88E0GHIOlmWNp/1Z7w5UdznEp0240KDwYp3crR4FuDGew== + version "15.1.0" + resolved "https://registry.yarnpkg.com/ngx-drag-drop/-/ngx-drag-drop-15.1.0.tgz#ddc208202ea6576e27c5362b87e87e9a4b081877" + integrity sha512-ZTAMrKMv7Fqdybvt+2sEtbT0LlOwsaFCNwFQ/CnKXrXEBkbs5K1jx2rN8HXx9BMlVAfa4ovOmtkJXtx/9XYqrA== dependencies: tslib "^2.3.0" @@ -8208,16 +8721,16 @@ ngx-sharebuttons@^12.0.0: tslib "^2.0.0" ngx-translate-messageformat-compiler@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/ngx-translate-messageformat-compiler/-/ngx-translate-messageformat-compiler-6.2.0.tgz#54cd3dc151e29d035d483ad3ac8951fb1e074a25" - integrity sha512-niGhub53gMw8GbmP3u3OB7SVJn7z5JZodQxQxDb6ZE0A9c0WeVBzz30WbekQshBF7ijzLYE/qcM+lzTCpWkRmg== + version "6.5.1" + resolved "https://registry.yarnpkg.com/ngx-translate-messageformat-compiler/-/ngx-translate-messageformat-compiler-6.5.1.tgz#dfb51a83df5ec41bb6c3fff3b2e3f640ecb4a324" + integrity sha512-jJHlEYfE6myYQsILhXHNp2QIOgP3B19BE+NFN9H2a9sgqWgV/CoHBzhEvnt0suf1og/drgHFSkugp5N0Im0xHg== dependencies: - tslib "^2.4.1" + tslib "^2.5.0" ngx-window-token@>=6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/ngx-window-token/-/ngx-window-token-6.0.0.tgz#8b4704242df93a302422a23163359c09d6bb34a0" - integrity sha512-IeLKO1jzfzSvZ6vlAt4QSY/B5XcHEhdOwTjqvWEPt6/esWV9T3mA2ln10kj6SCc9pUSx4NybxE10gcyyYroImg== + version "7.0.0" + resolved "https://registry.yarnpkg.com/ngx-window-token/-/ngx-window-token-7.0.0.tgz#2e1bc76846411a388188b802154e4841d3e27856" + integrity sha512-5+XfRVSY7Dciu8xyCNMkOlH2UfwR9W2P1Pirz7caaZgOZDjFbL8aEO2stjfJJm2FFf1D6dlVHNzhLWGk9HGkqA== dependencies: tslib "^2.0.0" @@ -8245,16 +8758,17 @@ node-forge@^1: integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== node-gyp-build@^4.2.2: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + version "4.8.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.0.tgz#3fee9c1731df4581a3f9ead74664369ff00d26dd" + integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og== node-gyp@^9.0.0: - version "9.3.1" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.3.1.tgz#1e19f5f290afcc9c46973d68700cbd21a96192e4" - integrity sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg== + version "9.4.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.4.1.tgz#8a1023e0d6766ecb52764cc3a734b36ff275e185" + integrity sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ== dependencies: env-paths "^2.2.0" + exponential-backoff "^3.1.1" glob "^7.1.4" graceful-fs "^4.2.6" make-fetch-happen "^10.0.3" @@ -8265,10 +8779,10 @@ node-gyp@^9.0.0: tar "^6.1.2" which "^2.0.2" -node-releases@^2.0.8: - version "2.0.10" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" - integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== +node-releases@^2.0.14, node-releases@^2.0.8: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== non-layered-tidy-tree-layout@^2.0.2: version "2.0.2" @@ -8282,6 +8796,13 @@ nopt@^6.0.0: dependencies: abbrev "^1.0.0" +nopt@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7" + integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA== + dependencies: + abbrev "^2.0.0" + normalize-package-data@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-5.0.0.tgz#abcb8d7e724c40d88462b84982f7cbf6859b4588" @@ -8310,16 +8831,16 @@ npm-bundled@^3.0.0: npm-normalize-package-bin "^3.0.0" npm-install-checks@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-6.0.0.tgz#9a021d8e8b3956d61fd265c2eda4735bcd3d9b83" - integrity sha512-SBU9oFglRVZnfElwAtF14NivyulDqF1VKqqwNsFW9HDcbHMAPHpRSsVFgKuwFGq/hVvWZExz62Th0kvxn/XE7Q== + version "6.3.0" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-6.3.0.tgz#046552d8920e801fa9f919cad569545d60e826fe" + integrity sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw== dependencies: semver "^7.1.1" npm-normalize-package-bin@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.0.tgz#6097436adb4ef09e2628b59a7882576fe53ce485" - integrity sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q== + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz#25447e32a9a7de1f51362c61a559233b89947832" + integrity sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ== npm-package-arg@10.1.0, npm-package-arg@^10.0.0: version "10.1.0" @@ -8338,7 +8859,7 @@ npm-packlist@^7.0.0: dependencies: ignore-walk "^6.0.0" -npm-pick-manifest@8.0.1, npm-pick-manifest@^8.0.0: +npm-pick-manifest@8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz#c6acd97d1ad4c5dbb80eac7b386b03ffeb289e5f" integrity sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA== @@ -8348,13 +8869,23 @@ npm-pick-manifest@8.0.1, npm-pick-manifest@^8.0.0: npm-package-arg "^10.0.0" semver "^7.3.5" +npm-pick-manifest@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz#2159778d9c7360420c925c1a2287b5a884c713aa" + integrity sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg== + dependencies: + npm-install-checks "^6.0.0" + npm-normalize-package-bin "^3.0.0" + npm-package-arg "^10.0.0" + semver "^7.3.5" + npm-registry-fetch@^14.0.0: - version "14.0.3" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-14.0.3.tgz#8545e321c2b36d2c6fe6e009e77e9f0e527f547b" - integrity sha512-YaeRbVNpnWvsGOjX2wk5s85XJ7l1qQBGAp724h8e2CZFFhMSuw9enom7K1mWVUtvXO1uUSFIAPofQK0pPN0ZcA== + version "14.0.5" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz#fe7169957ba4986a4853a650278ee02e568d115d" + integrity sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA== dependencies: make-fetch-happen "^11.0.0" - minipass "^4.0.0" + minipass "^5.0.0" minipass-fetch "^3.0.0" minipass-json-stream "^1.0.1" minizlib "^2.1.2" @@ -8395,42 +8926,62 @@ object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.12.2, object-inspect@^1.9.0: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== object-is@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + version "1.1.6" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" + call-bind "^1.0.7" + define-properties "^1.2.1" object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== +object.assign@^4.1.4, object.assign@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" + call-bind "^1.0.5" + define-properties "^1.2.1" has-symbols "^1.0.3" object-keys "^1.1.1" -object.values@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" - integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== +object.fromentries@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.groupby@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.2.tgz#494800ff5bab78fd0eff2835ec859066e00192ec" + integrity sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw== + dependencies: + array.prototype.filter "^1.0.3" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.0.0" + +object.values@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" objectpath@^2.0.0: version "2.0.0" @@ -8501,17 +9052,17 @@ open@^8.0.9: is-docker "^2.1.1" is-wsl "^2.2.0" -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" - word-wrap "^1.2.3" ora@5.4.1, ora@^5.4.1: version "5.4.1" @@ -8722,6 +9273,14 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" + integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== + dependencies: + lru-cache "^9.1.1 || ^10.0.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -8804,6 +9363,11 @@ popper.js@1.16.1-lts: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" integrity sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA== +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + postcss-loader@7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.2.tgz#b53ff44a26fba3688eee92a048c7f2d4802e23bb" @@ -8819,18 +9383,18 @@ postcss-modules-extract-imports@^3.0.0: integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + version "4.0.4" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz#7cbed92abd312b94aaea85b68226d3dec39a14e6" + integrity sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q== dependencies: icss-utils "^5.0.0" postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz#32cfab55e84887c079a19bbb215e721d683ef134" + integrity sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA== dependencies: postcss-selector-parser "^6.0.4" @@ -8842,9 +9406,9 @@ postcss-modules-values@^4.0.0: icss-utils "^5.0.0" postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: - version "6.0.11" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc" - integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== + version "6.0.16" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz#3b88b9f5c5abd989ef4e2fc9ec8eedd34b20fb04" + integrity sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -8854,15 +9418,24 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@8.4.21, postcss@^8.2.14, postcss@^8.3.7, postcss@^8.4.19: - version "8.4.21" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" - integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== +postcss@8.4.31: + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== dependencies: - nanoid "^3.3.4" + nanoid "^3.3.6" picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^8.2.14, postcss@^8.3.7, postcss@^8.4.19: + version "8.4.36" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.36.tgz#dba513c3c3733c44e0288a712894f8910bbaabc6" + integrity sha512-/n7eumA6ZjFHAsbX30yhHup/IMkOmlmvtEi7P+6RMYf+bGJSUHc3geH4a0NSZxAz/RJfiS9tooCTs9LAVYUZKw== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.1.0" + postinstall-prepare@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postinstall-prepare/-/postinstall-prepare-2.0.0.tgz#2a6867c1a13a05502aa115d0495efbbd778769cb" @@ -8874,9 +9447,9 @@ prelude-ls@^1.2.1: integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier@^2.8.3: - version "2.8.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" - integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== pretty-bytes@^5.3.0: version "5.6.0" @@ -8959,20 +9532,15 @@ prr@~1.0.1: resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== - psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== punycode@^2.1.0, punycode@^2.1.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" - integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== q@1.4.1: version "1.4.1" @@ -8990,9 +9558,9 @@ qjobs@^1.2.0: integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== qrcode@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.1.tgz#0103f97317409f7bc91772ef30793a54cd59f0cb" - integrity sha512-nS8NJ1Z3md8uTjKtP+SGGhfqmTCs5flU/xR623oI0JX+Wepz9R8UrRVCTBTJm3qGw3rH6jJ6MUHjkDx15cxSSg== + version "1.5.3" + resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" + integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg== dependencies: dijkstrajs "^1.0.1" encode-utf8 "^1.0.3" @@ -9040,16 +9608,6 @@ raphael@^2.3.0: dependencies: eve-raphael "0.5.0" -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - raw-body@2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" @@ -9087,32 +9645,32 @@ rc-align@^4.0.0: resize-observer-polyfill "^1.5.1" rc-motion@^2.0.0, rc-motion@^2.0.1: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.6.3.tgz#e6d8ca06591c2c1bcd3391a8e7a822ebc4d94e9c" - integrity sha512-xFLkes3/7VL/J+ah9jJruEW/Akbx5F6jVa2wG5o/ApGKQKSOd5FR3rseHLL9+xtJg4PmCwo6/1tqhDO/T+jFHA== + version "2.9.0" + resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.9.0.tgz#9e18a1b8d61e528a97369cf9a7601e9b29205710" + integrity sha512-XIU2+xLkdIr1/h6ohPZXyPBMvOmuyFZQ/T0xnawz+Rh+gh4FINcnZmMT5UTIj6hgI0VLDjTaPeRd+smJeSPqiQ== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-util "^5.21.0" rc-overflow@^1.0.0: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc-overflow/-/rc-overflow-1.2.8.tgz#40f140fabc244118543e627cdd1ef750d9481a88" - integrity sha512-QJ0UItckWPQ37ZL1dMEBAdY1dhfTXFL9k6oTTcyydVwoUNMnMqCGqnRNA98axSr/OeDKqR6DVFyi8eA5RQI/uQ== + version "1.3.2" + resolved "https://registry.yarnpkg.com/rc-overflow/-/rc-overflow-1.3.2.tgz#72ee49e85a1308d8d4e3bd53285dc1f3e0bcce2c" + integrity sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw== dependencies: "@babel/runtime" "^7.11.1" classnames "^2.2.1" rc-resize-observer "^1.0.0" - rc-util "^5.19.2" + rc-util "^5.37.0" rc-resize-observer@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.3.1.tgz#b61b9f27048001243617b81f95e53d7d7d7a6a3d" - integrity sha512-iFUdt3NNhflbY3mwySv5CA1TC06zdJ+pfo0oc27xpf4PIOvfZwZGtD9Kz41wGYqC4SLio93RVAirSSpYlV/uYg== + version "1.4.0" + resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz#7bba61e6b3c604834980647cce6451914750d0cc" + integrity sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q== dependencies: "@babel/runtime" "^7.20.7" classnames "^2.2.1" - rc-util "^5.27.0" + rc-util "^5.38.0" resize-observer-polyfill "^1.5.1" rc-select@13.2.1: @@ -9139,23 +9697,23 @@ rc-trigger@^5.0.4: rc-motion "^2.0.0" rc-util "^5.19.2" -rc-util@^5.15.0, rc-util@^5.19.2, rc-util@^5.21.0, rc-util@^5.26.0, rc-util@^5.27.0, rc-util@^5.9.8: - version "5.28.0" - resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.28.0.tgz#9e5e441d5875b8bf0ba56c2f295042a28dcff580" - integrity sha512-KYDjhGodswVj29v0TRciKTqRPgumIFvFDndbCD227pitQ+0Cei196rxk+OXb/blu6V8zdTRK5RjCJn+WmHLvBA== +rc-util@^5.19.2, rc-util@^5.21.0, rc-util@^5.26.0, rc-util@^5.36.0, rc-util@^5.37.0, rc-util@^5.38.0, rc-util@^5.9.8: + version "5.39.1" + resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.39.1.tgz#7bca4fb55e20add0eef5c23166cd9f9e5f51a8a1" + integrity sha512-OW/ERynNDgNr4y0oiFmtes3rbEamXw7GHGbkbNd9iRr7kgT03T6fT0b9WpJ3mbxKhyOcAHnGcIoh5u/cjrC2OQ== dependencies: "@babel/runtime" "^7.18.3" - react-is "^16.12.0" + react-is "^18.2.0" rc-virtual-list@^3.2.0: - version "3.4.13" - resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.4.13.tgz#20acc934b263abcf7b7c161f50ef82281b2f7e8d" - integrity sha512-cPOVDmcNM7rH6ANotanMDilW/55XnFPw0Jh/GQYtrzZSy3AmWvCnqVNyNC/pgg3lfVmX2994dlzAhuUrd4jG7w== + version "3.11.4" + resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.11.4.tgz#d0a8937843160b7b00d5586854290bf56d396af7" + integrity sha512-NbBi0fvyIu26gP69nQBiWgUMTPX3mr4FcuBQiVqagU0BnuX8WQkiivnMs105JROeuUIFczLrlgUhLQwTWV1XDA== dependencies: "@babel/runtime" "^7.20.0" classnames "^2.2.6" rc-resize-observer "^1.0.0" - rc-util "^5.15.0" + rc-util "^5.36.0" react-ace@9.5.0: version "9.5.0" @@ -9186,7 +9744,7 @@ react-dropzone@^11.4.2: file-selector "^0.4.0" prop-types "^15.8.1" -react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: +react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -9196,6 +9754,11 @@ react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-is@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + react-transition-group@^4.0.0, react-transition-group@^4.4.0: version "4.4.5" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" @@ -9230,11 +9793,11 @@ read-package-json-fast@^3.0.0: npm-normalize-package-bin "^3.0.0" read-package-json@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-6.0.0.tgz#6a741841ad72a40e77a82b9c3c8c10e865bbc519" - integrity sha512-b/9jxWJ8EwogJPpv99ma+QwtqB7FSl3+V6UXS7Aaay8/5VwMY50oIFooY1UKXMWpfNCM6T/PoGqa5GD1g9xf9w== + version "6.0.4" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-6.0.4.tgz#90318824ec456c287437ea79595f4c2854708836" + integrity sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw== dependencies: - glob "^8.0.1" + glob "^10.2.2" json-parse-even-better-errors "^3.0.0" normalize-package-data "^5.0.0" npm-normalize-package-bin "^3.0.0" @@ -9253,9 +9816,9 @@ readable-stream@^2.0.1, readable-stream@~2.3.6: util-deprecate "~1.0.1" readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.1.tgz#f9f9b5f536920253b3d26e7660e7da4ccff9bb62" - integrity sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -9274,14 +9837,14 @@ reduce-flatten@^2.0.0: integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== reflect-metadata@^0.1.2: - version "0.1.13" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" - integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== + version "0.1.14" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.14.tgz#24cf721fe60677146bb77eeb0e1f9dece3d65859" + integrity sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A== regenerate-unicode-properties@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" - integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== + version "10.1.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== dependencies: regenerate "^1.4.2" @@ -9295,31 +9858,37 @@ regenerator-runtime@^0.13.11: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== -regenerator-transform@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" - integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== dependencies: "@babel/runtime" "^7.8.4" regex-parser@^2.2.11: - version "2.2.11" - resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" - integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q== + version "2.3.0" + resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.3.0.tgz#4bb61461b1a19b8b913f3960364bb57887f920ee" + integrity sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg== -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== +regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" + integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" + call-bind "^1.0.6" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.1" regexpu-core@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.1.tgz#66900860f88def39a5cb79ebd9490e84f17bcdfb" - integrity sha512-nCOzW2V/X15XpLsK2rlgdwrysrBq+AauCn+omItIz4R1pIcmeot5zvjdmOBRLzEH/CkC6IxMJVmxDe3QcMuNVQ== + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== dependencies: "@babel/regjsgen" "^0.8.0" regenerate "^1.4.2" @@ -9407,7 +9976,7 @@ resolve-url-loader@5.0.0: postcss "^8.2.14" source-map "0.6.1" -resolve@1.22.1, resolve@^1.14.2, resolve@^1.22.1: +resolve@1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -9416,6 +9985,15 @@ resolve@1.22.1, resolve@^1.14.2, resolve@^1.22.1: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.14.2, resolve@^1.22.4: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -9440,9 +10018,9 @@ reusify@^1.0.4: integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + version "1.3.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" + integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== rifm@^0.7.0: version "0.7.0" @@ -9465,10 +10043,10 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" -robust-predicates@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a" - integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g== +robust-predicates@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== run-async@^2.4.0: version "2.4.1" @@ -9495,12 +10073,22 @@ rxjs@6.6.7: tslib "^1.9.0" rxjs@^7.5.5, rxjs@~7.8.0: - version "7.8.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" - integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== dependencies: tslib "^2.1.0" +safe-array-concat@^1.1.0, safe-array-concat@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" + integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -9516,13 +10104,13 @@ safe-identifier@^0.4.1: resolved "https://registry.yarnpkg.com/safe-identifier/-/safe-identifier-0.4.2.tgz#cf6bfca31c2897c588092d1750d30ef501d59fcb" integrity sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w== -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== +safe-regex-test@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" + call-bind "^1.0.6" + es-errors "^1.3.0" is-regex "^1.1.4" "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: @@ -9560,9 +10148,9 @@ saucelabs@^1.5.0: https-proxy-agent "^2.2.1" sax@>=0.6.0, sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + version "1.3.0" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" + integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== scheduler@^0.20.2: version "0.20.2" @@ -9573,30 +10161,30 @@ scheduler@^0.20.2: object-assign "^4.1.1" schema-inspector@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/schema-inspector/-/schema-inspector-2.0.2.tgz#3b902e9095f4636428a890203d469b0d404ada5b" - integrity sha512-phq0/I55VGzl4kmq3Tp1jlY75Xtc1o7wfGmOEFTgGyucI6zIdEsiM7MJu9jjQf2SfMreqSbTi/ktUsEMs6pV7A== + version "2.1.0" + resolved "https://registry.yarnpkg.com/schema-inspector/-/schema-inspector-2.1.0.tgz#85096fbc78162a420262ed41b82e60ac927767b2" + integrity sha512-3bmQVhbA01/EW8cZin4vIpqlpNU2SIy4BhKCfCgogJ3T/L76dLx3QAE+++4o+dNT33sa+SN9vOJL7iHiHFjiNg== dependencies: async "~2.6.3" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== dependencies: "@types/json-schema" "^7.0.8" ajv "^6.12.5" ajv-keywords "^3.5.2" schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" - integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== dependencies: "@types/json-schema" "^7.0.9" - ajv "^8.8.0" + ajv "^8.9.0" ajv-formats "^2.1.1" - ajv-keywords "^5.0.0" + ajv-keywords "^5.1.0" screenfull@^6.0.2: version "6.0.2" @@ -9624,28 +10212,36 @@ selenium-webdriver@3.6.0, selenium-webdriver@^3.0.1: xml2js "^0.4.17" selfsigned@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" - integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== + version "2.4.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== dependencies: + "@types/node-forge" "^1.3.0" node-forge "^1" -semver@7.3.8, semver@^7.0.0, semver@^7.1.1, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== +semver@7.5.3: + version "7.5.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" + integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.0.0, semver@^7.1.1, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" send@0.18.0: version "0.18.0" @@ -9666,10 +10262,10 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" - integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== +serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== dependencies: randombytes "^2.1.0" @@ -9701,6 +10297,28 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -9748,31 +10366,35 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -sigmund@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - integrity sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g== + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + sigstore@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-1.0.0.tgz#3c7a8bbacf99d0f978276bd29bd94911006b72c7" - integrity sha512-e+qfbn/zf1+rCza/BhIA//Awmf0v1pa5HQS8Xk8iXrn9bgytytVLqYD0P7NSqZ6IELTgq+tcDvLPkQjNHyWLNg== + version "1.9.0" + resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-1.9.0.tgz#1e7ad8933aa99b75c6898ddd0eeebc3eb0d59875" + integrity sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A== dependencies: + "@sigstore/bundle" "^1.1.0" + "@sigstore/protobuf-specs" "^0.2.0" + "@sigstore/sign" "^1.0.0" + "@sigstore/tuf" "^1.0.3" make-fetch-happen "^11.0.1" - tuf-js "^1.0.0" slash@^2.0.0: version "2.0.0" @@ -9795,31 +10417,33 @@ smart-buffer@^4.2.0: integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== socket.io-adapter@~2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12" - integrity sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA== + version "2.5.4" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz#4fdb1358667f6d68f25343353bd99bd11ee41006" + integrity sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg== dependencies: + debug "~4.3.4" ws "~8.11.0" -socket.io-parser@~4.2.1: - version "4.2.2" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.2.tgz#1dd384019e25b7a3d374877f492ab34f2ad0d206" - integrity sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw== +socket.io-parser@~4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" + integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== dependencies: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" socket.io@^4.4.1: - version "4.6.1" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.6.1.tgz#62ec117e5fce0692fa50498da9347cfb52c3bc70" - integrity sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA== + version "4.7.5" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.5.tgz#56eb2d976aef9d1445f373a62d781a41c7add8f8" + integrity sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA== dependencies: accepts "~1.3.4" base64id "~2.0.0" + cors "~2.8.5" debug "~4.3.2" - engine.io "~6.4.1" + engine.io "~6.5.2" socket.io-adapter "~2.5.2" - socket.io-parser "~4.2.1" + socket.io-parser "~4.2.4" sockjs@^0.3.24: version "0.3.24" @@ -9840,11 +10464,11 @@ socks-proxy-agent@^7.0.0: socks "^2.6.2" socks@^2.6.2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" - integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + version "2.8.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.1.tgz#22c7d9dd7882649043cba0eafb49ae144e3457af" + integrity sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ== dependencies: - ip "^2.0.0" + ip-address "^9.0.5" smart-buffer "^4.2.0" sorted-btree@^1.8.1: @@ -9852,10 +10476,10 @@ sorted-btree@^1.8.1: resolved "https://registry.yarnpkg.com/sorted-btree/-/sorted-btree-1.8.1.tgz#6e6275f7955e5892bb8737149cbe495be10f426f" integrity sha512-395+XIP+wqNn3USkFSrNz7G3Ss/MXlZEqesxvzCRFwL14h6e8LukDHdLBePn5pwbm5OQ9vGu8mDyz2lLDIqamQ== -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.1.0.tgz#9e7d5cb46f0689fb6691b30f226937558d0fa94b" + integrity sha512-9vC2SfsJzlej6MAaMPLu8HiBSHGdRAJ9hVFYN1ibZoNkeanmDmLUcIrj6G9DGL7XMJ54AKg/G75akXl1/izTOw== source-map-loader@4.0.1: version "4.0.1" @@ -9897,19 +10521,19 @@ source-map@^0.5.6: integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== -spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: +spdx-expression-parse@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== @@ -9917,10 +10541,18 @@ spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" +spdx-expression-parse@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz#a23af9f3132115465dac215c099303e4ceac5794" + integrity sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + spdx-license-ids@^3.0.0: - version "3.0.12" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" - integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + version "3.0.17" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c" + integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg== spdy-transport@^3.0.0: version "3.0.0" @@ -9946,24 +10578,29 @@ spdy@^4.0.2: spdy-transport "^3.0.0" splaytree@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/splaytree/-/splaytree-3.1.1.tgz#e1bc8e68e64ef5a9d5f09d36e6d9f3621795a438" - integrity sha512-9FaQ18FF0+sZc/ieEeXHt+Jw2eSpUgUtTLDYB/HXKWvhYVyOc7h1hzkn5MMO3GPib9MmXG1go8+OsBBzs/NMww== + version "3.1.2" + resolved "https://registry.yarnpkg.com/splaytree/-/splaytree-3.1.2.tgz#d1db2691665a3c69d630de98d55145a6546dc166" + integrity sha512-4OM2BJgC5UzrhVnnJA4BkHKGtjXNzzUfpQjCO8I05xYPsfS/VuQDwjCGGMi8rYQilHEV4j8NBqTFbls/PZEE7A== split.js@^1.6.5: version "1.6.5" resolved "https://registry.yarnpkg.com/split.js/-/split.js-1.6.5.tgz#f7f61da1044c9984cb42947df4de4fadb5a3f300" integrity sha512-mPTnGCiS/RiuTNsVhCm9De9cCAUsrNFFviRbADdKiiV+Kk8HKp/0fWu7Kr8pi3/yBmsqLFHuXGT9UUZ+CNLwFw== +sprintf-js@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== sshpk@^1.7.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -9976,11 +10613,11 @@ sshpk@^1.7.0: tweetnacl "~0.14.0" ssri@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.1.tgz#c61f85894bbc6929fc3746f05e31cf5b44c030d5" - integrity sha512-WVy6di9DlPOeBWEjMScpNipeSX2jIZBGEn5Uuo8Q7aIuFEuDX0pw8RxcOjlD1TWP4obi24ki7m/13+nFpcbXrw== + version "10.0.5" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.5.tgz#e49efcd6e36385196cb515d3a2ad6c3f0265ef8c" + integrity sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A== dependencies: - minipass "^4.0.0" + minipass "^7.0.3" ssri@^9.0.0: version "9.0.1" @@ -10015,7 +10652,7 @@ streamroller@^3.1.5: debug "^4.3.4" fs-extra "^8.1.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -10024,23 +10661,42 @@ streamroller@^3.1.5: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" -string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== +string.prototype.trim@^1.2.8, string.prototype.trim@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" + integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" + +string.prototype.trimend@^1.0.7, string.prototype.trimend@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" + integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" string_decoder@^1.1.1: version "1.3.0" @@ -10056,6 +10712,13 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -10063,12 +10726,12 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: - ansi-regex "^5.0.1" + ansi-regex "^6.0.1" strip-bom@^3.0.0: version "3.0.0" @@ -10080,15 +10743,15 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== stylis@^4.1.2: - version "4.1.3" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.3.tgz#fd2fbe79f5fed17c55269e16ed8da14c84d069f7" - integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA== + version "4.3.1" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.1.tgz#ed8a9ebf9f76fe1e12d462f5cc3c4c980b23a7eb" + integrity sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ== supports-color@^2.0.0: version "2.0.0" @@ -10147,27 +10810,27 @@ tapable@^2.1.1, tapable@^2.2.0: integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== tar@^6.1.11, tar@^6.1.2: - version "6.1.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b" - integrity sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw== + version "6.2.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" + integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" - minipass "^4.0.0" + minipass "^5.0.0" minizlib "^2.1.1" mkdirp "^1.0.3" yallist "^4.0.0" -terser-webpack-plugin@^5.1.3: - version "5.3.6" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" - integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== +terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== dependencies: - "@jridgewell/trace-mapping" "^0.3.14" + "@jridgewell/trace-mapping" "^0.3.20" jest-worker "^27.4.5" schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - terser "^5.14.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" terser@5.16.3: version "5.16.3" @@ -10179,13 +10842,13 @@ terser@5.16.3: commander "^2.20.0" source-map-support "~0.5.20" -terser@^5.14.1: - version "5.16.5" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.5.tgz#1c285ca0655f467f92af1bbab46ab72d1cb08e5a" - integrity sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg== +terser@^5.26.0: + version "5.29.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.29.2.tgz#c17d573ce1da1b30f21a877bffd5655dd86fdb35" + integrity sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw== dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" commander "^2.20.0" source-map-support "~0.5.20" @@ -10236,14 +10899,14 @@ tinycolor2@^1.6.0: integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== "tinymce@^6.0.0 || ^5.5.0": - version "6.3.1" - resolved "https://registry.yarnpkg.com/tinymce/-/tinymce-6.3.1.tgz#cc5cf2b9f702d429cf5d1d21ed62245d768bfc4f" - integrity sha512-+oCwXuTxAdJXVJ0130OxQz0JDNsqg3deuzgeUo8X5Vb27EzCJgXwO5eWvCxvkxpQo4oiHMVlM4tUIpTUHufHGQ== + version "6.8.3" + resolved "https://registry.yarnpkg.com/tinymce/-/tinymce-6.8.3.tgz#0025a4aaa4c24dc2a3e32e83dfda705d196fd802" + integrity sha512-3fCHKAeqT+xNwBVESf6iDbDV0VNwZNmfrkx9c/6Gz5iB8piMfaO6s7FvoiTrj1hf1gVbfyLTnz1DooI6DhgINQ== tinymce@~5.10.7: - version "5.10.7" - resolved "https://registry.yarnpkg.com/tinymce/-/tinymce-5.10.7.tgz#d89d446f1962f2a1df6b2b70018ce475ec7ffb80" - integrity sha512-9UUjaO0R7FxcFo0oxnd1lMs7H+D0Eh+dDVo5hKbVe1a+VB0nit97vOqlinj+YwgoBDt6/DSCUoWqAYlLI8BLYA== + version "5.10.9" + resolved "https://registry.yarnpkg.com/tinymce/-/tinymce-5.10.9.tgz#1dfacb3231c71a688d90ff44a0b3f2e91b3b9edf" + integrity sha512-5bkrors87X9LhYX2xq8GgPHrIgJYHl87YNs+kBcjQ5I3CiUgzo/vFcGvT3MZQ9QHsEeYMhYO6a5CLGGffR8hMg== tmp@0.0.30: version "0.0.30" @@ -10252,7 +10915,7 @@ tmp@0.0.30: dependencies: os-tmpdir "~1.0.1" -tmp@0.2.1, tmp@^0.2.1: +tmp@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== @@ -10266,6 +10929,11 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tmp@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" + integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -10307,9 +10975,9 @@ ts-dedent@^2.2.0: integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== ts-node@^10.0.0, ts-node@^10.9.1: - version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" - integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== dependencies: "@cspotcode/source-map-support" "^0.8.0" "@tsconfig/node10" "^1.0.7" @@ -10330,10 +10998,10 @@ ts-transformer-keys@^0.4.4: resolved "https://registry.yarnpkg.com/ts-transformer-keys/-/ts-transformer-keys-0.4.4.tgz#c185508b3ae9b79236aac58f788c85ca3ac807d7" integrity sha512-LrqgvaFvar01/5mbunRyeLTSIkqoC2xfcpL/90aDY6vR07DGyH+UaYGdIEsUudnlAw2Sr0pxFgdZvE0QIyI4qA== -tsconfig-paths@^3.14.1: - version "3.14.2" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" - integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== dependencies: "@types/json5" "^0.0.29" json5 "^1.0.2" @@ -10341,9 +11009,9 @@ tsconfig-paths@^3.14.1: strip-bom "^3.0.0" tsconfig-paths@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz#4819f861eef82e6da52fb4af1e8c930a39ed979a" - integrity sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw== + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== dependencies: json5 "^2.2.2" minimist "^1.2.6" @@ -10354,7 +11022,7 @@ tslib@2.3.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== -tslib@2.5.0, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.5.0: +tslib@2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== @@ -10364,6 +11032,11 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -10371,13 +11044,14 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" -tuf-js@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-1.1.0.tgz#25dd680bce9e3819e1fe4640d85186f862efb827" - integrity sha512-Tsqlm419OAlrkCE6rsf1WuPvww44vfK1ZHz+Uq9Mpq5JiV5qnJ9LLItvsbM9OipIIeSG3rydVBS4BmD40ts2uA== +tuf-js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-1.1.7.tgz#21b7ae92a9373015be77dfe0cb282a80ec3bbe43" + integrity sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg== dependencies: - "@tufjs/models" "1.0.0" - make-fetch-happen "^11.0.1" + "@tufjs/models" "1.0.4" + debug "^4.3.4" + make-fetch-happen "^11.1.1" tunnel-agent@^0.6.0: version "0.6.0" @@ -10421,14 +11095,49 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== +typed-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" + integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" + es-errors "^1.3.0" + is-typed-array "^1.1.13" + +typed-array-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" + integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-byte-offset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" + integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-length@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.5.tgz#57d44da160296d8663fd63180a1802ebf25905d5" + integrity sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA== + dependencies: + call-bind "^1.0.7" for-each "^0.3.3" - is-typed-array "^1.1.9" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" typed-assert@^1.0.8: version "1.0.9" @@ -10456,9 +11165,9 @@ typical@^5.2.0: integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== ua-parser-js@^0.7.30: - version "0.7.33" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.33.tgz#1d04acb4ccef9293df6f70f2c3d22f3030d8b532" - integrity sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw== + version "0.7.37" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.37.tgz#e464e66dac2d33a7a1251d7d7a99d6157ec27832" + integrity sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA== unbox-primitive@^1.0.2: version "1.0.2" @@ -10470,6 +11179,11 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" @@ -10527,19 +11241,19 @@ universalify@^0.1.0: integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" - integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== +update-browserslist-db@^1.0.10, update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== dependencies: escalade "^3.1.1" picocolors "^1.0.0" @@ -10579,9 +11293,9 @@ uuid@^8.3.2: integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== uuid@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" - integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== v8-compile-cache-lib@^3.0.1: version "3.0.1" @@ -10623,9 +11337,9 @@ void-elements@^2.0.0: integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -10644,6 +11358,11 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +web-worker@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.3.0.tgz#e5f2df5c7fe356755a5fb8f8410d4312627e6776" + integrity sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA== + webdriver-js-extender@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz#57d7a93c00db4cc8d556e4d3db4b5db0a80c3bb7" @@ -10726,7 +11445,7 @@ webpack-dev-server@4.11.1: webpack-dev-middleware "^5.3.1" ws "^8.4.2" -webpack-merge@5.8.0, webpack-merge@^5.7.3: +webpack-merge@5.8.0: version "5.8.0" resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== @@ -10734,6 +11453,15 @@ webpack-merge@5.8.0, webpack-merge@^5.7.3: clone-deep "^4.0.1" wildcard "^2.0.0" +webpack-merge@^5.7.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.0" + webpack-sources@^3.0.0, webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" @@ -10746,36 +11474,6 @@ webpack-subresource-integrity@5.1.0: dependencies: typed-assert "^1.0.8" -webpack@5.75.0: - version "5.75.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" - integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" - webpack-sources "^3.2.3" - webpack@5.76.1: version "5.76.1" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.1.tgz#7773de017e988bccb0f13c7d75ec245f377d295c" @@ -10807,21 +11505,21 @@ webpack@5.76.1: webpack-sources "^3.2.3" webpack@^5.77.0: - version "5.77.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.77.0.tgz#dea3ad16d7ea6b84aa55fa42f4eac9f30e7eb9b4" - integrity sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q== + version "5.90.3" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.90.3.tgz#37b8f74d3ded061ba789bb22b31e82eed75bd9ac" + integrity sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.11.5" + "@webassemblyjs/wasm-edit" "^1.11.5" + "@webassemblyjs/wasm-parser" "^1.11.5" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" + acorn-import-assertions "^1.9.0" + browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + enhanced-resolve "^5.15.0" + es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" @@ -10830,9 +11528,9 @@ webpack@^5.77.0: loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.0" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" + terser-webpack-plugin "^5.3.10" watchpack "^2.4.0" webpack-sources "^3.2.3" @@ -10862,31 +11560,30 @@ which-boxed-primitive@^1.0.2: is-symbol "^1.0.3" which-collection@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" - integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== dependencies: - is-map "^2.0.1" - is-set "^2.0.1" - is-weakmap "^2.0.1" - is-weakset "^2.0.1" + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== -which-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== +which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" for-each "^0.3.3" gopd "^1.0.1" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" + has-tostringtag "^1.0.2" which@^1.2.1, which@^1.2.9: version "1.3.1" @@ -10903,9 +11600,9 @@ which@^2.0.1, which@^2.0.2: isexe "^2.0.0" which@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/which/-/which-3.0.0.tgz#a9efd016db59728758a390d23f1687b6e8f59f8e" - integrity sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ== + version "3.0.1" + resolved "https://registry.yarnpkg.com/which/-/which-3.0.1.tgz#89f1cd0c23f629a8105ffe69b8172791c87b4be1" + integrity sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg== dependencies: isexe "^2.0.0" @@ -10917,14 +11614,9 @@ wide-align@^1.1.5: string-width "^1.0.2 || 2 || 3 || 4" wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== wordwrapjs@^4.0.0: version "4.0.1" @@ -10934,6 +11626,15 @@ wordwrapjs@^4.0.0: reduce-flatten "^2.0.0" typical "^5.2.0" +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -10943,14 +11644,14 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" wrappy@1: version "1.0.2" @@ -10958,9 +11659,9 @@ wrappy@1: integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== ws@^8.4.2: - version "8.12.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.1.tgz#c51e583d79140b5e42e39be48c934131942d4a8f" - integrity sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew== + version "8.16.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" + integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== ws@~8.11.0: version "8.11.0" @@ -10990,11 +11691,6 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== - yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -11072,9 +11768,9 @@ yargs@^16.1.1: yargs-parser "^20.2.2" yargs@^17.2.1: - version "17.7.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" - integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" escalade "^3.1.1" @@ -11095,9 +11791,9 @@ yocto-queue@^0.1.0: integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== zone.js@~0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.13.0.tgz#4c735cb8ef49312b58c0ad13451996dc2b202a6d" - integrity sha512-7m3hNNyswsdoDobCkYNAy5WiUulkMd3+fWaGT9ij6iq3Zr/IwJo4RMCYPSDjT+r7tnPErmY9sZpKhWQ8S5k6XQ== + version "0.13.3" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.13.3.tgz#344c24098fa047eda6427a4c7ed486e391fd67b5" + integrity sha512-MKPbmZie6fASC/ps4dkmIhaT5eonHkEt6eAy80K42tAm0G2W+AahLJjbfi6X9NPdciOE9GRFTTM8u2IiF6O3ww== dependencies: tslib "^2.3.0" From 0cd0c65a08c47f6b31e8e52c02b6986e42922dc4 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Mon, 18 Mar 2024 12:37:36 +0200 Subject: [PATCH 363/397] do not refresh token if refresh token expired --- .../mail/RefreshTokenExpCheckService.java | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/mail/RefreshTokenExpCheckService.java b/application/src/main/java/org/thingsboard/server/service/mail/RefreshTokenExpCheckService.java index 8e6dfce8f0..7c7edf2164 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/RefreshTokenExpCheckService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/RefreshTokenExpCheckService.java @@ -56,22 +56,33 @@ public class RefreshTokenExpCheckService { JsonNode jsonValue = settings.getJsonValue(); if (OFFICE_365.name().equals(jsonValue.get("providerId").asText()) && jsonValue.has("refreshToken") && jsonValue.has("refreshTokenExpires")) { - long expiresIn = jsonValue.get("refreshTokenExpires").longValue(); - if ((expiresIn - System.currentTimeMillis()) < 604800000L) { //less than 7 days - log.info("Trying to refresh refresh token."); + try { + long expiresIn = jsonValue.get("refreshTokenExpires").longValue(); + long tokenLifeDuration = expiresIn - System.currentTimeMillis(); + if (tokenLifeDuration < 0) { + ((ObjectNode) jsonValue).put("tokenGenerated", false); + ((ObjectNode) jsonValue).remove("refreshToken"); + ((ObjectNode) jsonValue).remove("refreshTokenExpires"); - String clientId = jsonValue.get("clientId").asText(); - String clientSecret = jsonValue.get("clientSecret").asText(); - String refreshToken = jsonValue.get("refreshToken").asText(); - String tokenUri = jsonValue.get("tokenUri").asText(); + adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, settings); + } else if (tokenLifeDuration < 604800000L) { //less than 7 days + log.info("Trying to refresh refresh token."); - TokenResponse tokenResponse = new RefreshTokenRequest(new NetHttpTransport(), new GsonFactory(), - new GenericUrl(tokenUri), refreshToken) - .setClientAuthentication(new ClientParametersAuthentication(clientId, clientSecret)) - .execute(); - ((ObjectNode) jsonValue).put("refreshToken", tokenResponse.getRefreshToken()); - ((ObjectNode) jsonValue).put("refreshTokenExpires", Instant.now().plus(Duration.ofDays(AZURE_DEFAULT_REFRESH_TOKEN_LIFETIME_IN_DAYS)).toEpochMilli()); - adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, settings); + String clientId = jsonValue.get("clientId").asText(); + String clientSecret = jsonValue.get("clientSecret").asText(); + String refreshToken = jsonValue.get("refreshToken").asText(); + String tokenUri = jsonValue.get("tokenUri").asText(); + + TokenResponse tokenResponse = new RefreshTokenRequest(new NetHttpTransport(), new GsonFactory(), + new GenericUrl(tokenUri), refreshToken) + .setClientAuthentication(new ClientParametersAuthentication(clientId, clientSecret)) + .execute(); + ((ObjectNode) jsonValue).put("refreshToken", tokenResponse.getRefreshToken()); + ((ObjectNode) jsonValue).put("refreshTokenExpires", Instant.now().plus(Duration.ofDays(AZURE_DEFAULT_REFRESH_TOKEN_LIFETIME_IN_DAYS)).toEpochMilli()); + adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, settings); + } + } catch (Exception e) { + log.error("Error occurred while checking token", e); } } } From f4733a44b41ef5442c60bf936bcaa1037a393fd3 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 18 Mar 2024 12:47:32 +0200 Subject: [PATCH 364/397] Fix existingNotificationTypes for Edge --- .../dao/notification/DefaultNotificationSettingsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationSettingsService.java b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationSettingsService.java index 1bdc835b29..b719de0192 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationSettingsService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationSettingsService.java @@ -222,7 +222,7 @@ public class DefaultNotificationSettingsService implements NotificationSettingsS } else { var requiredNotificationTypes = List.of(NotificationType.EDGE_CONNECTION, NotificationType.EDGE_COMMUNICATION_FAILURE); var existingNotificationTypes = notificationTemplateService.findNotificationTemplatesByTenantIdAndNotificationTypes( - tenantId, requiredNotificationTypes, new PageLink(1)) + tenantId, requiredNotificationTypes, new PageLink(2)) .getData() .stream() .map(NotificationTemplate::getNotificationType) From 7ead550348f92ee3c550b62aaaa7d39a2539f6c3 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 18 Mar 2024 13:28:11 +0200 Subject: [PATCH 365/397] UI: Update minor versions. --- ui-ngx/package.json | 33 +++---- ui-ngx/yarn.lock | 216 ++++++++++---------------------------------- 2 files changed, 63 insertions(+), 186 deletions(-) diff --git a/ui-ngx/package.json b/ui-ngx/package.json index c39817749f..0ba5880ed3 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -14,17 +14,17 @@ }, "private": true, "dependencies": { - "@angular/animations": "^15.2.9", + "@angular/animations": "^15.2.10", "@angular/cdk": "^15.2.9", - "@angular/common": "^15.2.9", - "@angular/compiler": "^15.2.9", - "@angular/core": "^15.2.9", + "@angular/common": "^15.2.10", + "@angular/compiler": "^15.2.10", + "@angular/core": "^15.2.10", "@angular/flex-layout": "^15.0.0-beta.42", - "@angular/forms": "^15.2.9", + "@angular/forms": "^15.2.10", "@angular/material": "^15.2.9", - "@angular/platform-browser": "^15.2.9", - "@angular/platform-browser-dynamic": "^15.2.9", - "@angular/router": "^15.2.9", + "@angular/platform-browser": "^15.2.10", + "@angular/platform-browser-dynamic": "^15.2.10", + "@angular/router": "^15.2.10", "@auth0/angular-jwt": "^5.1.2", "@date-io/core": "1.3.7", "@date-io/date-fns": "1.3.7", @@ -112,16 +112,16 @@ }, "devDependencies": { "@angular-builders/custom-webpack": "~15.0.0", - "@angular-devkit/build-angular": "^15.2.8", + "@angular-devkit/build-angular": "^15.2.10", "@angular-eslint/builder": "15.2.1", "@angular-eslint/eslint-plugin": "15.2.1", "@angular-eslint/eslint-plugin-template": "15.2.1", "@angular-eslint/schematics": "15.2.1", "@angular-eslint/template-parser": "15.2.1", - "@angular/cli": "^15.2.8", - "@angular/compiler-cli": "^15.2.9", - "@angular/language-service": "^15.2.9", - "@ngtools/webpack": "15.2.1", + "@angular/cli": "^15.2.10", + "@angular/compiler-cli": "^15.2.10", + "@angular/language-service": "^15.2.10", + "@ngtools/webpack": "15.2.10", "@types/ace-diff": "^2.1.1", "@types/canvas-gauges": "^2.1.4", "@types/flot": "^0.0.32", @@ -130,7 +130,7 @@ "@types/jasminewd2": "^2.0.10", "@types/jquery": "^3.5.16", "@types/js-beautify": "^1.13.3", - "@types/leaflet": "^1.8.0", + "@types/leaflet": "~1.8.0", "@types/leaflet-polylinedecorator": "^1.6.1", "@types/leaflet-providers": "^1.2.1", "@types/leaflet.gridlayer.googlemutant": "^0.4.6", @@ -166,11 +166,12 @@ "raw-loader": "^4.0.2", "ts-node": "^10.9.1", "typescript": "~4.9.5", - "webpack": "^5.77.0" + "webpack": "5.77.0" }, "resolutions": { "@types/react": "17.0.37", "ace-builds": "1.4.13", - "@date-io/core": "1.3.7" + "@date-io/core": "1.3.7", + "rc-virtual-list": "3.4.13" } } diff --git a/ui-ngx/yarn.lock b/ui-ngx/yarn.lock index 892b959e06..ef25146805 100644 --- a/ui-ngx/yarn.lock +++ b/ui-ngx/yarn.lock @@ -44,7 +44,7 @@ "@angular-devkit/core" "15.2.10" rxjs "6.6.7" -"@angular-devkit/build-angular@^15.0.0", "@angular-devkit/build-angular@^15.2.8": +"@angular-devkit/build-angular@^15.0.0", "@angular-devkit/build-angular@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-15.2.10.tgz#af4080a4811461bd1cab4f3b1b10edef53f31da8" integrity sha512-3pCPVEJilVwHIJC6Su1/PIEqvFfU1Lxew9yItxX4s6dud8HY+fuKrsDnao4NNMFNqCLqL4el5QbSBKnnpWH1sg== @@ -199,7 +199,7 @@ "@angular-eslint/bundled-angular-compiler" "15.2.1" "@typescript-eslint/utils" "5.48.2" -"@angular/animations@^15.2.9": +"@angular/animations@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-15.2.10.tgz#c9194ba9a2b9b4e466e9c76e18591cde096a28e8" integrity sha512-yxfN8qQpMaukRU5LjFkJBmy85rqrOp86tYVCsf+hmPEFRiXBMUj6xYLeCMcpk3Mt1JtnWGBR34ivGx+7bNeAow== @@ -215,7 +215,7 @@ optionalDependencies: parse5 "^7.1.2" -"@angular/cli@^15.2.8": +"@angular/cli@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-15.2.10.tgz#4035a64510e11894be2ff695e48ee0ef6badb494" integrity sha512-/TSnm/ZQML6A4lvunyN2tjTB5utuvk3d1Pnfyehp/FXtV6YfZm6+EZrOpKkKPCxTuAgW6c9KK4yQtt3RuNVpwQ== @@ -239,14 +239,14 @@ symbol-observable "4.0.0" yargs "17.6.2" -"@angular/common@^15.2.9": +"@angular/common@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/common/-/common-15.2.10.tgz#897923023c8ca4a361ce218bdee9a3f09060df75" integrity sha512-jdBn3fctkqoNrJn9VLsUHpcCEhCxWSczdsR+BBbD6T0oLl6vMrAVNjPwfBejnlgfWN1KoRU9kgOYsMxa5apIWQ== dependencies: tslib "^2.3.0" -"@angular/compiler-cli@^15.2.9": +"@angular/compiler-cli@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-15.2.10.tgz#e51013aa0f3da303fc74f8e1948c550d8e74ead5" integrity sha512-mCFIxrs60XicKfA2o42hA7LrQvhybi9BQveWuZn/2iIEOXx7R62Iemz8E21pLWftAZHGxEW3NECfBrY1d3gVmA== @@ -262,14 +262,14 @@ tslib "^2.3.0" yargs "^17.2.1" -"@angular/compiler@^15.2.9": +"@angular/compiler@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-15.2.10.tgz#bd78f327d12eb5978f9dd05440aa23d4b5b925a9" integrity sha512-M0XkeU0O73UlJZwDvOyp8/apetz9UKj78eTFDseMYJDLcxe6MpkbkxqpsGZnKYDj7LIep8PmCAKEkhtenE82zw== dependencies: tslib "^2.3.0" -"@angular/core@^15.2.9": +"@angular/core@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/core/-/core-15.2.10.tgz#93c1e0d460d21711654c578d2709a402e1822023" integrity sha512-meGGidnitQJGDxYd9/LrqYiVlId+vGaLoiLgJdKBz+o2ZO6OmXQGuNw2VBqf17/Cc0/UjzrOY7+kILNFKkk/WQ== @@ -283,14 +283,14 @@ dependencies: tslib "^2.3.0" -"@angular/forms@^15.2.9": +"@angular/forms@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-15.2.10.tgz#09308e887df2fa4d349300c9d1f05cadfb3872b3" integrity sha512-NIntGsNcN6o8L1txsbWXOf6f3K/CUBizdKsxsYVYGJIXEW5qU6UnWmfAZffNNXsT/XvbgUCjgDwT0cAwcqZPuQ== dependencies: tslib "^2.3.0" -"@angular/language-service@^15.2.9": +"@angular/language-service@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-15.2.10.tgz#829a802aaf40bfab21d71463023a3b517500ffa9" integrity sha512-G0g0teF4pBqLTgfyLcoBl55g91sCZvBK+V4VgTD/hXGpXyMNlNpOsgECSMliGQoJlsRLEugFsSlBNqy7CRoBtw== @@ -349,21 +349,21 @@ "@material/typography" "15.0.0-canary.684e33d25.0" tslib "^2.3.0" -"@angular/platform-browser-dynamic@^15.2.9": +"@angular/platform-browser-dynamic@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-15.2.10.tgz#cc9ad3dcded6cb945ee8c4eef14db081dc6c3dfd" integrity sha512-JHP6W+FX715Qv7DhqvfZLuBZXSDJrboiQsR06gUAgDSjAUyhbqmpVg/2YOtgeWpPkzNDtXdPU2PhcRdIv5J3Yg== dependencies: tslib "^2.3.0" -"@angular/platform-browser@^15.2.9": +"@angular/platform-browser@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-15.2.10.tgz#ca5a904b4da9e0cf719414db89514ee4221cb93d" integrity sha512-9tbgVGSJqwfrOzT8aA/kWBLNhJSQ9gUg0CJxwFBSJm8VkBUJrszoBlDsnSvlxx8/W2ejNULKHFTXeUzq0O/+RQ== dependencies: tslib "^2.3.0" -"@angular/router@^15.2.9": +"@angular/router@^15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@angular/router/-/router-15.2.10.tgz#a5d32d769b930e905582ed6c7aa8122e63655738" integrity sha512-LmuqEg0iIXSw7bli6HKJ19cbxP91v37GtRwbGKswyLihqzTgvjBYpvcfMnB5FRQ5LWkTwq5JclkX03dZw290Yg== @@ -2577,11 +2577,6 @@ dependencies: tslib "^2.0.0" -"@ngtools/webpack@15.2.1": - version "15.2.1" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-15.2.1.tgz#439ac075b2dcb9f304f0b7009182cc5049c7988a" - integrity sha512-YtA8rWAglPuf4CSStrFAxaprTSYE+DREGrJFc3WvZLcF5XrwVK+H4CC4Pmz07iYsG1TXShR4bWp1fbGw1cmBKw== - "@ngtools/webpack@15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-15.2.10.tgz#8118450206ae9398d81ca2eebe1b369321ac5583" @@ -3019,7 +3014,7 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^1.0.5": +"@types/estree@*": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== @@ -3155,13 +3150,20 @@ dependencies: "@types/leaflet" "*" -"@types/leaflet@*", "@types/leaflet@^1.8.0": +"@types/leaflet@*": version "1.9.8" resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.9.8.tgz#32162a8eaf305c63267e99470b9603b5883e63e8" integrity sha512-EXdsL4EhoUtGm2GC2ZYtXn+Fzc6pluVgagvo2VC1RHWToLGlTRwVYoDpqS/7QXa01rmDyBjJk3Catpf60VMkwg== dependencies: "@types/geojson" "*" +"@types/leaflet@~1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.8.0.tgz#dc92d3e868fb6d5067b4b59fa08cd4441f84fabe" + integrity sha512-+sXFmiJTFdhaXXIGFlV5re9AdqtAODoXbGAvxx02e5SHXL3ir7ClP5J7pahO8VmzKY3dth4RUS1nf2BTT+DW1A== + dependencies: + "@types/geojson" "*" + "@types/lodash@^4.14.192": version "4.17.0" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3" @@ -3501,44 +3503,21 @@ "@webassemblyjs/helper-numbers" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" -"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.11.5": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" - integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/floating-point-hex-parser@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== -"@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== - "@webassemblyjs/helper-api-error@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== -"@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== - "@webassemblyjs/helper-buffer@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== -"@webassemblyjs/helper-buffer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" - integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== - "@webassemblyjs/helper-numbers@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" @@ -3548,25 +3527,11 @@ "@webassemblyjs/helper-api-error" "1.11.1" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" - "@xtuc/long" "4.2.2" - "@webassemblyjs/helper-wasm-bytecode@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== -"@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== - "@webassemblyjs/helper-wasm-section@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" @@ -3577,16 +3542,6 @@ "@webassemblyjs/helper-wasm-bytecode" "1.11.1" "@webassemblyjs/wasm-gen" "1.11.1" -"@webassemblyjs/helper-wasm-section@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" - integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/ieee754@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" @@ -3594,13 +3549,6 @@ dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - "@webassemblyjs/leb128@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" @@ -3608,23 +3556,11 @@ dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== - dependencies: - "@xtuc/long" "4.2.2" - "@webassemblyjs/utf8@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== -"@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== - "@webassemblyjs/wasm-edit@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" @@ -3639,20 +3575,6 @@ "@webassemblyjs/wasm-parser" "1.11.1" "@webassemblyjs/wast-printer" "1.11.1" -"@webassemblyjs/wasm-edit@^1.11.5": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" - integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-opt" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - "@webassemblyjs/wast-printer" "1.12.1" - "@webassemblyjs/wasm-gen@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" @@ -3664,17 +3586,6 @@ "@webassemblyjs/leb128" "1.11.1" "@webassemblyjs/utf8" "1.11.1" -"@webassemblyjs/wasm-gen@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" - integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - "@webassemblyjs/wasm-opt@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" @@ -3685,16 +3596,6 @@ "@webassemblyjs/wasm-gen" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" -"@webassemblyjs/wasm-opt@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" - integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - "@webassemblyjs/wasm-parser@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" @@ -3707,18 +3608,6 @@ "@webassemblyjs/leb128" "1.11.1" "@webassemblyjs/utf8" "1.11.1" -"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.11.5": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" - integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-api-error" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" - "@webassemblyjs/wast-printer@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" @@ -3727,14 +3616,6 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" - integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== - dependencies: - "@webassemblyjs/ast" "1.12.1" - "@xtuc/long" "4.2.2" - "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -3785,7 +3666,7 @@ ace-diff@^3.0.3: dependencies: diff-match-patch "^1.0.5" -acorn-import-assertions@^1.7.6, acorn-import-assertions@^1.9.0: +acorn-import-assertions@^1.7.6: version "1.9.0" resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== @@ -4359,7 +4240,7 @@ browserslist@4.21.5: node-releases "^2.0.8" update-browserslist-db "^1.0.10" -browserslist@^4.14.5, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.22.2, browserslist@^4.22.3: +browserslist@^4.14.5, browserslist@^4.21.4, browserslist@^4.22.2, browserslist@^4.22.3: version "4.23.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== @@ -5757,7 +5638,7 @@ engine.io@~6.5.2: engine.io-parser "~5.2.1" ws "~8.11.0" -enhanced-resolve@^5.10.0, enhanced-resolve@^5.15.0: +enhanced-resolve@^5.10.0: version "5.16.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787" integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA== @@ -5940,11 +5821,6 @@ es-module-lexer@^0.9.0: resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== -es-module-lexer@^1.2.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" - integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== - es-object-atoms@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" @@ -9697,7 +9573,7 @@ rc-trigger@^5.0.4: rc-motion "^2.0.0" rc-util "^5.19.2" -rc-util@^5.19.2, rc-util@^5.21.0, rc-util@^5.26.0, rc-util@^5.36.0, rc-util@^5.37.0, rc-util@^5.38.0, rc-util@^5.9.8: +rc-util@^5.15.0, rc-util@^5.19.2, rc-util@^5.21.0, rc-util@^5.26.0, rc-util@^5.37.0, rc-util@^5.38.0, rc-util@^5.9.8: version "5.39.1" resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.39.1.tgz#7bca4fb55e20add0eef5c23166cd9f9e5f51a8a1" integrity sha512-OW/ERynNDgNr4y0oiFmtes3rbEamXw7GHGbkbNd9iRr7kgT03T6fT0b9WpJ3mbxKhyOcAHnGcIoh5u/cjrC2OQ== @@ -9705,15 +9581,15 @@ rc-util@^5.19.2, rc-util@^5.21.0, rc-util@^5.26.0, rc-util@^5.36.0, rc-util@^5.3 "@babel/runtime" "^7.18.3" react-is "^18.2.0" -rc-virtual-list@^3.2.0: - version "3.11.4" - resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.11.4.tgz#d0a8937843160b7b00d5586854290bf56d396af7" - integrity sha512-NbBi0fvyIu26gP69nQBiWgUMTPX3mr4FcuBQiVqagU0BnuX8WQkiivnMs105JROeuUIFczLrlgUhLQwTWV1XDA== +rc-virtual-list@3.4.13, rc-virtual-list@^3.2.0: + version "3.4.13" + resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.4.13.tgz#20acc934b263abcf7b7c161f50ef82281b2f7e8d" + integrity sha512-cPOVDmcNM7rH6ANotanMDilW/55XnFPw0Jh/GQYtrzZSy3AmWvCnqVNyNC/pgg3lfVmX2994dlzAhuUrd4jG7w== dependencies: "@babel/runtime" "^7.20.0" classnames "^2.2.6" rc-resize-observer "^1.0.0" - rc-util "^5.36.0" + rc-util "^5.15.0" react-ace@9.5.0: version "9.5.0" @@ -10167,7 +10043,7 @@ schema-inspector@^2.0.2: dependencies: async "~2.6.3" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1, schema-utils@^3.2.0: +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: version "3.3.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== @@ -10821,7 +10697,7 @@ tar@^6.1.11, tar@^6.1.2: mkdirp "^1.0.3" yallist "^4.0.0" -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.10: +terser-webpack-plugin@^5.1.3: version "5.3.10" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== @@ -11504,22 +11380,22 @@ webpack@5.76.1: watchpack "^2.4.0" webpack-sources "^3.2.3" -webpack@^5.77.0: - version "5.90.3" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.90.3.tgz#37b8f74d3ded061ba789bb22b31e82eed75bd9ac" - integrity sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA== +webpack@5.77.0: + version "5.77.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.77.0.tgz#dea3ad16d7ea6b84aa55fa42f4eac9f30e7eb9b4" + integrity sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.5" - "@webassemblyjs/ast" "^1.11.5" - "@webassemblyjs/wasm-edit" "^1.11.5" - "@webassemblyjs/wasm-parser" "^1.11.5" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" acorn "^8.7.1" - acorn-import-assertions "^1.9.0" - browserslist "^4.21.10" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.15.0" - es-module-lexer "^1.2.1" + enhanced-resolve "^5.10.0" + es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" @@ -11528,9 +11404,9 @@ webpack@^5.77.0: loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.2.0" + schema-utils "^3.1.0" tapable "^2.1.1" - terser-webpack-plugin "^5.3.10" + terser-webpack-plugin "^5.1.3" watchpack "^2.4.0" webpack-sources "^3.2.3" From 2a2d09be7d5d3d1c46d0e244ae1ce333ad1f08e3 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 18 Mar 2024 15:05:51 +0200 Subject: [PATCH 366/397] UI: Fix build --- ui-ngx/package.json | 6 +- ui-ngx/yarn.lock | 330 +++++++++----------------------------------- 2 files changed, 68 insertions(+), 268 deletions(-) diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 0ba5880ed3..a74a1f2953 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -62,7 +62,7 @@ "html2canvas": "^1.4.1", "jquery": "^3.6.3", "jquery.terminal": "^2.35.3", - "js-beautify": "^1.14.7", + "js-beautify": "1.14.7", "json-schema-defaults": "^0.4.0", "jstree": "^3.3.15", "jstree-bootstrap-theme": "^1.0.1", @@ -172,6 +172,8 @@ "@types/react": "17.0.37", "ace-builds": "1.4.13", "@date-io/core": "1.3.7", - "rc-virtual-list": "3.4.13" + "rc-virtual-list": "3.4.13", + "read-package-json": "6.0.0", + "cacache": "17.0.4" } } diff --git a/ui-ngx/yarn.lock b/ui-ngx/yarn.lock index ef25146805..ca5c179ad5 100644 --- a/ui-ngx/yarn.lock +++ b/ui-ngx/yarn.lock @@ -1582,11 +1582,6 @@ dependencies: tslib "^2.2.0" -"@gar/promisify@^1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" - integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== - "@geoman-io/leaflet-geoman-free@^2.13.0": version "2.16.0" resolved "https://registry.yarnpkg.com/@geoman-io/leaflet-geoman-free/-/leaflet-geoman-free-2.16.0.tgz#c8a92fcc2cdd5770ebf43f8ef9f03cc8ef842359" @@ -1625,18 +1620,6 @@ dependencies: tslib "^2.3.0" -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -2617,14 +2600,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@npmcli/fs@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.2.tgz#a9e2541a4a2fec2e69c29b35e6060973da79b865" - integrity sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ== - dependencies: - "@gar/promisify" "^1.1.3" - semver "^7.3.5" - "@npmcli/fs@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e" @@ -2654,14 +2629,6 @@ npm-bundled "^3.0.0" npm-normalize-package-bin "^3.0.0" -"@npmcli/move-file@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-2.0.1.tgz#26f6bdc379d87f75e55739bab89db525b06100e4" - integrity sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ== - dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - "@npmcli/node-gyp@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz#101b2d0490ef1aa20ed460e4c0813f0db560545a" @@ -2685,16 +2652,6 @@ read-package-json-fast "^3.0.0" which "^3.0.0" -"@one-ini/wasm@0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@one-ini/wasm/-/wasm-0.1.1.tgz#6013659736c9dbfccc96e8a9c2b3de317df39323" - integrity sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw== - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - "@schematics/angular@15.2.10": version "15.2.10" resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-15.2.10.tgz#fa6c05f37ba82422abd6b3f13a2fc78ec7a4eb3d" @@ -3641,11 +3598,6 @@ abbrev@^1.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -abbrev@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" - integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== - accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -3810,11 +3762,6 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" - integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== - ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -3834,11 +3781,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - ansidec@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/ansidec/-/ansidec-0.3.4.tgz#e12d267d6b1f122d2da5b98fe0de1f98d14ac62b" @@ -4292,7 +4234,7 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacache@17.0.4: +cacache@17.0.4, cacache@^16.1.0, cacache@^17.0.0: version "17.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.0.4.tgz#5023ed892ba8843e3b7361c26d0ada37e146290c" integrity sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA== @@ -4311,48 +4253,6 @@ cacache@17.0.4: tar "^6.1.11" unique-filename "^3.0.0" -cacache@^16.1.0: - version "16.1.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.3.tgz#a02b9f34ecfaf9a78c9f4bc16fceb94d5d67a38e" - integrity sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ== - dependencies: - "@npmcli/fs" "^2.1.0" - "@npmcli/move-file" "^2.0.0" - chownr "^2.0.0" - fs-minipass "^2.1.0" - glob "^8.0.1" - infer-owner "^1.0.4" - lru-cache "^7.7.1" - minipass "^3.1.6" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - mkdirp "^1.0.4" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^9.0.0" - tar "^6.1.11" - unique-filename "^2.0.0" - -cacache@^17.0.0: - version "17.1.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.1.4.tgz#b3ff381580b47e85c6e64f801101508e26604b35" - integrity sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A== - dependencies: - "@npmcli/fs" "^3.1.0" - fs-minipass "^3.0.0" - glob "^10.2.2" - lru-cache "^7.7.1" - minipass "^7.0.3" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - p-map "^4.0.0" - ssri "^10.0.0" - tar "^6.1.11" - unique-filename "^3.0.0" - call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" @@ -4620,12 +4520,7 @@ commander@7: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - -commander@^2.20.0: +commander@^2.19.0, commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -4856,7 +4751,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -5534,11 +5429,6 @@ domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -5555,15 +5445,15 @@ echarts@^5.5.0: tslib "2.3.0" zrender "5.5.0" -editorconfig@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-1.0.4.tgz#040c9a8e9a6c5288388b87c2db07028aa89f53a3" - integrity sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q== +editorconfig@^0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" + integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== dependencies: - "@one-ini/wasm" "0.1.1" - commander "^10.0.0" - minimatch "9.0.1" - semver "^7.5.3" + commander "^2.19.0" + lru-cache "^4.1.5" + semver "^5.6.0" + sigmund "^1.0.1" ee-first@1.1.1: version "1.1.1" @@ -5585,11 +5475,6 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - emoji-toolkit@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/emoji-toolkit/-/emoji-toolkit-7.0.1.tgz#4ea2a78fe4b40c7cdbe7ef5725c7011299932f09" @@ -6385,14 +6270,6 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" -foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -6450,7 +6327,7 @@ fs-extra@^9.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-minipass@^2.0.0, fs-minipass@^2.1.0: +fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== @@ -6590,7 +6467,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@8.1.0, glob@^8.0.1: +glob@8.1.0, glob@^8.0.1, glob@^8.0.3: version "8.1.0" resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== @@ -6601,17 +6478,6 @@ glob@8.1.0, glob@^8.0.1: minimatch "^5.0.1" once "^1.3.0" -glob@^10.2.2, glob@^10.3.3: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== - dependencies: - foreground-child "^3.1.0" - jackspeak "^2.3.5" - minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" - glob@^7.0.3, glob@^7.0.6, glob@^7.1.3, glob@^7.1.4, glob@^7.1.7: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -7030,11 +6896,6 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -infer-owner@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -7461,15 +7322,6 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jackspeak@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - jasmine-core@^3.6.0: version "3.99.1" resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.99.1.tgz#5bfa4b2d76618868bfac4c8ff08bb26fffa4120d" @@ -7536,21 +7388,15 @@ jquery@>=1.9.1, jquery@^3.5.0, jquery@^3.6.3, jquery@^3.7.1: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== -js-beautify@^1.14.7: - version "1.15.1" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.15.1.tgz#4695afb508c324e1084ee0b952a102023fc65b64" - integrity sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA== +js-beautify@1.14.7: + version "1.14.7" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.14.7.tgz#9206296de33f86dc106d3e50a35b7cf8729703b2" + integrity sha512-5SOX1KXPFKx+5f6ZrPsIPEY7NwKeQz47n3jm2i+XeHx9MoRsfQenlOP13FQhWvg8JRS0+XLO6XYUQ2GX+q+T9A== dependencies: config-chain "^1.1.13" - editorconfig "^1.0.4" - glob "^10.3.3" - js-cookie "^3.0.5" - nopt "^7.2.0" - -js-cookie@^3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc" - integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw== + editorconfig "^0.15.3" + glob "^8.0.3" + nopt "^6.0.0" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" @@ -8091,6 +7937,14 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -8110,11 +7964,6 @@ lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== -"lru-cache@^9.1.1 || ^10.0.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" - integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== - magic-string@0.29.0: version "0.29.0" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.29.0.tgz#f034f79f8c43dba4ae1730ffb5e8c4e084b16cf3" @@ -8310,13 +8159,6 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.1.tgz#8a555f541cf976c622daf078bb28f29fb927c253" - integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w== - dependencies: - brace-expansion "^2.0.1" - minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -8331,7 +8173,7 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.0, minimatch@^9.0.1: +minimatch@^9.0.0: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== @@ -8423,7 +8265,7 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.3: +minipass@^7.0.3: version "7.0.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== @@ -8443,7 +8285,7 @@ mkdirp@^0.5.5: dependencies: minimist "^1.2.6" -mkdirp@^1.0.3, mkdirp@^1.0.4: +mkdirp@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -8672,13 +8514,6 @@ nopt@^6.0.0: dependencies: abbrev "^1.0.0" -nopt@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7" - integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA== - dependencies: - abbrev "^2.0.0" - normalize-package-data@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-5.0.0.tgz#abcb8d7e724c40d88462b84982f7cbf6859b4588" @@ -9149,14 +8984,6 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== - dependencies: - lru-cache "^9.1.1 || ^10.0.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -9408,6 +9235,11 @@ prr@~1.0.1: resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -9668,12 +9500,12 @@ read-package-json-fast@^3.0.0: json-parse-even-better-errors "^3.0.0" npm-normalize-package-bin "^3.0.0" -read-package-json@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-6.0.4.tgz#90318824ec456c287437ea79595f4c2854708836" - integrity sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw== +read-package-json@6.0.0, read-package-json@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-6.0.0.tgz#6a741841ad72a40e77a82b9c3c8c10e865bbc519" + integrity sha512-b/9jxWJ8EwogJPpv99ma+QwtqB7FSl3+V6UXS7Aaay8/5VwMY50oIFooY1UKXMWpfNCM6T/PoGqa5GD1g9xf9w== dependencies: - glob "^10.2.2" + glob "^8.0.1" json-parse-even-better-errors "^3.0.0" normalize-package-data "^5.0.0" npm-normalize-package-bin "^3.0.0" @@ -10251,16 +10083,16 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +sigmund@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + integrity sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g== + signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - sigstore@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-1.9.0.tgz#1e7ad8933aa99b75c6898ddd0eeebc3eb0d59875" @@ -10528,7 +10360,7 @@ streamroller@^3.1.5: debug "^4.3.4" fs-extra "^8.1.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -10537,15 +10369,6 @@ streamroller@^3.1.5: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - string.prototype.trim@^1.2.8, string.prototype.trim@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" @@ -10588,13 +10411,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -10602,12 +10418,12 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - ansi-regex "^6.0.1" + ansi-regex "^5.0.1" strip-bom@^3.0.0: version "3.0.0" @@ -11083,13 +10899,6 @@ unicode-property-aliases-ecmascript@^2.0.0: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== -unique-filename@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-2.0.1.tgz#e785f8675a9a7589e0ac77e0b5c34d2eaeac6da2" - integrity sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A== - dependencies: - unique-slug "^3.0.0" - unique-filename@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" @@ -11097,13 +10906,6 @@ unique-filename@^3.0.0: dependencies: unique-slug "^4.0.0" -unique-slug@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-3.0.0.tgz#6d347cf57c8a7a7a6044aabd0e2d74e4d76dc7c9" - integrity sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w== - dependencies: - imurmurhash "^0.1.4" - unique-slug@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3" @@ -11502,15 +11304,6 @@ wordwrapjs@^4.0.0: reduce-flatten "^2.0.0" typical "^5.2.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -11520,14 +11313,14 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" wrappy@1: version "1.0.2" @@ -11567,6 +11360,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" From 32f0c3c67c3d319cbe609d79860970ba8f22034f Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 19 Mar 2024 13:30:20 +0200 Subject: [PATCH 367/397] Don't create Rule Engine consumer when no partitions to avoid NPE when deleting queue --- .../queue/DefaultTbRuleEngineConsumerService.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java index 13de09bb2d..f0b93a175a 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java @@ -114,9 +114,17 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< if (partitionService.isManagedByCurrentService(queueKey.getTenantId())) { var consumer = getConsumer(queueKey).orElseGet(() -> { Queue config = queueService.findQueueByTenantIdAndName(queueKey.getTenantId(), queueKey.getQueueName()); + if (config == null) { + if (!partitions.isEmpty()) { + log.error("[{}] Queue configuration is missing", queueKey, new RuntimeException("stacktrace")); + } + return null; + } return createConsumer(queueKey, config); }); - consumer.update(partitions); + if (consumer != null) { + consumer.update(partitions); + } } }); consumers.keySet().stream() From 2ee4d10621b25b67a5e051d8835f0d346902a271 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 19 Mar 2024 16:24:06 +0200 Subject: [PATCH 368/397] Update TBEL version to 1.2.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6fa82db97e..a9b7efc653 100755 --- a/pom.xml +++ b/pom.xml @@ -81,7 +81,7 @@ 3.8.1 3.21.9 1.42.1 - 1.1.5 + 1.2.0 1.18.26 1.2.4 1.2.5 From 7dd81ffb937d669a0cc7a337470d07d43ea90edb Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 19 Mar 2024 16:28:52 +0200 Subject: [PATCH 369/397] Ignore invalid lwm2m tests --- .../lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java | 5 ++++- .../transport/lwm2m/server/client/LwM2mClientTest.java | 2 ++ .../lwm2m/server/store/util/LwM2MClientSerDesTest.java | 5 ++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java index 3e923bb644..9f49f3b138 100644 --- a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapServiceTest.java @@ -17,6 +17,8 @@ package org.thingsboard.server.transport.lwm2m.bootstrap; import org.eclipse.californium.core.network.CoapEndpoint; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; +import org.junit.Ignore; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -48,7 +50,7 @@ public class LwM2MTransportBootstrapServiceTest { @Mock private TbLwM2MDtlsBootstrapCertificateVerifier certificateVerifier; - + @Disabled // fixme: nick @Test public void getLHServer_creates_ConnectionIdGenerator_when_connection_id_length_not_null(){ final Integer CONNECTION_ID_LENGTH = 6; @@ -66,6 +68,7 @@ public class LwM2MTransportBootstrapServiceTest { .isEqualTo(CONNECTION_ID_LENGTH); } + @Disabled // fixme: nick @Test public void getLHServer_creates_no_ConnectionIdGenerator_when_connection_id_length_is_null(){ when(serverConfig.getDtlsCidLength()).thenReturn(null); diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientTest.java index ee154794ce..5bc334756d 100644 --- a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientTest.java +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientTest.java @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.client; import org.eclipse.leshan.core.link.Link; import org.eclipse.leshan.server.registration.Registration; +import org.junit.Ignore; import org.junit.Test; import org.junit.jupiter.api.Assertions; @@ -24,6 +25,7 @@ import java.net.InetSocketAddress; public class LwM2mClientTest { + @Ignore @Test public void setRegistration() { LwM2mClient client = new LwM2mClient("nodeId", "testEndpoint"); diff --git a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java index 3e279efe40..43187f2a36 100644 --- a/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java +++ b/common/transport/lwm2m/src/test/java/org/thingsboard/server/transport/lwm2m/server/store/util/LwM2MClientSerDesTest.java @@ -15,15 +15,14 @@ */ package org.thingsboard.server.transport.lwm2m.server.store.util; -import org.eclipse.leshan.core.link.Link; import org.eclipse.leshan.core.node.LwM2mMultipleResource; import org.eclipse.leshan.core.node.LwM2mResource; import org.eclipse.leshan.core.node.LwM2mSingleResource; import org.eclipse.leshan.core.request.WriteRequest; import org.eclipse.leshan.server.registration.Registration; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; -import org.mockito.Mockito; import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.device.data.PowerMode; import org.thingsboard.server.common.data.id.CustomerId; @@ -42,7 +41,6 @@ import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; -import java.net.InetSocketAddress; import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; @@ -58,6 +56,7 @@ import static org.mockito.Mockito.when; public class LwM2MClientSerDesTest { + @Ignore @Test public void serializeDeserialize() throws Exception { LwM2mClient client = new LwM2mClient("nodeId", "testEndpoint"); From c4b8068e96793fba7ba9132780a3bef00af3e387 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 19 Mar 2024 16:56:11 +0200 Subject: [PATCH 370/397] Use AttributeScope instead of DataConstants in DefaultDeviceStateServiceTest --- .../service/state/DefaultDeviceStateServiceTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java b/application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java index e590e4d8c3..f80c8c4c82 100644 --- a/application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/state/DefaultDeviceStateServiceTest.java @@ -205,7 +205,7 @@ public class DefaultDeviceStateServiceTest { // THEN then(telemetrySubscriptionService).should().saveAttrAndNotify( - eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), eq(LAST_CONNECT_TIME), eq(lastConnectTime), any() + eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(AttributeScope.SERVER_SCOPE), eq(LAST_CONNECT_TIME), eq(lastConnectTime), any() ); var msgCaptor = ArgumentCaptor.forClass(TbMsg.class); @@ -289,7 +289,7 @@ public class DefaultDeviceStateServiceTest { // THEN then(telemetrySubscriptionService).should().saveAttrAndNotify( - eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), + eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(AttributeScope.SERVER_SCOPE), eq(LAST_DISCONNECT_TIME), eq(lastDisconnectTime), any() ); @@ -410,11 +410,11 @@ public class DefaultDeviceStateServiceTest { // THEN then(telemetrySubscriptionService).should().saveAttrAndNotify( - eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), + eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(AttributeScope.SERVER_SCOPE), eq(INACTIVITY_ALARM_TIME), eq(lastInactivityTime), any() ); then(telemetrySubscriptionService).should().saveAttrAndNotify( - eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), + eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(AttributeScope.SERVER_SCOPE), eq(ACTIVITY_STATE), eq(false), any() ); @@ -450,11 +450,11 @@ public class DefaultDeviceStateServiceTest { // THEN then(telemetrySubscriptionService).should().saveAttrAndNotify( - eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), + eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(AttributeScope.SERVER_SCOPE), eq(INACTIVITY_ALARM_TIME), anyLong(), any() ); then(telemetrySubscriptionService).should().saveAttrAndNotify( - eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(DataConstants.SERVER_SCOPE), + eq(TenantId.SYS_TENANT_ID), eq(deviceId), eq(AttributeScope.SERVER_SCOPE), eq(ACTIVITY_STATE), eq(false), any() ); From 28ef94bb1c261a01196d45a8fc4f2dc2dde7ad95 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Thu, 21 Mar 2024 11:07:33 +0200 Subject: [PATCH 371/397] Remove api limits from tenantProfileEdgeMsg --- .../tenant/TenantMsgConstructorV1.java | 19 +++++++++++++++++++ .../tenant/TenantMsgConstructorV2.java | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java index 6b72e49df6..c6160c05bd 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java @@ -21,6 +21,7 @@ import org.springframework.stereotype.Component; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.TenantProfile; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.gen.edge.v1.EdgeVersion; import org.thingsboard.server.gen.edge.v1.TenantProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.TenantUpdateMsg; @@ -78,6 +79,23 @@ public class TenantMsgConstructorV1 implements TenantMsgConstructor { @Override public TenantProfileUpdateMsg constructTenantProfileUpdateMsg(UpdateMsgType msgType, TenantProfile tenantProfile, EdgeVersion edgeVersion) { + tenantProfile = JacksonUtil.clone(tenantProfile); + // clear all config + DefaultTenantProfileConfiguration configuration = + (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration(); + configuration.setRpcTtlDays(0); + configuration.setMaxJSExecutions(0); + configuration.setMaxREExecutions(0); + configuration.setMaxDPStorageDays(0); + configuration.setMaxTbelExecutions(0); + configuration.setQueueStatsTtlDays(0); + configuration.setMaxTransportMessages(0); + configuration.setDefaultStorageTtlDays(0); + configuration.setMaxTransportDataPoints(0); + configuration.setRuleEngineExceptionsTtlDays(0); + configuration.setMaxRuleNodeExecutionsPerMessage(0); + tenantProfile.getProfileData().setConfiguration(configuration); + ByteString profileData = EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_6_2) ? ByteString.empty() : ByteString.copyFrom(dataDecodingEncodingService.encode(tenantProfile.getProfileData())); TenantProfileUpdateMsg.Builder builder = TenantProfileUpdateMsg.newBuilder() @@ -93,4 +111,5 @@ public class TenantMsgConstructorV1 implements TenantMsgConstructor { } return builder.build(); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV2.java index c6ccb439ea..7ed36d9aef 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV2.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV2.java @@ -19,6 +19,7 @@ import org.springframework.stereotype.Component; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.TenantProfile; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.gen.edge.v1.EdgeVersion; import org.thingsboard.server.gen.edge.v1.TenantProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.TenantUpdateMsg; @@ -36,6 +37,24 @@ public class TenantMsgConstructorV2 implements TenantMsgConstructor { @Override public TenantProfileUpdateMsg constructTenantProfileUpdateMsg(UpdateMsgType msgType, TenantProfile tenantProfile, EdgeVersion edgeVersion) { + tenantProfile = JacksonUtil.clone(tenantProfile); + // clear all config + DefaultTenantProfileConfiguration configuration = + (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration(); + configuration.setRpcTtlDays(0); + configuration.setMaxJSExecutions(0); + configuration.setMaxREExecutions(0); + configuration.setMaxDPStorageDays(0); + configuration.setMaxTbelExecutions(0); + configuration.setQueueStatsTtlDays(0); + configuration.setMaxTransportMessages(0); + configuration.setDefaultStorageTtlDays(0); + configuration.setMaxTransportDataPoints(0); + configuration.setRuleEngineExceptionsTtlDays(0); + configuration.setMaxRuleNodeExecutionsPerMessage(0); + tenantProfile.getProfileData().setConfiguration(configuration); + return TenantProfileUpdateMsg.newBuilder().setMsgType(msgType).setEntity(JacksonUtil.toString(tenantProfile)).build(); } + } From 420cebcd030a85b03304596fd23b530de086da70 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Thu, 21 Mar 2024 11:55:02 +0200 Subject: [PATCH 372/397] Use getDefaultProfileConfiguration instead of casting --- .../edge/rpc/constructor/tenant/TenantMsgConstructorV1.java | 3 +-- .../edge/rpc/constructor/tenant/TenantMsgConstructorV2.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java index c6160c05bd..baa4a77b6b 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java @@ -81,8 +81,7 @@ public class TenantMsgConstructorV1 implements TenantMsgConstructor { public TenantProfileUpdateMsg constructTenantProfileUpdateMsg(UpdateMsgType msgType, TenantProfile tenantProfile, EdgeVersion edgeVersion) { tenantProfile = JacksonUtil.clone(tenantProfile); // clear all config - DefaultTenantProfileConfiguration configuration = - (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration(); + var configuration = tenantProfile.getDefaultProfileConfiguration(); configuration.setRpcTtlDays(0); configuration.setMaxJSExecutions(0); configuration.setMaxREExecutions(0); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV2.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV2.java index 7ed36d9aef..274e18e7f3 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV2.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV2.java @@ -39,8 +39,7 @@ public class TenantMsgConstructorV2 implements TenantMsgConstructor { public TenantProfileUpdateMsg constructTenantProfileUpdateMsg(UpdateMsgType msgType, TenantProfile tenantProfile, EdgeVersion edgeVersion) { tenantProfile = JacksonUtil.clone(tenantProfile); // clear all config - DefaultTenantProfileConfiguration configuration = - (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration(); + var configuration = tenantProfile.getDefaultProfileConfiguration(); configuration.setRpcTtlDays(0); configuration.setMaxJSExecutions(0); configuration.setMaxREExecutions(0); From b46728de705534a6d01bf1a172c73ca1bbe1398c Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Thu, 21 Mar 2024 12:22:48 +0200 Subject: [PATCH 373/397] Fix V1 for tenantPrfoile to correctly set profile data --- .../edge/rpc/constructor/tenant/TenantMsgConstructorV1.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java index baa4a77b6b..f75bbd219e 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/tenant/TenantMsgConstructorV1.java @@ -21,7 +21,6 @@ import org.springframework.stereotype.Component; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.TenantProfile; -import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.gen.edge.v1.EdgeVersion; import org.thingsboard.server.gen.edge.v1.TenantProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.TenantUpdateMsg; @@ -81,6 +80,7 @@ public class TenantMsgConstructorV1 implements TenantMsgConstructor { public TenantProfileUpdateMsg constructTenantProfileUpdateMsg(UpdateMsgType msgType, TenantProfile tenantProfile, EdgeVersion edgeVersion) { tenantProfile = JacksonUtil.clone(tenantProfile); // clear all config + var tenantProfileData = tenantProfile.getProfileData(); var configuration = tenantProfile.getDefaultProfileConfiguration(); configuration.setRpcTtlDays(0); configuration.setMaxJSExecutions(0); @@ -93,7 +93,8 @@ public class TenantMsgConstructorV1 implements TenantMsgConstructor { configuration.setMaxTransportDataPoints(0); configuration.setRuleEngineExceptionsTtlDays(0); configuration.setMaxRuleNodeExecutionsPerMessage(0); - tenantProfile.getProfileData().setConfiguration(configuration); + tenantProfileData.setConfiguration(configuration); + tenantProfile.setProfileData(tenantProfileData); ByteString profileData = EdgeVersionUtils.isEdgeVersionOlderThan(edgeVersion, EdgeVersion.V_3_6_2) ? ByteString.empty() : ByteString.copyFrom(dataDecodingEncodingService.encode(tenantProfile.getProfileData())); From 9973cc609a75d2700dd75c13b6281a88ccaab97f Mon Sep 17 00:00:00 2001 From: rusikv Date: Thu, 21 Mar 2024 18:39:05 +0200 Subject: [PATCH 374/397] UI: upgrade oauth checkboxes to chip buttons --- .../pages/admin/oauth2-settings.component.html | 16 +++++++++------- .../pages/admin/oauth2-settings.component.ts | 13 +++++++++++-- .../src/assets/locale/locale.constant-en_US.json | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html index 0414a5dff7..acaf58895e 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html @@ -29,13 +29,15 @@
    -
    - - {{ 'admin.oauth2.enable' | translate }} - - - {{ 'admin.oauth2.edge-enable' | translate }} - +
    +
    + + {{ 'admin.oauth2.enable' | translate }} + + + {{ 'admin.oauth2.edge-enable' | translate }} + +
    diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts index 9cbf6368e6..f6f8340550 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts @@ -205,13 +205,22 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha this.oauth2SettingsForm = this.fb.group({ oauth2ParamsInfos: this.fb.array([]), enabled: [false], - edgeEnabled: [false] + edgeEnabled: [{value: false, disabled: true}] }); + + this.subscriptions.push(this.oauth2SettingsForm.get('enabled').valueChanges.subscribe(enabled => { + if (enabled) { + this.oauth2SettingsForm.get('edgeEnabled').enable(); + } else { + this.oauth2SettingsForm.get('edgeEnabled').patchValue(false); + this.oauth2SettingsForm.get('edgeEnabled').disable(); + } + })) } private initOAuth2Settings(oauth2Info: OAuth2Info): void { if (oauth2Info) { - this.oauth2SettingsForm.patchValue({enabled: oauth2Info.enabled, edgeEnabled: oauth2Info.edgeEnabled}, {emitEvent: false}); + this.oauth2SettingsForm.patchValue({enabled: oauth2Info.enabled, edgeEnabled: oauth2Info.edgeEnabled}); oauth2Info.oauth2ParamsInfos.forEach((oauth2ParamsInfo) => { this.oauth2ParamsInfos.push(this.buildOAuth2ParamsInfoForm(oauth2ParamsInfo)); }); 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 457b6ecf66..a317b9b89d 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -283,7 +283,7 @@ "domain-schema-https": "HTTPS", "domain-schema-mixed": "HTTP+HTTPS", "enable": "Enable OAuth2 settings", - "edge-enable": "Propagate OAuth2 settings to Edge", + "edge-enable": "Propagate to Edge", "domains": "Domains", "mobile-apps": "Mobile applications", "no-mobile-apps": "No applications configured", From d9669c9391146b402821f6fc872418ecbe0f3686 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Fri, 22 Mar 2024 14:05:25 +0200 Subject: [PATCH 375/397] Fix TbSubscriptionUtils order for matching KeyValueType and DataType --- .../subscription/TbSubscriptionUtils.java | 28 ++++++++++++---- .../server/utils/TbSubscriptionUtilsTest.java | 33 +++++++++++++++++++ .../server/common/data/EntityType.java | 3 +- .../server/common/data/kv/DataType.java | 15 ++++++++- 4 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 application/src/test/java/org/thingsboard/server/utils/TbSubscriptionUtilsTest.java diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscriptionUtils.java b/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscriptionUtils.java index 24d54109be..4c3a1b2351 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscriptionUtils.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/TbSubscriptionUtils.java @@ -36,7 +36,6 @@ import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto; -import org.thingsboard.server.gen.transport.TransportProtos.KeyValueType; import org.thingsboard.server.gen.transport.TransportProtos.SubscriptionMgrMsgProto; import org.thingsboard.server.gen.transport.TransportProtos.TbAlarmDeleteProto; import org.thingsboard.server.gen.transport.TransportProtos.TbAlarmUpdateProto; @@ -54,6 +53,7 @@ import org.thingsboard.server.service.ws.notification.sub.NotificationsSubscript import org.thingsboard.server.service.ws.telemetry.sub.AlarmSubscriptionUpdate; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -62,6 +62,14 @@ import java.util.UUID; public class TbSubscriptionUtils { + private static final DataType[] dataTypeByProtoNumber; + + static { + int arraySize = Arrays.stream(DataType.values()).mapToInt(DataType::getProtoNumber).max().orElse(0); + dataTypeByProtoNumber = new DataType[arraySize + 1]; + Arrays.stream(DataType.values()).forEach(dataType -> dataTypeByProtoNumber[dataType.getProtoNumber()] = dataType); + } + public static ToCoreMsg toSubEventProto(String serviceId, TbEntitySubEvent event) { SubscriptionMgrMsgProto.Builder msgBuilder = SubscriptionMgrMsgProto.newBuilder(); var builder = TbEntitySubEventProto.newBuilder() @@ -235,7 +243,7 @@ public class TbSubscriptionUtils { private static TsKvProto.Builder toKeyValueProto(long ts, KvEntry attr) { KeyValueProto.Builder dataBuilder = KeyValueProto.newBuilder(); dataBuilder.setKey(attr.getKey()); - dataBuilder.setType(KeyValueType.forNumber(attr.getDataType().ordinal())); + dataBuilder.setType(toProto(attr.getDataType())); switch (attr.getDataType()) { case BOOLEAN: attr.getBooleanValue().ifPresent(dataBuilder::setBoolV); @@ -259,7 +267,7 @@ public class TbSubscriptionUtils { private static TransportProtos.TsValueProto toTsValueProto(long ts, KvEntry attr) { TransportProtos.TsValueProto.Builder dataBuilder = TransportProtos.TsValueProto.newBuilder(); dataBuilder.setTs(ts); - dataBuilder.setType(KeyValueType.forNumber(attr.getDataType().ordinal())); + dataBuilder.setType(toProto(attr.getDataType())); switch (attr.getDataType()) { case BOOLEAN: attr.getBooleanValue().ifPresent(dataBuilder::setBoolV); @@ -299,8 +307,7 @@ public class TbSubscriptionUtils { private static KvEntry getKvEntry(KeyValueProto proto) { KvEntry entry = null; - DataType type = DataType.values()[proto.getType().getNumber()]; - switch (type) { + switch (fromProto(proto.getType())) { case BOOLEAN: entry = new BooleanDataEntry(proto.getKey(), proto.getBoolV()); break; @@ -328,8 +335,7 @@ public class TbSubscriptionUtils { private static KvEntry getKvEntry(String key, TransportProtos.TsValueProto proto) { KvEntry entry = null; - DataType type = DataType.values()[proto.getType().getNumber()]; - switch (type) { + switch (fromProto(proto.getType())) { case BOOLEAN: entry = new BooleanDataEntry(key, proto.getBoolV()); break; @@ -448,4 +454,12 @@ public class TbSubscriptionUtils { return ToCoreNotificationMsg.newBuilder().setToLocalSubscriptionServiceMsg(result).build(); } + public static TransportProtos.KeyValueType toProto(DataType dataType) { + return TransportProtos.KeyValueType.forNumber(dataType.getProtoNumber()); + } + + public static DataType fromProto(TransportProtos.KeyValueType keyValueType) { + return dataTypeByProtoNumber[keyValueType.getNumber()]; + } + } diff --git a/application/src/test/java/org/thingsboard/server/utils/TbSubscriptionUtilsTest.java b/application/src/test/java/org/thingsboard/server/utils/TbSubscriptionUtilsTest.java new file mode 100644 index 0000000000..a3f1f0f0fa --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/utils/TbSubscriptionUtilsTest.java @@ -0,0 +1,33 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.utils; + +import org.junit.Test; +import org.thingsboard.server.common.data.kv.DataType; +import org.thingsboard.server.service.subscription.TbSubscriptionUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TbSubscriptionUtilsTest { + + @Test + public void protoDataTypeSerialization() { + for (DataType dataType : DataType.values()) { + assertThat(TbSubscriptionUtils.fromProto(TbSubscriptionUtils.toProto(dataType))).as(dataType.name()).isEqualTo(dataType); + } + } + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java index fb4fe1011e..3580a86bcc 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java @@ -26,6 +26,7 @@ import java.util.stream.Collectors; * @author Andrew Shvayka */ public enum EntityType { + TENANT(1), CUSTOMER(2), USER(3), @@ -63,7 +64,7 @@ public enum EntityType { @Getter private final int protoNumber; // Corresponds to EntityTypeProto - private EntityType(int protoNumber) { + EntityType(int protoNumber) { this.protoNumber = protoNumber; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/kv/DataType.java b/common/data/src/main/java/org/thingsboard/server/common/data/kv/DataType.java index a9d857ca9e..a8ad9b42c1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/kv/DataType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/kv/DataType.java @@ -15,8 +15,21 @@ */ package org.thingsboard.server.common.data.kv; +import lombok.Getter; + public enum DataType { - STRING, LONG, BOOLEAN, DOUBLE, JSON; + BOOLEAN(0), + LONG(1), + DOUBLE(2), + STRING(3), + JSON(4); + + @Getter + private final int protoNumber; // Corresponds to KeyValueType + + DataType(int protoNumber) { + this.protoNumber = protoNumber; + } } From 8bd2c1c0c4c15fca30347db82f3bbd86de4d0232 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Fri, 22 Mar 2024 17:53:40 +0200 Subject: [PATCH 376/397] UI: Fixed mask for older version chrome --- .../widget/lib/gateway/device-gateway-command.component.scss | 2 ++ .../widget/lib/indicator/battery-level-widget.component.scss | 5 +++++ .../device/device-check-connectivity-dialog.component.scss | 2 ++ .../home/pages/edge/edge-instructions-dialog.component.scss | 2 ++ ui-ngx/src/form.scss | 4 ++++ 5 files changed, 15 insertions(+) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.scss index 3425065ca2..3f66b67943 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/device-gateway-command.component.scss @@ -63,7 +63,9 @@ height: 18px; background: #305680; mask-image: url(/assets/copy-code-icon.svg); + -webkit-mask-image: url(/assets/copy-code-icon.svg); mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; } } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.scss index 444417fb09..a85d7d694b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/battery-level-widget.component.scss @@ -73,8 +73,11 @@ position: absolute; inset: 0; mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; mask-size: cover; + -webkit-mask-size: cover; mask-position: center; + -webkit-mask-position: center; } .tb-battery-level-container { position: absolute; @@ -95,6 +98,7 @@ &.vertical { .tb-battery-level-shape { mask-image: url(/assets/widget/battery-level/battery-shape-vertical.svg); + -webkit-mask-image: url(/assets/widget/battery-level/battery-shape-vertical.svg); } .tb-battery-level-container { flex-direction: column-reverse; @@ -122,6 +126,7 @@ &.horizontal { .tb-battery-level-shape { mask-image: url(/assets/widget/battery-level/battery-shape-horizontal.svg); + -webkit-mask-image: url(/assets/widget/battery-level/battery-shape-horizontal.svg); } .tb-battery-level-container { inset: 6.25% 8.85% 6.25% 3.54%; diff --git a/ui-ngx/src/app/modules/home/pages/device/device-check-connectivity-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/device/device-check-connectivity-dialog.component.scss index f7ed839541..ef5a1c0ff4 100644 --- a/ui-ngx/src/app/modules/home/pages/device/device-check-connectivity-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/pages/device/device-check-connectivity-dialog.component.scss @@ -155,7 +155,9 @@ height: 18px; background: #305680; mask-image: url(/assets/copy-code-icon.svg); + -webkit-mask-image: url(/assets/copy-code-icon.svg); mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; } } } diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-instructions-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/edge/edge-instructions-dialog.component.scss index 4ff80e2c21..b28b28863e 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edge-instructions-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-instructions-dialog.component.scss @@ -92,7 +92,9 @@ height: 18px; background: $tb-primary-color; mask-image: url(/assets/copy-code-icon.svg); + -webkit-mask-image: url(/assets/copy-code-icon.svg); mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; } } &.multiline { diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index e2390c795d..f4d3cdb398 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -588,9 +588,13 @@ bottom: 0; background: $tb-primary-color; mask-image: url(/assets/home/no_data_folder_bg.svg); + -webkit-mask-image: url(/assets/home/no_data_folder_bg.svg); mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; mask-size: contain; + -webkit-mask-size: contain; mask-position: center; + -webkit-mask-position: center; } } From 03c30791009d71e0a5752577eac47c5b1e5d4ff7 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 20 Mar 2024 12:50:50 +0200 Subject: [PATCH 377/397] UI: Fixed some time new time windows intervals not apply --- ui-ngx/.eslintrc.json | 3 +- .../components/time/timeinterval.component.ts | 28 +++++++++++-------- .../time/timewindow-panel.component.ts | 1 - 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/ui-ngx/.eslintrc.json b/ui-ngx/.eslintrc.json index cf9f0e8238..764733e4d7 100644 --- a/ui-ngx/.eslintrc.json +++ b/ui-ngx/.eslintrc.json @@ -51,7 +51,8 @@ "import/order": "off", "@typescript-eslint/member-ordering": "off", "no-underscore-dangle": "off", - "@typescript-eslint/naming-convention": "off" + "@typescript-eslint/naming-convention": "off", + "jsdoc/newline-after-description": 0 } }, { diff --git a/ui-ngx/src/app/shared/components/time/timeinterval.component.ts b/ui-ngx/src/app/shared/components/time/timeinterval.component.ts index 8775b0a6ed..ad6b489ade 100644 --- a/ui-ngx/src/app/shared/components/time/timeinterval.component.ts +++ b/ui-ngx/src/app/shared/components/time/timeinterval.component.ts @@ -21,6 +21,7 @@ import { coerceNumberProperty } from '@angular/cdk/coercion'; import { SubscriptSizing } from '@angular/material/form-field'; import { coerceBoolean } from '@shared/decorators/coercion'; import { Interval, IntervalMath, TimeInterval } from '@shared/models/time/time.models'; +import { isDefined } from '@core/utils'; @Component({ selector: 'tb-timeinterval', @@ -90,14 +91,14 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { secs = 0; interval: Interval = 0; - modelValue: Interval; + intervals: Array; advanced = false; - rendered = false; - intervals: Array; + private modelValue: Interval; + private rendered = false; - private propagateChange = (_: any) => {}; + private propagateChange: (value: any) => void = () => {}; constructor(private timeService: TimeService) { } @@ -108,6 +109,9 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { registerOnChange(fn: any): void { this.propagateChange = fn; + if (isDefined(this.modelValue) && this.rendered) { + this.propagateChange(this.modelValue); + } } registerOnTouched(fn: any): void { @@ -132,7 +136,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { } } - setInterval(interval: Interval) { + private setInterval(interval: Interval) { if (!this.advanced) { this.interval = interval; } @@ -143,7 +147,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { this.secs = intervalSeconds % 60; } - boundInterval(updateToPreferred = false) { + private boundInterval(updateToPreferred = false) { const min = this.timeService.boundMinInterval(this.minValue); const max = this.timeService.boundMaxInterval(this.maxValue); this.intervals = this.timeService.getIntervals(this.minValue, this.maxValue, this.useCalendarIntervals); @@ -165,7 +169,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { } } - updateView(updateToPreferred = false) { + private updateView(updateToPreferred = false) { if (!this.rendered) { return; } @@ -187,7 +191,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { this.boundInterval(updateToPreferred); } - calculateIntervalMs(): number { + private calculateIntervalMs(): number { return (this.days * 86400 + this.hours * 3600 + this.mins * 60 + @@ -232,7 +236,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { } } - onSecsChange() { + private onSecsChange() { if (typeof this.secs === 'undefined') { return; } @@ -252,7 +256,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { this.updateView(); } - onMinsChange() { + private onMinsChange() { if (typeof this.mins === 'undefined') { return; } @@ -272,7 +276,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { this.updateView(); } - onHoursChange() { + private onHoursChange() { if (typeof this.hours === 'undefined') { return; } @@ -292,7 +296,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { this.updateView(); } - onDaysChange() { + private onDaysChange() { if (typeof this.days === 'undefined') { return; } diff --git a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts index 0c0dd4294c..857d2c7cb7 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts +++ b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.ts @@ -20,7 +20,6 @@ import { AggregationType, DAY, HistoryWindowType, - QuickTimeInterval, quickTimeIntervalPeriod, RealtimeWindowType, Timewindow, From 7a43ae996606f34bf4ffdb95cca9306c183aa3fe Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Fri, 22 Mar 2024 18:29:11 +0200 Subject: [PATCH 378/397] UI: Fixed power button widget for firefox --- .../lib/rpc/power-button-widget.models.ts | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts index 51a427d23b..656ba75fa1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/power-button-widget.models.ts @@ -444,7 +444,7 @@ class InnerShadowCircle { add.x('-50%').y('-50%').width('200%').height('200%'); let effect: Effect = add.componentTransfer(components => { components.funcA({ type: 'table', tableValues: '1 0' }); - }).in(add.$fill); + }); effect = effect.gaussianBlur(this.blur, this.blur).attr({stdDeviation: this.blur}); this.blurEffect = effect; effect = effect.offset(this.dx, this.dy); @@ -454,7 +454,7 @@ class InnerShadowCircle { effect = effect.composite(this.offsetEffect, 'in'); effect.composite(add.$sourceAlpha, 'in'); add.merge(m => { - m.mergeNode(add.$fill); + m.mergeNode(); m.mergeNode(); }); }); @@ -538,14 +538,14 @@ class DefaultPowerButtonShape extends PowerButtonShape { this.pressedTimeline.finish(); const pressedScale = 0.75; powerButtonAnimation(this.centerGroup).transform({scale: pressedScale}); - powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale}); + powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale, origin: {x: cx, y: cy}}); this.pressedShadow.animate(6, 0.6); } protected onPressEnd() { this.pressedTimeline.finish(); powerButtonAnimation(this.centerGroup).transform({scale: 1}); - powerButtonAnimation(this.onLabelShape).transform({scale: 1}); + powerButtonAnimation(this.onLabelShape).transform({scale: 1, origin: {x: cx, y: cy}}); this.pressedShadow.animateRestore(); } @@ -602,14 +602,14 @@ class SimplifiedPowerButtonShape extends PowerButtonShape { this.pressedTimeline.finish(); const pressedScale = 0.75; powerButtonAnimation(this.centerGroup).transform({scale: pressedScale}); - powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale}); + powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale, origin: {x: cx, y: cy}}); this.pressedShadow.animate(6, 0.6); } protected onPressEnd() { this.pressedTimeline.finish(); powerButtonAnimation(this.centerGroup).transform({scale: 1}); - powerButtonAnimation(this.onLabelShape).transform({scale: 1}); + powerButtonAnimation(this.onLabelShape).transform({scale: 1, origin: {x: cx, y: cy}}); this.pressedShadow.animateRestore(); } } @@ -674,7 +674,7 @@ class OutlinedPowerButtonShape extends PowerButtonShape { const pressedScale = 0.75; powerButtonAnimation(this.centerGroup).transform({scale: pressedScale}); powerButtonAnimation(this.onCenterGroup).transform({scale: 0.98}); - powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale / 0.98}); + powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale / 0.98, origin: {x: cx, y: cy}}); this.pressedShadow.animate(6, 0.6); } @@ -682,7 +682,7 @@ class OutlinedPowerButtonShape extends PowerButtonShape { this.pressedTimeline.finish(); powerButtonAnimation(this.centerGroup).transform({scale: 1}); powerButtonAnimation(this.onCenterGroup).transform({scale: 1}); - powerButtonAnimation(this.onLabelShape).transform({scale: 1}); + powerButtonAnimation(this.onLabelShape).transform({scale: 1, origin: {x: cx, y: cy}}); this.pressedShadow.animateRestore(); } } @@ -774,14 +774,14 @@ class DefaultVolumePowerButtonShape extends PowerButtonShape { this.innerShadow.show(); const pressedScale = 0.75; powerButtonAnimation(this.centerGroup).transform({scale: pressedScale}); - powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale}); + powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale, origin: {x: cx, y: cy}}); this.innerShadow.animate(6, 0.6); } protected onPressEnd() { this.pressedTimeline.finish(); powerButtonAnimation(this.centerGroup).transform({scale: 1}); - powerButtonAnimation(this.onLabelShape).transform({scale: 1}); + powerButtonAnimation(this.onLabelShape).transform({scale: 1, origin: {x: cx, y: cy}}); this.innerShadow.animateRestore().after(() => { if (this.disabled) { this.innerShadow.hide(); @@ -849,14 +849,14 @@ class SimplifiedVolumePowerButtonShape extends PowerButtonShape { this.backgroundShape.removeClass('tb-shadow'); } powerButtonAnimation(this.centerGroup).transform({scale: pressedScale}); - powerButtonAnimation(this.onCenterGroup).transform({scale: pressedScale}); + powerButtonAnimation(this.onCenterGroup).transform({scale: pressedScale, origin: {x: cx, y: cy}}); this.pressedShadow.animate(8, 0.4); } protected onPressEnd() { this.pressedTimeline.finish(); powerButtonAnimation(this.centerGroup).transform({scale: 1}); - powerButtonAnimation(this.onCenterGroup).transform({scale: 1}); + powerButtonAnimation(this.onCenterGroup).transform({scale: 1, origin: {x: cx, y: cy}}); this.pressedShadow.animateRestore().after(() => { if (!this.value) { this.backgroundShape.addClass('tb-shadow'); @@ -938,7 +938,7 @@ class OutlinedVolumePowerButtonShape extends PowerButtonShape { const pressedScale = 0.75; powerButtonAnimation(this.centerGroup).transform({scale: pressedScale}); powerButtonAnimation(this.onCenterGroup).transform({scale: 0.98}); - powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale / 0.98}); + powerButtonAnimation(this.onLabelShape).transform({scale: pressedScale / 0.98, origin: {x: cx, y: cy}}); this.pressedShadow.animate(6, 0.6); } @@ -946,7 +946,7 @@ class OutlinedVolumePowerButtonShape extends PowerButtonShape { this.pressedTimeline.finish(); powerButtonAnimation(this.centerGroup).transform({scale: 1}); powerButtonAnimation(this.onCenterGroup).transform({scale: 1}); - powerButtonAnimation(this.onLabelShape).transform({scale: 1}); + powerButtonAnimation(this.onLabelShape).transform({scale: 1, origin: {x: cx, y: cy}}); this.pressedShadow.animateRestore(); } From 8423eac5979183a94ef34dafdacb105f294401b8 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 21 Mar 2024 10:14:48 +0200 Subject: [PATCH 379/397] UI: Improved save value in propagateChange --- .../app/shared/components/time/timeinterval.component.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/shared/components/time/timeinterval.component.ts b/ui-ngx/src/app/shared/components/time/timeinterval.component.ts index ad6b489ade..8ed6fb2034 100644 --- a/ui-ngx/src/app/shared/components/time/timeinterval.component.ts +++ b/ui-ngx/src/app/shared/components/time/timeinterval.component.ts @@ -97,8 +97,11 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { private modelValue: Interval; private rendered = false; + private propagateChangeValue: any; - private propagateChange: (value: any) => void = () => {}; + private propagateChange = (value: any) => { + this.propagateChangeValue = value; + }; constructor(private timeService: TimeService) { } @@ -109,8 +112,8 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { registerOnChange(fn: any): void { this.propagateChange = fn; - if (isDefined(this.modelValue) && this.rendered) { - this.propagateChange(this.modelValue); + if (isDefined(this.propagateChangeValue)) { + this.propagateChange(this.propagateChangeValue); } } From 8910b4b1dfd04319c820ba6fb8d6a7d2ff5bf177 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 22 Mar 2024 20:02:51 +0200 Subject: [PATCH 380/397] Swagger docs Open API 3.1 --- application/pom.xml | 2 +- .../server/config/SwaggerConfiguration.java | 402 +++++++++++++----- .../thingsboard/server/config/WebConfig.java | 5 + .../server/controller/AdminController.java | 6 +- .../controller/AlarmCommentController.java | 7 +- .../server/controller/AlarmController.java | 29 +- .../server/controller/AssetController.java | 39 +- .../controller/AssetProfileController.java | 24 +- .../server/controller/AuditLogController.java | 12 +- .../controller/DashboardController.java | 61 +-- .../server/controller/DeviceController.java | 9 +- .../controller/DeviceProfileController.java | 27 +- .../server/controller/EdgeController.java | 53 +-- .../controller/EdgeEventController.java | 2 +- .../controller/EntityRelationController.java | 25 +- .../controller/EntityViewController.java | 18 +- .../server/controller/EventController.java | 7 +- .../server/controller/Lwm2mController.java | 3 +- .../controller/OtaPackageController.java | 19 +- .../controller/RuleChainController.java | 8 +- .../controller/TbResourceController.java | 21 +- .../controller/TelemetryController.java | 51 +-- .../src/main/resources/thingsboard.yml | 2 + .../common/data/alarm/AlarmComment.java | 11 +- .../server/common/data/id/EntityId.java | 4 +- .../server/common/data/id/UserId.java | 3 +- .../transport/http/DeviceApiController.java | 42 +- pom.xml | 8 +- 28 files changed, 476 insertions(+), 424 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index adc3f1e801..902b541566 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -262,7 +262,7 @@ opensmpp-core - org.springdoc + org.thingsboard springdoc-openapi-starter-webmvc-ui diff --git a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java index 21255bf1f7..963205c08b 100644 --- a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java @@ -15,12 +15,17 @@ */ package org.thingsboard.server.config; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.core.converter.AnnotatedType; +import io.swagger.v3.core.converter.ModelConverter; import io.swagger.v3.core.converter.ModelConverters; +import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; @@ -33,29 +38,42 @@ import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; -import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.oas.models.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springdoc.core.customizers.OpenApiCustomizer; +import org.springdoc.core.customizers.OperationCustomizer; +import org.springdoc.core.customizers.RouterOperationCustomizer; +import org.springdoc.core.discoverer.SpringDocParameterNameDiscoverer; import org.springdoc.core.models.GroupedOpenApi; +import org.springdoc.core.properties.SpringDocConfigProperties; import org.springdoc.core.properties.SwaggerUiConfigProperties; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; +import org.springframework.core.MethodParameter; import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RequestParam; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; +import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.exception.ThingsboardCredentialsExpiredResponse; import org.thingsboard.server.exception.ThingsboardErrorResponse; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.rest.LoginRequest; import org.thingsboard.server.service.security.auth.rest.LoginResponse; -import java.util.Collections; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @@ -67,8 +85,14 @@ public class SwaggerConfiguration { public static final String LOGIN_ENDPOINT = "/api/auth/login"; + private static final ApiResponses loginResponses = loginResponses(); + private static final ApiResponses defaultErrorResponses = defaultErrorResponses(false); + private static final ApiResponses defaultPostErrorResponses = defaultErrorResponses(true); + @Value("${swagger.api_path:/api/**}") private String apiPath; + @Value("${swagger.security_path_regex}") + private String securityPathRegex; @Value("${swagger.non_security_path_regex}") private String nonSecurityPathRegex; @Value("${swagger.title}") @@ -90,6 +114,7 @@ public class SwaggerConfiguration { @Value("${app.version:unknown}") private String appVersion; + @Bean public OpenAPI thingsboardApi() { Contact contact = new Contact() @@ -115,93 +140,24 @@ public class SwaggerConfiguration { SecurityScheme securityScheme = new SecurityScheme() .type(SecurityScheme.Type.HTTP) - .scheme("bearer") - .bearerFormat("JWT") - .in(SecurityScheme.In.HEADER) - .description("Enter Username / Password"); + .description("Enter Username / Password") + .scheme("loginPassword") + .bearerFormat("/api/auth/login|X-Authorization"); var openApi = new OpenAPI() - .addServersItem(new Server().url("/").description("Default Server URL")) .components(new Components().addSecuritySchemes("HTTP login form", securityScheme)) .info(info); + addDefaultSchemas(openApi); addLoginOperation(openApi); return openApi; } - public void addLoginOperation(OpenAPI openAPI) { - openAPI.getComponents() - .addSchemas("LoginRequest", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginRequest.class)).schema) - .addSchemas("LoginResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginResponse.class)).schema) - .addSchemas("ThingsboardErrorResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardErrorResponse.class)).schema) - .addSchemas("ThingsboardCredentialsExpiredResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardCredentialsExpiredResponse.class)).schema); - - var operation = new Operation(); - operation.summary("Login method to get user JWT token data"); - operation.description("Login method used to authenticate user and get JWT token data.\n\nValue of the response **token** " + - "field can be used as **X-Authorization** header value:\n\n`X-Authorization: Bearer $JWT_TOKEN_VALUE`."); - var requestBody = new RequestBody().content(new Content().addMediaType(APPLICATION_JSON_VALUE, - new MediaType().schema(new Schema().$ref("#/components/schemas/LoginRequest")))); - operation.requestBody(requestBody); - operation.responses(getResponses()); - operation.addTagsItem("login-endpoint"); - var pathItem = new PathItem().post(operation); - openAPI.path(LOGIN_ENDPOINT, pathItem); - } - - private ApiResponses getResponses() { - ApiResponses apiResponses = new ApiResponses(); - - apiResponses.addApiResponse("200", new ApiResponse().description("OK") - .content(new Content().addMediaType(APPLICATION_JSON_VALUE, - new MediaType().schema(new Schema().$ref("#/components/schemas/LoginResponse"))))); - - ApiResponse unauthorizedResponse = new ApiResponse().description("Unauthorized"); - Content content = new Content(); - MediaType mediaType = new MediaType().schema(new Schema().$ref("#/components/schemas/ThingsboardErrorResponse")); - - Map examples = Map.of( - "bad-credentials", errorExample("Bad credentials", - ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), - "token-expired", errorExample("JWT token expired", - ThingsboardErrorResponse.of("Token has expired", ThingsboardErrorCode.JWT_TOKEN_EXPIRED, HttpStatus.UNAUTHORIZED)), - "account-disabled", errorExample("Disabled account", - ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), - "account-locked", errorExample("Locked account", - ThingsboardErrorResponse.of("User account is locked due to security policy", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), - "authentication-failed", errorExample("General authentication error", - ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)) - ); - - mediaType.setExamples(examples); - content.addMediaType(APPLICATION_JSON_VALUE, mediaType); - unauthorizedResponse.setContent(content); - apiResponses.addApiResponse("401", unauthorizedResponse); - - ApiResponse expiredCredentialsResponse = new ApiResponse().description("Unauthorized (**Expired credentials**)"); - Content expiredContent = new Content(); - MediaType expiredMediaType = new MediaType().schema(new Schema().$ref("#/components/schemas/ThingsboardCredentialsExpiredResponse")); - expiredMediaType.addExamples("credentials-expired", errorExample("Expired credentials", - ThingsboardCredentialsExpiredResponse.of("User password expired!", StringUtils.randomAlphanumeric(30)))); - expiredContent.addMediaType(APPLICATION_JSON_VALUE, expiredMediaType); - expiredCredentialsResponse.setContent(expiredContent); - apiResponses.addApiResponse("401 ", expiredCredentialsResponse); - - return apiResponses; - } - - private Example errorExample(String summary, ThingsboardErrorResponse example) { - return new Example() - .summary(summary) - .value(example); - } - @Bean - public GroupedOpenApi groupedApi() { - return GroupedOpenApi.builder() - .group("thingsboard") - .pathsToMatch(apiPath) - .addOpenApiCustomizer(customOpenApiCustomizer()) - .build(); + @Primary + public SpringDocConfigProperties springDocConfig(SpringDocConfigProperties springDocProperties) { + springDocProperties.getApiDocs().setVersion(SpringDocConfigProperties.ApiDocs.OpenApiVersion.OPENAPI_3_1); + springDocProperties.setRemoveBrokenReferenceDefinitions(false); + return springDocProperties; } @Bean @@ -232,35 +188,166 @@ public class SwaggerConfiguration { return uiProperties; } - public OpenApiCustomizer customOpenApiCustomizer() { - var loginForm = new SecurityRequirement().addList("HTTP login form"); - return openAPI -> openAPI.getPaths().entrySet().stream().peek(entry -> { - securityCustomization(loginForm, entry); - if (!entry.getKey().equals(LOGIN_ENDPOINT)) { - defaultErrorResponsesCustomization(entry.getValue()); + private void addLoginOperation(OpenAPI openAPI) { + var operation = new Operation(); + operation.summary("Login method to get user JWT token data"); + operation.description(""" + Login method used to authenticate user and get JWT token data. + + Value of the response **token** field can be used as **X-Authorization** header value: + + `X-Authorization: Bearer $JWT_TOKEN_VALUE`."""); + var requestBody = new RequestBody().description("Login request") + .content(new Content().addMediaType(APPLICATION_JSON_VALUE, + new MediaType().schema(new Schema().$ref("#/components/schemas/LoginRequest")))); + operation.requestBody(requestBody); + + operation.responses(loginResponses); + + operation.addTagsItem("login-endpoint"); + var pathItem = new PathItem().post(operation); + openAPI.path(LOGIN_ENDPOINT, pathItem); + } + + @Bean + public GroupedOpenApi groupedApi(SpringDocParameterNameDiscoverer localSpringDocParameterNameDiscoverer) { + return GroupedOpenApi.builder() + .group("thingsboard") + .pathsToMatch(apiPath) + .addRouterOperationCustomizer(routerOperationCustomizer(localSpringDocParameterNameDiscoverer)) + .addOperationCustomizer(operationCustomizer()) + .addOpenApiCustomizer(customOpenApiCustomizer()) + .build(); + } + + @Bean + @Lazy(false) + ModelConverter mapAwareConverter() { + return (type, context, chain) -> { + if (chain.hasNext()) { + Schema schema = chain.next().resolve(type, context, chain); + JavaType javaType = Json.mapper().constructType(type.getType()); + if (javaType != null) { + Class cls = javaType.getRawClass(); + if (Map.class.isAssignableFrom(cls)) { + if (schema != null && schema.getProperties() != null) { + schema.getProperties().remove("empty"); + if (schema.getProperties().isEmpty()) { + schema.setProperties(null); + } + } + } + } + return schema; + } else { + return null; } - }).map(this::tagsCustomization).forEach(openAPI::addTagsItem); + }; } - private Tag tagsCustomization(Map.Entry entry) { - var operations = entry.getValue().readOperationsMap().values(); - var tagItem = operations.stream().findAny().get().getTags().get(0); - return tagFromTagItem(tagItem); + private void addDefaultSchemas(OpenAPI openAPI) { + var jsonNodeSchema = ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(JsonNode.class)).schema; + jsonNodeSchema.setType("any"); + //noinspection unchecked + jsonNodeSchema.setExamples(List.of(JacksonUtil.newObjectNode())); + jsonNodeSchema.setDescription("A value representing the any type (object or primitive)"); + openAPI.getComponents() + .addSchemas("JsonNode", jsonNodeSchema) + .addSchemas("LoginRequest", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginRequest.class)).schema) + .addSchemas("LoginResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(LoginResponse.class)).schema) + .addSchemas("ThingsboardErrorResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardErrorResponse.class)).schema) + .addSchemas("ThingsboardCredentialsExpiredResponse", ModelConverters.getInstance().readAllAsResolvedSchema(new AnnotatedType().type(ThingsboardCredentialsExpiredResponse.class)).schema); } - private void defaultErrorResponsesCustomization(PathItem pathItem) { - pathItem.readOperationsMap().forEach(((httpMethod, operation) -> { - operation.setResponses(getResponses(operation.getResponses(), httpMethod.equals(PathItem.HttpMethod.POST))); - })); + private RouterOperationCustomizer routerOperationCustomizer(SpringDocParameterNameDiscoverer localSpringDocParameterNameDiscoverer) { + return (routerOperation, handlerMethod) -> { + String[] pNames = localSpringDocParameterNameDiscoverer.getParameterNames(handlerMethod.getMethod()); + String[] reflectionParametersNames = Arrays.stream(handlerMethod.getMethod().getParameters()).map(java.lang.reflect.Parameter::getName).toArray(String[]::new); + if (pNames == null || Arrays.stream(pNames).anyMatch(Objects::isNull)) + pNames = reflectionParametersNames; + MethodParameter[] parameters = handlerMethod.getMethodParameters(); + List requestParams = new ArrayList<>(); + for (var i = 0; i < parameters.length; i++) { + var methodParameter = parameters[i]; + RequestParam requestParam = methodParameter.getParameterAnnotation(RequestParam.class); + if (requestParam != null) { + String pName = StringUtils.isNotBlank(requestParam.value()) ? requestParam.value() : + pNames[i]; + if (StringUtils.isNotBlank(pName)) { + requestParams.add(pName); + } + } + } + if (!requestParams.isEmpty()) { + var path = routerOperation.getPath() + "{?" + String.join(",", requestParams) + "}"; + routerOperation.setPath(path); + } + return routerOperation; + }; } - private void securityCustomization(SecurityRequirement loginForm, Map.Entry entry) { - if (!(entry.getKey().matches(nonSecurityPathRegex) || entry.getKey().equals(LOGIN_ENDPOINT))) { - entry.getValue() - .readOperationsMap() - .values() - .forEach(operation -> operation.addSecurityItem(loginForm)); + private OperationCustomizer operationCustomizer() { + return (operation, handlerMethod) -> { + if (StringUtils.isBlank(operation.getSummary())) { + operation.setSummary(operation.getOperationId()); + } + return operation; + }; + } + + private OpenApiCustomizer customOpenApiCustomizer() { + var loginForm = new SecurityRequirement().addList("HTTP login form", Arrays.asList( + Authority.SYS_ADMIN.name(), + Authority.TENANT_ADMIN.name(), + Authority.CUSTOMER_USER.name() + )); + return openAPI -> { + var paths = openAPI.getPaths(); + paths.entrySet().stream().peek(entry -> { + securityCustomization(loginForm, entry); + if (!entry.getKey().equals(LOGIN_ENDPOINT)) { + defaultErrorResponsesCustomization(entry.getValue()); + } + }).map(this::tagsCustomization).filter(Objects::nonNull).distinct().sorted(Comparator.comparing(Tag::getName)).forEach(openAPI::addTagsItem); + + var pathItemsByTags = new TreeMap>(); + paths.forEach((k, v) -> { + var tagItem = tagItemFromPathItem(v); + if (tagItem != null) { + var pathItemMap = pathItemsByTags.computeIfAbsent(tagItem, k1 -> new TreeMap<>()); + pathItemMap.put(k, v); + } + }); + var sortedPaths = new Paths(); + pathItemsByTags.forEach((tagItem, pathItemMap) -> { + pathItemMap.forEach(sortedPaths::addPathItem); + }); + sortedPaths.setExtensions(paths.getExtensions()); + openAPI.setPaths(sortedPaths); + var sortedSchemas = new TreeMap<>(openAPI.getComponents().getSchemas()); + openAPI.getComponents().setSchemas(new LinkedHashMap<>(sortedSchemas)); + }; + } + + + private Tag tagsCustomization(Map.Entry entry) { + var tagItem = tagItemFromPathItem(entry.getValue()); + if (tagItem != null) { + return tagFromTagItem(tagItem); } + return null; + } + + private String tagItemFromPathItem(PathItem item) { + var operations = item.readOperationsMap().values(); + var operation = operations.stream().findAny(); + if (operation.isPresent()) { + var tags = operation.get().getTags(); + if (tags != null && !tags.isEmpty()) { + return tags.get(0); + } + } + return null; } private Tag tagFromTagItem(String tagItem) { @@ -276,32 +363,113 @@ public class SwaggerConfiguration { return new Tag().name(tagItem).description(sb.toString().trim()); } - private ApiResponses getResponses(ApiResponses apiResponses, boolean isPost) { - if (apiResponses == null) { - apiResponses = new ApiResponses(); + private void defaultErrorResponsesCustomization(PathItem pathItem) { + pathItem.readOperationsMap().forEach(((httpMethod, operation) -> { + var errorResponses = httpMethod.equals(PathItem.HttpMethod.POST) ? defaultPostErrorResponses : defaultErrorResponses; + var responses = operation.getResponses(); + if (responses == null) { + responses = errorResponses; + } else { + ApiResponses updated = responses; + errorResponses.forEach((key, apiResponse) -> { + if (!updated.containsKey(key)) { + updated.put(key, apiResponse); + } + }); + } + operation.setResponses(responses); + })); + } + + private void securityCustomization(SecurityRequirement loginForm, Map.Entry entry) { + var path = entry.getKey(); + if (path.matches(securityPathRegex) && !path.matches(nonSecurityPathRegex) && !path.equals(LOGIN_ENDPOINT)) { + entry.getValue() + .readOperationsMap() + .values() + .forEach(operation -> operation.addSecurityItem(loginForm)); } + } - apiResponses.addApiResponse("400", new ApiResponse().description("Bad Request") - .content(getErrorContent(ThingsboardErrorResponse.of(isPost ? "Invalid request body" : "Invalid UUID string: 123", ThingsboardErrorCode.BAD_REQUEST_PARAMS, HttpStatus.BAD_REQUEST)))); + private static ApiResponses loginResponses() { + ApiResponses apiResponses = new ApiResponses(); + apiResponses.addApiResponse("200", new ApiResponse().description("OK") + .content(new Content().addMediaType(APPLICATION_JSON_VALUE, + new MediaType().schema(new Schema().$ref("#/components/schemas/LoginResponse"))))); + apiResponses.putAll(loginErrorResponses()); + return apiResponses; + } + + private static ApiResponses defaultErrorResponses(boolean isPost) { + ApiResponses apiResponses = new ApiResponses(); + apiResponses.addApiResponse("400", errorResponse("400", "Bad Request", + ThingsboardErrorResponse.of(isPost ? "Invalid request body" : "Invalid UUID string: 123", ThingsboardErrorCode.BAD_REQUEST_PARAMS, HttpStatus.BAD_REQUEST))); - apiResponses.addApiResponse("401", new ApiResponse().description("Unauthorized") - .content(getErrorContent(ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)))); + apiResponses.addApiResponse("401", errorResponse("401", "Unauthorized", + ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED))); - apiResponses.addApiResponse("403", new ApiResponse().description("Forbidden") - .content(getErrorContent(ThingsboardErrorResponse.of("You don't have permission to perform this operation!", ThingsboardErrorCode.PERMISSION_DENIED, HttpStatus.FORBIDDEN)))); + apiResponses.addApiResponse("403", errorResponse("403", "Forbidden", + ThingsboardErrorResponse.of("You don't have permission to perform this operation!", ThingsboardErrorCode.PERMISSION_DENIED, HttpStatus.FORBIDDEN))); - apiResponses.addApiResponse("404", new ApiResponse().description("Not Found") - .content(getErrorContent(ThingsboardErrorResponse.of("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND)))); + apiResponses.addApiResponse("404", errorResponse("404", "Not Found", + ThingsboardErrorResponse.of("Requested item wasn't found!", ThingsboardErrorCode.ITEM_NOT_FOUND, HttpStatus.NOT_FOUND))); - apiResponses.addApiResponse("429", new ApiResponse().description("Too Many Requests") - .content(getErrorContent(ThingsboardErrorResponse.of("Too many requests for current tenant!", ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS)))); + apiResponses.addApiResponse("429", errorResponse("429", "Too Many Requests", + ThingsboardErrorResponse.of("Too many requests for current tenant!", ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS))); return apiResponses; } - private Content getErrorContent(ThingsboardErrorResponse errorResponse) { - return new Content().addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, - new MediaType().schema(new Schema().example(errorResponse))); + private static ApiResponses loginErrorResponses() { + ApiResponses apiResponses = new ApiResponses(); + + apiResponses.addApiResponse("401", errorResponse("Unauthorized", + Map.of( + "bad-credentials", errorExample("Bad credentials", + ThingsboardErrorResponse.of("Invalid username or password", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), + "token-expired", errorExample("JWT token expired", + ThingsboardErrorResponse.of("Token has expired", ThingsboardErrorCode.JWT_TOKEN_EXPIRED, HttpStatus.UNAUTHORIZED)), + "account-disabled", errorExample("Disabled account", + ThingsboardErrorResponse.of("User account is not active", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), + "account-locked", errorExample("Locked account", + ThingsboardErrorResponse.of("User account is locked due to security policy", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)), + "authentication-failed", errorExample("General authentication error", + ThingsboardErrorResponse.of("Authentication failed", ThingsboardErrorCode.AUTHENTICATION, HttpStatus.UNAUTHORIZED)) + ) + )); + var credentialsExpiredSchema = new Schema(); + credentialsExpiredSchema.$ref("#/components/schemas/ThingsboardCredentialsExpiredResponse"); + apiResponses.addApiResponse("401 ", errorResponse("Unauthorized (**Expired credentials**)", + Map.of( + "credentials-expired", errorExample("Expired credentials", + ThingsboardCredentialsExpiredResponse.of("User password expired!", StringUtils.randomAlphanumeric(30))) + ), + credentialsExpiredSchema + )); + return apiResponses; + } + + private static ApiResponse errorResponse(String code, String description, ThingsboardErrorResponse example) { + return errorResponse(description, Map.of("error-code-" + code, errorExample(description, example))); + } + + private static ApiResponse errorResponse(String description, Map examples) { + var schema = new Schema(); + schema.$ref("#/components/schemas/ThingsboardErrorResponse"); + return errorResponse(description, examples, schema); + } + + private static ApiResponse errorResponse(String description, Map examples, Schema errorResponseSchema) { + MediaType mediaType = new MediaType().schema(errorResponseSchema); + mediaType.setExamples(examples); + Content content = new Content().addMediaType(org.springframework.http.MediaType.APPLICATION_JSON_VALUE, mediaType); + return new ApiResponse().description(description).content(content); + } + + private static Example errorExample(String summary, ThingsboardErrorResponse example) { + return new Example() + .summary(summary) + .value(example); } } diff --git a/application/src/main/java/org/thingsboard/server/config/WebConfig.java b/application/src/main/java/org/thingsboard/server/config/WebConfig.java index 81597952c0..70afc8b99c 100644 --- a/application/src/main/java/org/thingsboard/server/config/WebConfig.java +++ b/application/src/main/java/org/thingsboard/server/config/WebConfig.java @@ -37,4 +37,9 @@ public class WebConfig { response.sendRedirect(baseUrl + "/swagger-ui/"); } + @RequestMapping("/swagger-ui/") + public String redirectSwaggerIndex() throws IOException { + return "forward:/swagger-ui/index.html"; + } + } diff --git a/application/src/main/java/org/thingsboard/server/controller/AdminController.java b/application/src/main/java/org/thingsboard/server/controller/AdminController.java index 739f386dc9..818a2a15a6 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AdminController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AdminController.java @@ -184,8 +184,7 @@ public class AdminController extends BaseController { } @ApiOperation(value = "Get the JWT Settings object (getJwtSettings)", - notes = "Get the JWT Settings object that contains JWT token policy, etc. " + SYSTEM_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Get the JWT Settings object that contains JWT token policy, etc. " + SYSTEM_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/jwtSettings", method = RequestMethod.GET) @ResponseBody @@ -195,8 +194,7 @@ public class AdminController extends BaseController { } @ApiOperation(value = "Update JWT Settings (saveJwtSettings)", - notes = "Updates the JWT Settings object that contains JWT token policy, etc. The tokenSigningKey field is a Base64 encoded string." + SYSTEM_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Updates the JWT Settings object that contains JWT token policy, etc. The tokenSigningKey field is a Base64 encoded string." + SYSTEM_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/jwtSettings", method = RequestMethod.POST) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index cca82f5ee5..65f5c1c543 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -69,8 +69,7 @@ public class AlarmCommentController extends BaseController { "Referencing non-existing Alarm Comment Id will cause 'Not Found' error. " + "\n\n To create new Alarm comment entity it is enough to specify 'comment' json element with 'text' node, for example: {\"comment\": { \"text\": \"my comment\"}}. " + "\n\n If comment type is not specified the default value 'OTHER' will be saved. If 'alarmId' or 'userId' specified in body it will be ignored." + - TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH - , responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.POST) @ResponseBody @@ -84,7 +83,7 @@ public class AlarmCommentController extends BaseController { } @ApiOperation(value = "Delete Alarm comment (deleteAlarmComment)", - notes = "Deletes the Alarm comment. Referencing non-existing Alarm comment Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Deletes the Alarm comment. Referencing non-existing Alarm comment Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment/{commentId}", method = RequestMethod.DELETE) @ResponseBody @@ -100,7 +99,7 @@ public class AlarmCommentController extends BaseController { @ApiOperation(value = "Get Alarm comments (getAlarmComments)", notes = "Returns a page of alarm comments for specified alarm. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index d983f08ec2..ba22663467 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -104,7 +104,7 @@ public class AlarmController extends BaseController { "filled in the AlarmInfo object field: 'originatorName' or will returns as null."; @ApiOperation(value = "Get Alarm (getAlarmById)", - notes = "Fetch the Alarm object based on the provided Alarm Id. " + ALARM_SECURITY_CHECK, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Fetch the Alarm object based on the provided Alarm Id. " + ALARM_SECURITY_CHECK) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.GET) @ResponseBody @@ -117,7 +117,7 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Get Alarm Info (getAlarmInfoById)", notes = "Fetch the Alarm Info object based on the provided Alarm Id. " + - ALARM_SECURITY_CHECK + ALARM_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + ALARM_SECURITY_CHECK + ALARM_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/info/{alarmId}", method = RequestMethod.GET) @ResponseBody @@ -139,7 +139,7 @@ public class AlarmController extends BaseController { "If the user clears the alarm (see 'Clear Alarm(clearAlarm)'), than new alarm with the same type and same device may be created. " + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Alarm entity. " + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH - , responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + ) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm", method = RequestMethod.POST) @ResponseBody @@ -155,7 +155,7 @@ public class AlarmController extends BaseController { } @ApiOperation(value = "Delete Alarm (deleteAlarm)", - notes = "Deletes the Alarm. Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Deletes the Alarm. Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}", method = RequestMethod.DELETE) @ResponseBody @@ -169,7 +169,7 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Acknowledge Alarm (ackAlarm)", notes = "Acknowledge the Alarm. " + "Once acknowledged, the 'ack_ts' field will be set to current timestamp and special rule chain event 'ALARM_ACK' will be generated. " + - "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/ack", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) @@ -184,7 +184,7 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Clear Alarm (clearAlarm)", notes = "Clear the Alarm. " + "Once cleared, the 'clear_ts' field will be set to current timestamp and special rule chain event 'ALARM_CLEAR' will be generated. " + - "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/clear", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) @@ -200,7 +200,7 @@ public class AlarmController extends BaseController { notes = "Assign the Alarm. " + "Once assigned, the 'assign_ts' field will be set to current timestamp and special rule chain event 'ALARM_ASSIGNED' " + "(or ALARM_REASSIGNED in case of assigning already assigned alarm) will be generated. " + - "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/assign/{assigneeId}", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) @@ -221,7 +221,7 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Unassign Alarm (unassignAlarm)", notes = "Unassign the Alarm. " + "Once unassigned, the 'assign_ts' field will be set to current timestamp and special rule chain event 'ALARM_UNASSIGNED' will be generated. " + - "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Referencing non-existing Alarm Id will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{alarmId}/assign", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) @@ -236,7 +236,7 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Get Alarms (getAlarms)", notes = "Returns a page of alarms for the selected entity. Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) @ResponseBody @@ -292,7 +292,7 @@ public class AlarmController extends BaseController { "If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " + "If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " + "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarms", method = RequestMethod.GET) @ResponseBody @@ -341,7 +341,7 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Get Alarms (getAlarmsV2)", notes = "Returns a page of alarms for the selected entity. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/v2/alarm/{entityType}/{entityId}", method = RequestMethod.GET) @ResponseBody @@ -407,7 +407,7 @@ public class AlarmController extends BaseController { notes = "Returns a page of alarms that belongs to the current user owner. " + "If the user has the authority of 'Tenant Administrator', the server returns alarms that belongs to the tenant of current user. " + "If the user has the authority of 'Customer User', the server returns alarms that belongs to the customer of current user. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/v2/alarms", method = RequestMethod.GET) @ResponseBody @@ -468,7 +468,7 @@ public class AlarmController extends BaseController { @ApiOperation(value = "Get Highest Alarm Severity (getHighestAlarmSeverity)", notes = "Search the alarms by originator ('entityType' and entityId') and optional 'status' or 'searchStatus' filters and returns the highest AlarmSeverity(CRITICAL, MAJOR, MINOR, WARNING or INDETERMINATE). " + "Specifying both parameters 'searchStatus' and 'status' at the same time will cause an error." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH - , responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + ) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/highestSeverity/{entityType}/{entityId}", method = RequestMethod.GET) @ResponseBody @@ -499,8 +499,7 @@ public class AlarmController extends BaseController { } @ApiOperation(value = "Get Alarm Types (getAlarmTypes)", - notes = "Returns a set of unique alarm types based on alarms that are either owned by the tenant or assigned to the customer which user is performing the request.", - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Returns a set of unique alarm types based on alarms that are either owned by the tenant or assigned to the customer which user is performing the request.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm/types", method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 6f51202c36..751f3fd812 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -103,7 +103,7 @@ public class AssetController extends BaseController { notes = "Fetch the Asset object based on the provided Asset Id. " + "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " + "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH - , responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + ) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset/{assetId}", method = RequestMethod.GET) @ResponseBody @@ -118,7 +118,7 @@ public class AssetController extends BaseController { notes = "Fetch the Asset Info object based on the provided Asset Id. " + "If the user has the authority of 'Tenant Administrator', the server checks that the asset is owned by the same tenant. " + "If the user has the authority of 'Customer User', the server checks that the asset is assigned to the same customer. " - + ASSET_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + ASSET_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset/info/{assetId}", method = RequestMethod.GET) @ResponseBody @@ -135,7 +135,7 @@ public class AssetController extends BaseController { "Specify existing Asset id to update the asset. " + "Referencing non-existing Asset Id will cause 'Not Found' error. " + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Asset entity. " - + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset", method = RequestMethod.POST) @ResponseBody @@ -158,7 +158,7 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Assign asset to customer (assignAssetToCustomer)", - notes = "Creates assignment of the asset to customer. Customer will be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Creates assignment of the asset to customer. Customer will be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/asset/{assetId}", method = RequestMethod.POST) @ResponseBody @@ -174,7 +174,7 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Unassign asset from customer (unassignAssetFromCustomer)", - notes = "Clears assignment of the asset to customer. Customer will not be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Clears assignment of the asset to customer. Customer will not be able to query asset afterwards." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/asset/{assetId}", method = RequestMethod.DELETE) @ResponseBody @@ -192,7 +192,7 @@ public class AssetController extends BaseController { @ApiOperation(value = "Make asset publicly available (assignAssetToPublicCustomer)", notes = "Asset will be available for non-authorized (not logged-in) users. " + "This is useful to create dashboards that you plan to share/embed on a publicly available website. " + - "However, users that are logged-in and belong to different tenant will not be able to access the asset." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "However, users that are logged-in and belong to different tenant will not be able to access the asset." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/public/asset/{assetId}", method = RequestMethod.POST) @ResponseBody @@ -205,7 +205,7 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Tenant Assets (getTenantAssets)", notes = "Returns a page of assets owned by tenant. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -233,7 +233,7 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Tenant Asset Infos (getTenantAssetInfos)", notes = "Returns a page of assets info objects owned by tenant. " + - PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -266,7 +266,7 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Tenant Asset (getTenantAsset)", notes = "Requested asset must be owned by tenant that the user belongs to. " + - "Asset name is an unique property of asset. So it can be used to identify the asset." + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Asset name is an unique property of asset. So it can be used to identify the asset." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/assets", params = {"assetName"}, method = RequestMethod.GET) @ResponseBody @@ -279,7 +279,7 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Customer Assets (getCustomerAssets)", notes = "Returns a page of assets objects assigned to customer. " + - PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -312,7 +312,7 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get Customer Asset Infos (getCustomerAssetInfos)", notes = "Returns a page of assets info objects assigned to customer. " + - PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + ASSET_INFO_DESCRIPTION) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -349,7 +349,7 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Get Assets By Ids (getAssetsByIds)", - notes = "Requested assets must be owned by tenant or assigned to customer which user is performing the request. ", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Requested assets must be owned by tenant or assigned to customer which user is performing the request. ") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assets", params = {"assetIds"}, method = RequestMethod.GET) @ResponseBody @@ -376,7 +376,7 @@ public class AssetController extends BaseController { @ApiOperation(value = "Find related assets (findByQuery)", notes = "Returns all assets that are related to the specific entity. " + "The entity id, relation type, asset types, depth of the search, and other query parameters defined using complex 'AssetSearchQuery' object. " + - "See 'Model' tab of the Parameters for more info.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "See 'Model' tab of the Parameters for more info.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assets", method = RequestMethod.POST) @ResponseBody @@ -398,8 +398,7 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Get Asset Types (getAssetTypes)", - notes = "Deprecated. See 'getAssetProfileNames' API from Asset Profile Controller instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Deprecated. See 'getAssetProfileNames' API from Asset Profile Controller instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset/types", method = RequestMethod.GET) @ResponseBody @@ -416,8 +415,7 @@ public class AssetController extends BaseController { EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + "Second, remote edge service will receive a copy of assignment asset " + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + - "Third, once asset will be delivered to edge service, it's going to be available for usage on remote edge instance.", - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Third, once asset will be delivered to edge service, it's going to be available for usage on remote edge instance.") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.POST) @ResponseBody @@ -440,8 +438,7 @@ public class AssetController extends BaseController { EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + "Second, remote edge service will receive an 'unassign' command to remove asset " + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + - "Third, once 'unassign' command will be delivered to edge service, it's going to remove asset locally.", - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Third, once 'unassign' command will be delivered to edge service, it's going to remove asset locally.") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/asset/{assetId}", method = RequestMethod.DELETE) @ResponseBody @@ -460,7 +457,7 @@ public class AssetController extends BaseController { @ApiOperation(value = "Get assets assigned to edge (getEdgeAssets)", notes = "Returns a page of assets assigned to edge. " + - PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -510,7 +507,7 @@ public class AssetController extends BaseController { } @ApiOperation(value = "Import the bulk of assets (processAssetsBulkImport)", - notes = "There's an ability to import the bulk of assets using the only .csv file.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "There's an ability to import the bulk of assets using the only .csv file.") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PostMapping("/asset/bulk_import") public BulkImportResult processAssetsBulkImport(@RequestBody BulkImportRequest request) throws Exception { diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java index a6126011cc..a4dc7a1cb0 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetProfileController.java @@ -78,8 +78,7 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Asset Profile (getAssetProfileById)", notes = "Fetch the Asset Profile object based on the provided Asset Profile Id. " + - "The server checks that the asset profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "The server checks that the asset profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.GET) @ResponseBody @@ -99,8 +98,7 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Asset Profile Info (getAssetProfileInfoById)", notes = "Fetch the Asset Profile Info object based on the provided Asset Profile Id. " - + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assetProfileInfo/{assetProfileId}", method = RequestMethod.GET) @ResponseBody @@ -114,8 +112,7 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Default Asset Profile (getDefaultAssetProfileInfo)", notes = "Fetch the Default Asset Profile Info object. " + - ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assetProfileInfo/default", method = RequestMethod.GET) @ResponseBody @@ -130,8 +127,7 @@ public class AssetProfileController extends BaseController { "Referencing non-existing asset profile Id will cause 'Not Found' error. " + NEW_LINE + "Asset profile name is unique in the scope of tenant. Only one 'default' asset profile may exist in scope of tenant. " + "Remove 'id', 'tenantId' from the request body example (below) to create new Asset Profile entity. " + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfile", method = RequestMethod.POST) @ResponseBody @@ -145,8 +141,7 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Delete asset profile (deleteAssetProfile)", notes = "Deletes the asset profile. Referencing non-existing asset profile Id will cause an error. " + - "Can't delete the asset profile if it is referenced by existing assets." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Can't delete the asset profile if it is referenced by existing assets." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfile/{assetProfileId}", method = RequestMethod.DELETE) @ResponseStatus(value = HttpStatus.OK) @@ -160,8 +155,7 @@ public class AssetProfileController extends BaseController { } @ApiOperation(value = "Make Asset Profile Default (setDefaultAssetProfile)", - notes = "Marks asset profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Marks asset profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfile/{assetProfileId}/default", method = RequestMethod.POST) @ResponseBody @@ -177,8 +171,7 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Asset Profiles (getAssetProfiles)", notes = "Returns a page of asset profile objects owned by tenant. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/assetProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -199,8 +192,7 @@ public class AssetProfileController extends BaseController { @ApiOperation(value = "Get Asset Profile infos (getAssetProfileInfos)", notes = "Returns a page of asset profile info objects owned by tenant. " + - PAGE_DATA_PARAMETERS + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + ASSET_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/assetProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java b/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java index 5e58b28ab0..c8ea4073b1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuditLogController.java @@ -74,8 +74,7 @@ public class AuditLogController extends BaseController { @ApiOperation(value = "Get audit logs by customer id (getAuditLogsByCustomerId)", notes = "Returns a page of audit logs related to the targeted customer entities (devices, assets, etc.), " + "and users actions (login, logout, etc.) that belong to this customer. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -108,8 +107,7 @@ public class AuditLogController extends BaseController { @ApiOperation(value = "Get audit logs by user id (getAuditLogsByUserId)", notes = "Returns a page of audit logs related to the actions of targeted user. " + "For example, RPC call to a particular device, or alarm acknowledgment for a specific device, etc. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/audit/logs/user/{userId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -143,8 +141,7 @@ public class AuditLogController extends BaseController { notes = "Returns a page of audit logs related to the actions on the targeted entity. " + "Basically, this API call is used to get the full lifecycle of some specific entity. " + "For example to see when a device was created, updated, assigned to some customer, or even deleted from the system. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -179,8 +176,7 @@ public class AuditLogController extends BaseController { @ApiOperation(value = "Get all audit logs (getAuditLogs)", notes = "Returns a page of audit logs related to all entities in the scope of the current user's Tenant. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/audit/logs", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index 0683bc21be..dda88eceb6 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -133,9 +133,7 @@ public class DashboardController extends BaseController { } @ApiOperation(value = "Get Dashboard Info (getDashboardInfoById)", - notes = "Get the information about the dashboard based on 'dashboardId' parameter. " + DASHBOARD_INFO_DEFINITION, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)) - ) + notes = "Get the information about the dashboard based on 'dashboardId' parameter. " + DASHBOARD_INFO_DEFINITION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/info/{dashboardId}", method = RequestMethod.GET) @ResponseBody @@ -148,8 +146,7 @@ public class DashboardController extends BaseController { } @ApiOperation(value = "Get Dashboard (getDashboardById)", - notes = "Get the dashboard based on 'dashboardId' parameter. " + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)) + notes = "Get the dashboard based on 'dashboardId' parameter. " + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH ) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/{dashboardId}", method = RequestMethod.GET) @@ -174,8 +171,7 @@ public class DashboardController extends BaseController { "Specify existing Dashboard id to update the dashboard. " + "Referencing non-existing dashboard Id will cause 'Not Found' error. " + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Dashboard entity. " + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/dashboard", method = RequestMethod.POST) @ResponseBody @@ -203,8 +199,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Assign the Dashboard (assignDashboardToCustomer)", notes = "Assign the Dashboard to specified Customer or do nothing if the Dashboard is already assigned to that Customer. " + - "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.POST) @ResponseBody @@ -226,8 +221,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Unassign the Dashboard (unassignDashboardFromCustomer)", notes = "Unassign the Dashboard from specified Customer or do nothing if the Dashboard is already assigned to that Customer. " + - "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) @ResponseBody @@ -247,8 +241,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Update the Dashboard Customers (updateDashboardCustomers)", notes = "Updates the list of Customers that this Dashboard is assigned to. Removes previous assignments to customers that are not in the provided list. " + - "Returns the Dashboard object. " + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Returns the Dashboard object. " + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/dashboard/{dashboardId}/customers", method = RequestMethod.POST) @@ -267,8 +260,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Adds the Dashboard Customers (addDashboardCustomers)", notes = "Adds the list of Customers to the existing list of assignments for the Dashboard. Keeps previous assignments to customers that are not in the provided list. " + - "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/dashboard/{dashboardId}/customers/add", method = RequestMethod.POST) @ResponseBody @@ -286,8 +278,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Remove the Dashboard Customers (removeDashboardCustomers)", notes = "Removes the list of Customers from the existing list of assignments for the Dashboard. Keeps other assignments to customers that are not in the provided list. " + - "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/dashboard/{dashboardId}/customers/remove", method = RequestMethod.POST) @ResponseBody @@ -309,8 +300,7 @@ public class DashboardController extends BaseController { "Be aware that making the dashboard public does not mean that it automatically makes all devices and assets you use in the dashboard to be public." + "Use [assign Asset to Public Customer](#!/asset-controller/assignAssetToPublicCustomerUsingPOST) and " + "[assign Device to Public Customer](#!/device-controller/assignDeviceToPublicCustomerUsingPOST) for this purpose. " + - "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.POST) @ResponseBody @@ -325,8 +315,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Unassign the Dashboard from Public Customer (unassignDashboardFromPublicCustomer)", notes = "Unassigns the dashboard from a special, auto-generated 'Public' Customer. Once unassigned, unauthenticated users may no longer browse the dashboard. " + - "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Returns the Dashboard object." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/public/dashboard/{dashboardId}", method = RequestMethod.DELETE) @ResponseBody @@ -341,8 +330,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Tenant Dashboards by System Administrator (getTenantDashboards)", notes = "Returns a page of dashboard info objects owned by tenant. " + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + - SYSTEM_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + SYSTEM_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('SYS_ADMIN')") @RequestMapping(value = "/tenant/{tenantId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -367,8 +355,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Tenant Dashboards (getTenantDashboards)", notes = "Returns a page of dashboard info objects owned by the tenant of a current user. " - + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -396,8 +383,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Customer Dashboards (getCustomerDashboards)", notes = "Returns a page of dashboard info objects owned by the specified customer. " - + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -432,8 +418,7 @@ public class DashboardController extends BaseController { notes = "Returns the home dashboard object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " + "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " + "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " - + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + DASHBOARD_DEFINITION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/home", method = RequestMethod.GET) @ResponseBody @@ -465,8 +450,7 @@ public class DashboardController extends BaseController { notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the User. " + "If 'homeDashboardId' parameter is not set on the User level and the User has authority 'CUSTOMER_USER', check the same parameter for the corresponding Customer. " + "If 'homeDashboardId' parameter is not set on the User and Customer levels then checks the same parameter for the Tenant that owns the user. " + - TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/dashboard/home/info", method = RequestMethod.GET) @ResponseBody @@ -496,8 +480,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", notes = "Returns the home dashboard info object that is configured as 'homeDashboardId' parameter in the 'additionalInfo' of the corresponding tenant. " + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.GET) @ResponseBody @@ -518,8 +501,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Update Tenant Home Dashboard Info (getTenantHomeDashboardInfo)", notes = "Update the home dashboard assignment for the current tenant. " + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/dashboard/home/info", method = RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) @@ -584,8 +566,7 @@ public class DashboardController extends BaseController { "Second, remote edge service will receive a copy of assignment dashboard " + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once dashboard will be delivered to edge service, it's going to be available for usage on remote edge instance." + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.POST) @ResponseBody @@ -608,8 +589,7 @@ public class DashboardController extends BaseController { "Second, remote edge service will receive an 'unassign' command to remove dashboard " + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once 'unassign' command will be delivered to edge service, it's going to remove dashboard locally." + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/dashboard/{dashboardId}", method = RequestMethod.DELETE) @ResponseBody @@ -629,8 +609,7 @@ public class DashboardController extends BaseController { @ApiOperation(value = "Get Edge Dashboards (getEdgeDashboards)", notes = "Returns a page of dashboard info objects assigned to the specified edge. " - + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + DASHBOARD_INFO_DEFINITION + " " + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 555769370c..23518c96bf 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -534,8 +534,7 @@ public class DeviceController extends BaseController { } @ApiOperation(value = "Get Device Types (getDeviceTypes)", - notes = "Deprecated. See 'getDeviceProfileNames' API from Device Profile Controller instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Deprecated. See 'getDeviceProfileNames' API from Device Profile Controller instead." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/types", method = RequestMethod.GET) @ResponseBody @@ -668,8 +667,7 @@ public class DeviceController extends BaseController { EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + "Second, remote edge service will receive a copy of assignment device " + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + - "Third, once device will be delivered to edge service, it's going to be available for usage on remote edge instance." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Third, once device will be delivered to edge service, it's going to be available for usage on remote edge instance." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.POST) @ResponseBody @@ -693,8 +691,7 @@ public class DeviceController extends BaseController { EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + "Second, remote edge service will receive an 'unassign' command to remove device " + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + - "Third, once 'unassign' command will be delivered to edge service, it's going to remove device locally." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Third, once 'unassign' command will be delivered to edge service, it's going to remove device locally." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/device/{deviceId}", method = RequestMethod.DELETE) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java index 02cf15c81d..b84e801d31 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceProfileController.java @@ -86,8 +86,7 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Device Profile (getDeviceProfileById)", notes = "Fetch the Device Profile object based on the provided Device Profile Id. " + - "The server checks that the device profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "The server checks that the device profile is owned by the same tenant. " + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile/{deviceProfileId}", method = RequestMethod.GET) @ResponseBody @@ -107,8 +106,7 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Device Profile Info (getDeviceProfileInfoById)", notes = "Fetch the Device Profile Info object based on the provided Device Profile Id. " - + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/deviceProfileInfo/{deviceProfileId}", method = RequestMethod.GET) @ResponseBody @@ -122,8 +120,7 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Default Device Profile (getDefaultDeviceProfileInfo)", notes = "Fetch the Default Device Profile Info object. " + - DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/deviceProfileInfo/default", method = RequestMethod.GET) @ResponseBody @@ -136,8 +133,7 @@ public class DeviceProfileController extends BaseController { "If profile is not set returns a list of unique keys among all profiles. " + "The call is used for auto-complete in the UI forms. " + "The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. " + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile/devices/keys/timeseries", method = RequestMethod.GET) @ResponseBody @@ -160,8 +156,7 @@ public class DeviceProfileController extends BaseController { "If profile is not set returns a list of unique keys among all profiles. " + "The call is used for auto-complete in the UI forms. " + "The implementation limits the number of devices that participate in search to 100 as a trade of between accurate results and time-consuming queries. " + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile/devices/keys/attributes", method = RequestMethod.GET) @ResponseBody @@ -186,8 +181,7 @@ public class DeviceProfileController extends BaseController { "Referencing non-existing device profile Id will cause 'Not Found' error. " + NEW_LINE + "Device profile name is unique in the scope of tenant. Only one 'default' device profile may exist in scope of tenant." + DEVICE_PROFILE_DATA + "Remove 'id', 'tenantId' from the request body example (below) to create new Device Profile entity. " + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile", method = RequestMethod.POST) @ResponseBody @@ -215,8 +209,7 @@ public class DeviceProfileController extends BaseController { } @ApiOperation(value = "Make Device Profile Default (setDefaultDeviceProfile)", - notes = "Marks device profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Marks device profile as default within a tenant scope." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfile/{deviceProfileId}/default", method = RequestMethod.POST) @ResponseBody @@ -232,8 +225,7 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Device Profiles (getDeviceProfiles)", notes = "Returns a page of devices profile objects owned by tenant. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/deviceProfiles", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -254,8 +246,7 @@ public class DeviceProfileController extends BaseController { @ApiOperation(value = "Get Device Profiles for transport type (getDeviceProfileInfos)", notes = "Returns a page of devices profile info objects owned by tenant. " + - PAGE_DATA_PARAMETERS + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/deviceProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java index 9781d48828..3042b8f2a1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeController.java @@ -120,8 +120,7 @@ public class EdgeController extends BaseController { } @ApiOperation(value = "Get Edge (getEdgeById)", - notes = "Get the Edge object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Get the Edge object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/{edgeId}", method = RequestMethod.GET) @ResponseBody @@ -133,8 +132,7 @@ public class EdgeController extends BaseController { } @ApiOperation(value = "Get Edge Info (getEdgeInfoById)", - notes = "Get the Edge Info object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Get the Edge Info object based on the provided Edge Id. " + EDGE_SECURITY_CHECK + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/info/{edgeId}", method = RequestMethod.GET) @ResponseBody @@ -152,8 +150,7 @@ public class EdgeController extends BaseController { "Referencing non-existing Edge Id will cause 'Not Found' error." + "\n\nEdge name is unique in the scope of tenant. Use unique identifiers like MAC or IMEI for the edge names and non-unique 'label' field for user-friendly visualization purposes." + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Edge entity. " + - TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge", method = RequestMethod.POST) @ResponseBody @@ -193,7 +190,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Tenant Edges (getEdges)", notes = "Returns a page of edges owned by tenant. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -213,8 +210,7 @@ public class EdgeController extends BaseController { } @ApiOperation(value = "Assign edge to customer (assignEdgeToCustomer)", - notes = "Creates assignment of the edge to customer. Customer will be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Creates assignment of the edge to customer. Customer will be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/{customerId}/edge/{edgeId}", method = RequestMethod.POST) @ResponseBody @@ -232,8 +228,7 @@ public class EdgeController extends BaseController { } @ApiOperation(value = "Unassign edge from customer (unassignEdgeFromCustomer)", - notes = "Clears assignment of the edge to customer. Customer will not be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Clears assignment of the edge to customer. Customer will not be able to query edge afterwards." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/edge/{edgeId}", method = RequestMethod.DELETE) @ResponseBody @@ -253,8 +248,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Make edge publicly available (assignEdgeToPublicCustomer)", notes = "Edge will be available for non-authorized (not logged-in) users. " + "This is useful to create dashboards that you plan to share/embed on a publicly available website. " + - "However, users that are logged-in and belong to different tenant will not be able to access the edge." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "However, users that are logged-in and belong to different tenant will not be able to access the edge." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer/public/edge/{edgeId}", method = RequestMethod.POST) @ResponseBody @@ -268,7 +262,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Tenant Edges (getTenantEdges)", notes = "Returns a page of edges owned by tenant. " + - PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -296,8 +290,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Tenant Edge Infos (getTenantEdgeInfos)", notes = "Returns a page of edges info objects owned by tenant. " + - PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -325,8 +318,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Tenant Edge (getTenantEdge)", notes = "Requested edge must be owned by tenant or customer that the user belongs to. " + - "Edge name is an unique property of edge. So it can be used to identify the edge." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Edge name is an unique property of edge. So it can be used to identify the edge." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/edges", params = {"edgeName"}, method = RequestMethod.GET) @ResponseBody @@ -338,8 +330,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Set root rule chain for provided edge (setEdgeRootRuleChain)", notes = "Change root rule chain of the edge to the new provided rule chain. \n" + - "This operation will send a notification to update root rule chain on remote edge service." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "This operation will send a notification to update root rule chain on remote edge service." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/{ruleChainId}/root", method = RequestMethod.POST) @ResponseBody @@ -359,7 +350,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Customer Edges (getCustomerEdges)", notes = "Returns a page of edges objects assigned to customer. " + - PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/edges", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -395,7 +386,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Customer Edge Infos (getCustomerEdgeInfos)", notes = "Returns a page of edges info objects assigned to customer. " + - PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + EDGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/customer/{customerId}/edgeInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) @ResponseBody @@ -430,8 +421,7 @@ public class EdgeController extends BaseController { } @ApiOperation(value = "Get Edges By Ids (getEdgesByIds)", - notes = "Requested edges must be owned by tenant or assigned to customer which user is performing the request." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Requested edges must be owned by tenant or assigned to customer which user is performing the request." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edges", params = {"edgeIds"}, method = RequestMethod.GET) @ResponseBody @@ -459,8 +449,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Find related edges (findByQuery)", notes = "Returns all edges that are related to the specific entity. " + "The entity id, relation type, edge types, depth of the search, and other query parameters defined using complex 'EdgeSearchQuery' object. " + - "See 'Model' tab of the Parameters for more info." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "See 'Model' tab of the Parameters for more info." + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edges", method = RequestMethod.POST) @ResponseBody @@ -485,8 +474,7 @@ public class EdgeController extends BaseController { @ApiOperation(value = "Get Edge Types (getEdgeTypes)", notes = "Returns a set of unique edge types based on edges that are either owned by the tenant or assigned to the customer which user is performing the request." - + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/edge/types", method = RequestMethod.GET) @ResponseBody @@ -542,8 +530,7 @@ public class EdgeController extends BaseController { } @ApiOperation(value = "Import the bulk of edges (processEdgesBulkImport)", - notes = "There's an ability to import the bulk of edges using the only .csv file." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "There's an ability to import the bulk of edges using the only .csv file." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @PostMapping("/edge/bulk_import") public BulkImportResult processEdgesBulkImport(@RequestBody BulkImportRequest request) throws Exception { @@ -557,8 +544,7 @@ public class EdgeController extends BaseController { } @ApiOperation(value = "Get Edge Install Instructions (getEdgeInstallInstructions)", - notes = "Get an install instructions for provided edge id." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Get an install instructions for provided edge id." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/instructions/install/{edgeId}/{method}", method = RequestMethod.GET) @ResponseBody @@ -579,8 +565,7 @@ public class EdgeController extends BaseController { } @ApiOperation(value = "Get Edge Upgrade Instructions (getEdgeUpgradeInstructions)", - notes = "Get an upgrade instructions for provided edge version." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Get an upgrade instructions for provided edge version." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/instructions/upgrade/{edgeVersion}/{method}", method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java index 8828a714fc..d1912ba38f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EdgeEventController.java @@ -60,7 +60,7 @@ public class EdgeEventController extends BaseController { @ApiOperation(value = "Get Edge Events (getEdgeEvents)", notes = "Returns a page of edge events for the requested edge. " + - PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/events", method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java index 3932e483d5..0cd31a729b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java @@ -135,8 +135,7 @@ public class EntityRelationController extends BaseController { } @ApiOperation(value = "Get Relation (getRelation)", - notes = "Returns relation object between two specified entities if present. Otherwise throws exception. " + SECURITY_CHECKS_ENTITIES_DESCRIPTION, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Returns relation object between two specified entities if present. Otherwise throws exception. " + SECURITY_CHECKS_ENTITIES_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relation", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE, RELATION_TYPE, TO_ID, TO_TYPE}) @ResponseBody @@ -161,8 +160,7 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relations (findByFrom)", notes = "Returns list of relation objects for the specified entity by the 'from' direction. " + - SECURITY_CHECKS_ENTITY_DESCRIPTION, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + SECURITY_CHECKS_ENTITY_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE}) @ResponseBody @@ -180,8 +178,7 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relation Infos (findInfoByFrom)", notes = "Returns list of relation info objects for the specified entity by the 'from' direction. " + - SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE}) @ResponseBody @@ -199,8 +196,7 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relations (findByFrom)", notes = "Returns list of relation objects for the specified entity by the 'from' direction and relation type. " + - SECURITY_CHECKS_ENTITY_DESCRIPTION, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + SECURITY_CHECKS_ENTITY_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {FROM_ID, FROM_TYPE, RELATION_TYPE}) @ResponseBody @@ -220,8 +216,7 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relations (findByTo)", notes = "Returns list of relation objects for the specified entity by the 'to' direction. " + - SECURITY_CHECKS_ENTITY_DESCRIPTION, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + SECURITY_CHECKS_ENTITY_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {TO_ID, TO_TYPE}) @ResponseBody @@ -239,8 +234,7 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relation Infos (findInfoByTo)", notes = "Returns list of relation info objects for the specified entity by the 'to' direction. " + - SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + SECURITY_CHECKS_ENTITY_DESCRIPTION + " " + RELATION_INFO_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations/info", method = RequestMethod.GET, params = {TO_ID, TO_TYPE}) @ResponseBody @@ -258,8 +252,7 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Get List of Relations (findByTo)", notes = "Returns list of relation objects for the specified entity by the 'to' direction and relation type. " + - SECURITY_CHECKS_ENTITY_DESCRIPTION, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + SECURITY_CHECKS_ENTITY_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.GET, params = {TO_ID, TO_TYPE, RELATION_TYPE}) @ResponseBody @@ -280,7 +273,7 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Find related entities (findByQuery)", notes = "Returns all entities that are related to the specific entity. " + "The entity id, relation type, entity types, depth of the search, and other query parameters defined using complex 'EntityRelationsQuery' object. " + - "See 'Model' tab of the Parameters for more info.", responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "See 'Model' tab of the Parameters for more info.") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations", method = RequestMethod.POST) @ResponseBody @@ -296,7 +289,7 @@ public class EntityRelationController extends BaseController { @ApiOperation(value = "Find related entity infos (findInfoByQuery)", notes = "Returns all entity infos that are related to the specific entity. " + "The entity id, relation type, entity types, depth of the search, and other query parameters defined using complex 'EntityRelationsQuery' object. " + - "See 'Model' tab of the Parameters for more info. " + RELATION_INFO_DESCRIPTION, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "See 'Model' tab of the Parameters for more info. " + RELATION_INFO_DESCRIPTION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/relations/info", method = RequestMethod.POST) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java index 59877bd4d2..8b33aeeb15 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -97,8 +97,7 @@ public class EntityViewController extends BaseController { @ApiOperation(value = "Get entity view (getEntityViewById)", notes = "Fetch the EntityView object based on the provided entity view id. " - + ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET) @ResponseBody @@ -111,8 +110,7 @@ public class EntityViewController extends BaseController { @ApiOperation(value = "Get Entity View info (getEntityViewInfoById)", notes = "Fetch the Entity View info object based on the provided Entity View Id. " - + ENTITY_VIEW_INFO_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + ENTITY_VIEW_INFO_DESCRIPTION + MODEL_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityView/info/{entityViewId}", method = RequestMethod.GET) @ResponseBody @@ -127,8 +125,7 @@ public class EntityViewController extends BaseController { @ApiOperation(value = "Save or update entity view (saveEntityView)", notes = ENTITY_VIEW_DESCRIPTION + MODEL_DESCRIPTION + "Remove 'id', 'tenantId' and optionally 'customerId' from the request body example (below) to create new Entity View entity." + - TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityView", method = RequestMethod.POST) @ResponseBody @@ -162,8 +159,7 @@ public class EntityViewController extends BaseController { } @ApiOperation(value = "Get Entity View by name (getTenantEntityView)", - notes = "Fetch the Entity View object based on the tenant id and entity view name. " + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + notes = "Fetch the Entity View object based on the tenant id and entity view name. " + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/tenant/entityViews", params = {"entityViewName"}, method = RequestMethod.GET) @ResponseBody @@ -399,8 +395,7 @@ public class EntityViewController extends BaseController { EDGE_ASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + "Second, remote edge service will receive a copy of assignment entity view " + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + - "Third, once entity view will be delivered to edge service, it's going to be available for usage on remote edge instance.", - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Third, once entity view will be delivered to edge service, it's going to be available for usage on remote edge instance.") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/entityView/{entityViewId}", method = RequestMethod.POST) @ResponseBody @@ -424,8 +419,7 @@ public class EntityViewController extends BaseController { EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + "Second, remote edge service will receive an 'unassign' command to remove entity view " + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + - "Third, once 'unassign' command will be delivered to edge service, it's going to remove entity view locally.", - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Third, once 'unassign' command will be delivered to edge service, it's going to remove entity view locally.") @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/entityView/{entityViewId}", method = RequestMethod.DELETE) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/EventController.java b/application/src/main/java/org/thingsboard/server/controller/EventController.java index b1e2405ae6..372d724912 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EventController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EventController.java @@ -108,7 +108,7 @@ public class EventController extends BaseController { @ApiOperation(value = "Get Events by type (getEvents)", notes = "Returns a page of events for specified entity by specifying event type. " + - PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/events/{entityType}/{entityId}/{eventType}", method = RequestMethod.GET) @ResponseBody @@ -150,7 +150,7 @@ public class EventController extends BaseController { "The call was deprecated to improve the performance of the system. " + "Current implementation will return 'Lifecycle' events only. " + "Use 'Get events by type' or 'Get events by filter' instead. " + - PAGE_DATA_PARAMETERS, responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.GET) @ResponseBody @@ -190,8 +190,7 @@ public class EventController extends BaseController { @ApiOperation(value = "Get Events by event filter (getEvents)", notes = "Returns a page of events for the chosen entity by specifying the event filter. " + PAGE_DATA_PARAMETERS + NEW_LINE + - EVENT_FILTER_DEFINITION, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + EVENT_FILTER_DEFINITION) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.POST) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java b/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java index f6670193d9..25e49eb198 100644 --- a/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java +++ b/application/src/main/java/org/thingsboard/server/controller/Lwm2mController.java @@ -59,8 +59,7 @@ public class Lwm2mController extends BaseController { @ApiOperation(value = "Get Lwm2m Bootstrap SecurityInfo (getLwm2mBootstrapSecurityInfo)", notes = "Get the Lwm2m Bootstrap SecurityInfo object (of the current server) based on the provided isBootstrapServer parameter. If isBootstrapServer == true, get the parameters of the current Bootstrap Server. If isBootstrapServer == false, get the parameters of the current Lwm2m Server. Used for client settings when starting the client in Bootstrap mode. " + - TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/lwm2m/deviceProfile/bootstrap/{isBootstrapServer}", method = RequestMethod.GET) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java b/application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java index 4ceb39534f..f2b77c3b7b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java +++ b/application/src/main/java/org/thingsboard/server/controller/OtaPackageController.java @@ -105,8 +105,7 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Get OTA Package Info (getOtaPackageInfoById)", notes = "Fetch the OTA Package Info object based on the provided OTA Package Id. " + - OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/otaPackage/info/{otaPackageId}", method = RequestMethod.GET) @ResponseBody @@ -119,8 +118,7 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Get OTA Package (getOtaPackageById)", notes = "Fetch the OTA Package object based on the provided OTA Package Id. " + - "The server checks that the OTA Package is owned by the same tenant. " + OTA_PACKAGE_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) + "The server checks that the OTA Package is owned by the same tenant. " + OTA_PACKAGE_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.GET) @ResponseBody @@ -136,8 +134,7 @@ public class OtaPackageController extends BaseController { "The newly created OTA Package id will be present in the response. " + "Specify existing OTA Package id to update the OTA Package Info. " + "Referencing non-existing OTA Package Id will cause 'Not Found' error. " + - "\n\nOTA Package combination of the title with the version is unique in the scope of tenant. " + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) + "\n\nOTA Package combination of the title with the version is unique in the scope of tenant. " + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/otaPackage", method = RequestMethod.POST) @ResponseBody @@ -151,7 +148,6 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Save OTA Package data (saveOtaPackageData)", notes = "Update the OTA Package. Adds the date to the existing OTA Package Info" + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE)), requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(mediaType = MULTIPART_FORM_DATA_VALUE))) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.POST, consumes = MULTIPART_FORM_DATA_VALUE) @@ -176,8 +172,7 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Get OTA Package Infos (getOtaPackages)", notes = "Returns a page of OTA Package Info objects owned by tenant. " + - PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/otaPackages", method = RequestMethod.GET) @ResponseBody @@ -197,8 +192,7 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Get OTA Package Infos (getOtaPackages)", notes = "Returns a page of OTA Package Info objects owned by tenant. " + - PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + OTA_PACKAGE_INFO_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/otaPackages/{deviceProfileId}/{type}", method = RequestMethod.GET) @ResponseBody @@ -225,8 +219,7 @@ public class OtaPackageController extends BaseController { @ApiOperation(value = "Delete OTA Package (deleteOtaPackage)", notes = "Deletes the OTA Package. Referencing non-existing OTA Package Id will cause an error. " + - "Can't delete the OTA Package if it is referenced by existing devices or device profile." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = APPLICATION_JSON_VALUE))) + "Can't delete the OTA Package if it is referenced by existing devices or device profile." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @RequestMapping(value = "/otaPackage/{otaPackageId}", method = RequestMethod.DELETE) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java index e7c6e138ca..8d51daab8b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java +++ b/application/src/main/java/org/thingsboard/server/controller/RuleChainController.java @@ -371,7 +371,7 @@ public class RuleChainController extends BaseController { public JsonNode testScript( @Parameter(description = "Script language: JS or TBEL") @RequestParam(required = false) ScriptLanguage scriptLang, - @Parameter(description = "Test JS request. See API call description above.") + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Test JS request. See API call description above.") @RequestBody JsonNode inputParams) throws ThingsboardException, JsonProcessingException { String script = inputParams.get("script").asText(); String scriptType = inputParams.get("scriptType").asText(); @@ -499,8 +499,7 @@ public class RuleChainController extends BaseController { "Second, remote edge service will receive a copy of assignment rule chain " + EDGE_ASSIGN_RECEIVE_STEP_DESCRIPTION + "Third, once rule chain will be delivered to edge service, it's going to start processing messages locally. " + - "\n\nOnly rule chain with type 'EDGE' can be assigned to edge." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "\n\nOnly rule chain with type 'EDGE' can be assigned to edge." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.POST) @ResponseBody @@ -522,8 +521,7 @@ public class RuleChainController extends BaseController { EDGE_UNASSIGN_ASYNC_FIRST_STEP_DESCRIPTION + "Second, remote edge service will receive an 'unassign' command to remove rule chain " + EDGE_UNASSIGN_RECEIVE_STEP_DESCRIPTION + - "Third, once 'unassign' command will be delivered to edge service, it's going to remove rule chain locally." + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Third, once 'unassign' command will be delivered to edge service, it's going to remove rule chain locally." + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/edge/{edgeId}/ruleChain/{ruleChainId}", method = RequestMethod.DELETE) @ResponseBody diff --git a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java index bf59f78519..1908459200 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TbResourceController.java @@ -146,8 +146,7 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get Resource Info (getResourceInfoById)", notes = "Fetch the Resource Info object based on the provided Resource Id. " + - RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @GetMapping(value = "/resource/info/{resourceId}") public TbResourceInfo getResourceInfoById(@Parameter(description = RESOURCE_ID_PARAM_DESCRIPTION) @@ -159,8 +158,7 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get Resource (getResourceById)", notes = "Fetch the Resource object based on the provided Resource Id. " + - RESOURCE_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)), hidden = true) + RESOURCE_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, hidden = true) @Deprecated // resource's data should be fetched with a download request @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @GetMapping(value = "/resource/{resourceId}") @@ -178,8 +176,7 @@ public class TbResourceController extends BaseController { "Referencing non-existing Resource Id will cause 'Not Found' error. " + "\n\nResource combination of the title with the key is unique in the scope of tenant. " + "Remove 'id', 'tenantId' from the request body example (below) to create new Resource entity." + - SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @PostMapping(value = "/resource") public TbResourceInfo saveResource(@Parameter(description = "A JSON value representing the Resource.") @@ -191,8 +188,7 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get Resource Infos (getResources)", notes = "Returns a page of Resource Info objects owned by tenant or sysadmin. " + - PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @GetMapping(value = "/resource") public PageData getResources(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @@ -227,8 +223,7 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get All Resource Infos (getAllResources)", notes = "Returns a page of Resource Info objects owned by tenant. " + - PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + RESOURCE_INFO_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @GetMapping(value = "/resource/tenant") public PageData getTenantResources(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @@ -251,8 +246,7 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjectsPage)", notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " + - PAGE_DATA_PARAMETERS + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + PAGE_DATA_PARAMETERS + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @GetMapping(value = "/resource/lwm2m/page") public List getLwm2mListObjectsPage(@Parameter(description = PAGE_SIZE_DESCRIPTION, required = true) @@ -271,8 +265,7 @@ public class TbResourceController extends BaseController { @ApiOperation(value = "Get LwM2M Objects (getLwm2mListObjects)", notes = "Returns a page of LwM2M objects parsed from Resources with type 'LWM2M_MODEL' owned by tenant or sysadmin. " + - "You can specify parameters to filter the results. " + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "You can specify parameters to filter the results. " + LWM2M_OBJECT_DESCRIPTION + TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") @GetMapping(value = "/resource/lwm2m") public List getLwm2mListObjects(@Parameter(description = SORT_ORDER_DESCRIPTION, schema = @Schema(allowableValues = {"ASC", "DESC"}, required = true)) diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index 9ca600603c..4e28caa3ba 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -177,8 +177,7 @@ public class TelemetryController extends BaseController { "\n\n * SERVER_SCOPE - supported for all entity types;" + "\n * CLIENT_SCOPE - supported for devices;" + "\n * SHARED_SCOPE - supported for devices. " - + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes", method = RequestMethod.GET) @ResponseBody @@ -193,8 +192,7 @@ public class TelemetryController extends BaseController { "\n\n * SERVER_SCOPE - supported for all entity types;" + "\n * CLIENT_SCOPE - supported for devices;" + "\n * SHARED_SCOPE - supported for devices. " - + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/attributes/{scope}", method = RequestMethod.GET) @ResponseBody @@ -212,8 +210,7 @@ public class TelemetryController extends BaseController { + MARKDOWN_CODE_BLOCK_START + ATTRIBUTE_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END - + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/attributes", method = RequestMethod.GET) @ResponseBody @@ -235,8 +232,7 @@ public class TelemetryController extends BaseController { + MARKDOWN_CODE_BLOCK_START + ATTRIBUTE_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END - + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/attributes/{scope}", method = RequestMethod.GET) @ResponseBody @@ -252,8 +248,7 @@ public class TelemetryController extends BaseController { @ApiOperation(value = "Get time-series keys (getTimeseriesKeys)", notes = "Returns a set of unique time-series key names for the selected entity. " + - "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/keys/timeseries", method = RequestMethod.GET) @ResponseBody @@ -275,8 +270,7 @@ public class TelemetryController extends BaseController { + MARKDOWN_CODE_BLOCK_START + LATEST_TS_STRICT_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END - + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + "\n\n " + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET) @ResponseBody @@ -299,8 +293,7 @@ public class TelemetryController extends BaseController { + MARKDOWN_CODE_BLOCK_START + TS_STRICT_DATA_EXAMPLE + MARKDOWN_CODE_BLOCK_END - + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + "\n\n" + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/{entityType}/{entityId}/values/timeseries", method = RequestMethod.GET, params = {"keys", "startTs", "endTs"}) @ResponseBody @@ -348,8 +341,7 @@ public class TelemetryController extends BaseController { @ApiOperation(value = "Save device attributes (saveDeviceAttributes)", notes = "Creates or updates the device attributes based on device id and specified attribute scope. " + SAVE_ATTRIBUTES_REQUEST_PAYLOAD - + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + "Platform creates an audit log event about device attributes updates with action type 'ATTRIBUTES_UPDATED', " + @@ -365,7 +357,7 @@ public class TelemetryController extends BaseController { public DeferredResult saveDeviceAttributes( @Parameter(description = DEVICE_ID_PARAM_DESCRIPTION, required = true) @PathVariable("deviceId") String deviceIdStr, @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, required = true)) @PathVariable("scope") AttributeScope scope, - @Parameter(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndUuid(EntityType.DEVICE, deviceIdStr); return saveAttributes(getTenantId(), entityId, scope, request); } @@ -374,8 +366,7 @@ public class TelemetryController extends BaseController { notes = "Creates or updates the entity attributes based on Entity Id and the specified attribute scope. " + ENTITY_SAVE_ATTRIBUTE_SCOPES + SAVE_ATTRIBUTES_REQUEST_PAYLOAD - + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), @ApiResponse(responseCode = "400", description = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), @@ -389,7 +380,7 @@ public class TelemetryController extends BaseController { @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"})) @PathVariable("scope")AttributeScope scope, - @Parameter(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody JsonNode request) throws ThingsboardException { + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveAttributes(getTenantId(), entityId, scope, request); } @@ -398,8 +389,7 @@ public class TelemetryController extends BaseController { notes = "Creates or updates the entity attributes based on Entity Id and the specified attribute scope. " + ENTITY_SAVE_ATTRIBUTE_SCOPES + SAVE_ATTRIBUTES_REQUEST_PAYLOAD - + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = SAVE_ATTIRIBUTES_STATUS_OK + SAVE_ENTITY_ATTRIBUTES_STATUS_OK), @ApiResponse(responseCode = "400", description = SAVE_ATTIRIBUTES_STATUS_BAD_REQUEST), @@ -413,7 +403,7 @@ public class TelemetryController extends BaseController { @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @Parameter(description = ATTRIBUTES_SCOPE_DESCRIPTION, schema = @Schema(allowableValues = {"SERVER_SCOPE", "SHARED_SCOPE"}, required = true)) @PathVariable("scope")AttributeScope scope, - @Parameter(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody JsonNode request) throws ThingsboardException { + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = ATTRIBUTES_JSON_REQUEST_DESCRIPTION, required = true) @RequestBody JsonNode request) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveAttributes(getTenantId(), entityId, scope, request); } @@ -423,8 +413,7 @@ public class TelemetryController extends BaseController { notes = "Creates or updates the entity time-series data based on the Entity Id and request payload." + SAVE_TIMESERIES_REQUEST_PAYLOAD + "\n\n The scope parameter is not used in the API call implementation but should be specified whatever value because it is used as a path variable. " - + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = SAVE_ENTITY_TIMESERIES_STATUS_OK), @ApiResponse(responseCode = "400", description = INVALID_STRUCTURE_OF_THE_REQUEST), @@ -448,8 +437,7 @@ public class TelemetryController extends BaseController { SAVE_TIMESERIES_REQUEST_PAYLOAD + "\n\n The scope parameter is not used in the API call implementation but should be specified whatever value because it is used as a path variable. " + "\n\nThe ttl parameter takes affect only in case of Cassandra DB." - + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = SAVE_ENTITY_TIMESERIES_STATUS_OK), @ApiResponse(responseCode = "400", description = INVALID_STRUCTURE_OF_THE_REQUEST), @@ -476,8 +464,7 @@ public class TelemetryController extends BaseController { " Use 'deleteLatest' to delete latest value (stored in separate table for performance) if the value's timestamp matches the time-range. " + " Use 'rewriteLatestIfDeleted' to rewrite latest value (stored in separate table for performance) if the value's timestamp matches the time-range and 'deleteLatest' param is true." + " The replacement value will be fetched from the 'time-series' table, and its timestamp will be the most recent one before the defined time-range. " + - TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Timeseries for the selected keys in the request was removed. " + "Platform creates an audit log event about entity timeseries removal with action type 'TIMESERIES_DELETED'."), @@ -552,8 +539,7 @@ public class TelemetryController extends BaseController { @ApiOperation(value = "Delete device attributes (deleteDeviceAttributes)", notes = "Delete device attributes using provided Device Id, scope and a list of keys. " + - "Referencing a non-existing Device Id will cause an error" + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "Referencing a non-existing Device Id will cause an error" + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Device attributes was removed for the selected keys in the request. " + "Platform creates an audit log event about device attributes removal with action type 'ATTRIBUTES_DELETED'."), @@ -575,8 +561,7 @@ public class TelemetryController extends BaseController { @ApiOperation(value = "Delete entity attributes (deleteEntityAttributes)", notes = "Delete entity attributes using provided Entity Id, scope and a list of keys. " + - INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + INVALID_ENTITY_ID_OR_ENTITY_TYPE_DESCRIPTION + TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Entity attributes was removed for the selected keys in the request. " + "Platform creates an audit log event about entity attributes removal with action type 'ATTRIBUTES_DELETED'."), diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 521be28f84..daf9f5d1c1 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1332,6 +1332,8 @@ springdoc: swagger: # General swagger match pattern of swagger UI links api_path: "${SWAGGER_API_PATH:/api/**}" + # General swagger match pattern path of swagger UI links + security_path_regex: "${SWAGGER_SECURITY_PATH_REGEX:/api/.*}" # Nonsecurity API path match pattern of swagger UI links non_security_path_regex: "${SWAGGER_NON_SECURITY_PATH_REGEX:/api/(?:noauth|v1)/.*}" # The title on the API doc UI page diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java index 23b6c9b76d..0bd8e3a687 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmComment.java @@ -25,6 +25,7 @@ import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.id.AlarmCommentId; +import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.validation.Length; @@ -36,21 +37,21 @@ import org.thingsboard.server.common.data.validation.NoXss; @AllArgsConstructor public class AlarmComment extends BaseData implements HasName { @Schema(description = "JSON object with Alarm id.", accessMode = Schema.AccessMode.READ_ONLY) - private EntityId alarmId; + private AlarmId alarmId; @Schema(description = "JSON object with User id.", accessMode = Schema.AccessMode.READ_ONLY) private UserId userId; @Schema(description = "Defines origination of comment. System type means comment was created by TB. OTHER type means comment was created by user.", example = "SYSTEM/OTHER", accessMode = Schema.AccessMode.READ_ONLY) private AlarmCommentType type; - @Schema(description = "JSON object with text of comment.",implementation = com.fasterxml.jackson.databind.JsonNode.class) + @Schema(description = "JSON object with text of comment.") @NoXss @Length(fieldName = "comment", max = 10000) @EqualsAndHashCode.Include - private transient JsonNode comment; + private JsonNode comment; @Schema(description = "JSON object with the alarm comment Id. " + "Specify this field to update the alarm comment. " + "Referencing non-existing alarm Id will cause error. " + - "Omit this field to create new alarm." ) + "Omit this field to create new alarm.", accessMode = Schema.AccessMode.READ_ONLY) @Override public AlarmCommentId getId() { return super.getId(); @@ -72,7 +73,7 @@ public class AlarmComment extends BaseData implements HasName { @Override @JsonProperty(access = JsonProperty.Access.READ_ONLY) - @Schema(required = true, description = "representing comment text", example = "Please take a look") + @Schema(accessMode = Schema.AccessMode.READ_ONLY, description = "representing comment text", example = "Please take a look") public String getName() { return comment.toString(); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java index 8b4b1f156d..64c6b03427 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java @@ -35,10 +35,10 @@ public interface EntityId extends HasUUID, Serializable { //NOSONAR, the constan UUID NULL_UUID = UUID.fromString("13814000-1dd2-11b2-8080-808080808080"); - @Schema(required = true, description = "ID of the entity, time-based UUID v1", example = "784f394c-42b6-435a-983c-b7beff2784f9") + @Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "ID of the entity, time-based UUID v1", example = "784f394c-42b6-435a-983c-b7beff2784f9") UUID getId(); - @Schema(required = true, example = "DEVICE") + @Schema(requiredMode = Schema.RequiredMode.REQUIRED, example = "DEVICE") EntityType getEntityType(); @JsonIgnore diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java index 1f18f5a78e..65658246d2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/UserId.java @@ -22,6 +22,7 @@ import org.thingsboard.server.common.data.EntityType; import java.util.UUID; +@Schema public class UserId extends UUIDBased implements EntityId { @JsonCreator @@ -33,7 +34,7 @@ public class UserId extends UUIDBased implements EntityId { return new UserId(UUID.fromString(userId)); } - @Schema(required = true, description = "string", example = "USER", allowableValues = "USER") + @Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "string", example = "USER", allowableValues = "USER") @Override public EntityType getEntityType() { return EntityType.USER; diff --git a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java index 5e2d916397..7d2198f45a 100644 --- a/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java +++ b/common/transport/http/src/main/java/org/thingsboard/server/transport/http/DeviceApiController.java @@ -137,8 +137,7 @@ public class DeviceApiController implements TbTransportService { + MARKDOWN_CODE_BLOCK_START + ATTRIBUTE_PAYLOAD_EXAMPLE + MARKDOWN_CODE_BLOCK_END - + REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public DeferredResult getDeviceAttributes( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @@ -174,13 +173,12 @@ public class DeviceApiController implements TbTransportService { + MARKDOWN_CODE_BLOCK_START + ATTRIBUTE_PAYLOAD_EXAMPLE + MARKDOWN_CODE_BLOCK_END - + REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/attributes", method = RequestMethod.POST) public DeferredResult postDeviceAttributes( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @Parameter(description = "JSON with attribute key-value pairs. See API call description for example.") + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "JSON with attribute key-value pairs. See API call description for example.") @RequestBody String json) { DeferredResult responseWriter = new DeferredResult<>(); transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), @@ -196,8 +194,7 @@ public class DeviceApiController implements TbTransportService { description = "Post time-series data on behalf of device. " + "\n Example of the request: " + TS_PAYLOAD - + REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/telemetry", method = RequestMethod.POST) public DeferredResult postTelemetry( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @@ -222,8 +219,7 @@ public class DeviceApiController implements TbTransportService { + MARKDOWN_CODE_BLOCK_END + "Note: both 'secretKey' and 'durationMs' is optional parameters. " + "In case the secretKey is not specified, the empty string as a default value is used. In case the durationMs is not specified, the system parameter device.claim.duration is used.\n\n" - + REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/claim", method = RequestMethod.POST) public DeferredResult claimDevice( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @@ -244,8 +240,7 @@ public class DeviceApiController implements TbTransportService { description = "Subscribes to RPC commands using http long polling. " + "Deprecated, since long polling is resource and network consuming. " + "Consider using MQTT or CoAP protocol for light-weight real-time updates. \n\n" + - REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public DeferredResult subscribeToCommands( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @@ -268,15 +263,14 @@ public class DeviceApiController implements TbTransportService { @Operation(summary = "Reply to RPC commands (replyToCommand)", description = "Replies to server originated RPC command identified by 'requestId' parameter. The response is arbitrary JSON.\n\n" + - REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/rpc/{requestId}", method = RequestMethod.POST) public DeferredResult replyToCommand( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, @Parameter(description = "RPC request id from the incoming RPC request", required = true , schema = @Schema(defaultValue = "123")) @PathVariable("requestId") Integer requestId, - @Parameter(description = "Reply to the RPC request, JSON. For example: {\"status\":\"success\"}", required = true) + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Reply to the RPC request, JSON. For example: {\"status\":\"success\"}", required = true) @RequestBody String json) { DeferredResult responseWriter = new DeferredResult(); transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), @@ -296,13 +290,12 @@ public class DeviceApiController implements TbTransportService { MARKDOWN_CODE_BLOCK_START + "{\"result\": 4}" + MARKDOWN_CODE_BLOCK_END + - REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/rpc", method = RequestMethod.POST) public DeferredResult postRpcRequest( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @PathVariable("deviceToken") String deviceToken, - @Parameter(description = "The RPC request JSON", required = true) + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The RPC request JSON", required = true) @RequestBody String json) { DeferredResult responseWriter = new DeferredResult(); transportContext.getTransportService().process(DeviceTransportType.DEFAULT, ValidateDeviceTokenRequestMsg.newBuilder().setToken(deviceToken).build(), @@ -324,8 +317,7 @@ public class DeviceApiController implements TbTransportService { description = "Subscribes to client and shared scope attribute updates using http long polling. " + "Deprecated, since long polling is resource and network consuming. " + "Consider using MQTT or CoAP protocol for light-weight real-time updates. \n\n" + - REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/attributes/updates", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public DeferredResult subscribeToAttributes( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @@ -356,8 +348,7 @@ public class DeviceApiController implements TbTransportService { "Optional 'chunk' and 'size' parameters may be used to download the firmware in chunks. " + "For example, device may request first 16 KB of firmware using 'chunk'=0 and 'size'=16384. " + "Next 16KB using 'chunk'=1 and 'size'=16384. The last chunk should have less bytes then requested using 'size' parameter. \n\n" + - REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/firmware", method = RequestMethod.GET) public DeferredResult getFirmware( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @@ -383,8 +374,7 @@ public class DeviceApiController implements TbTransportService { "Optional 'chunk' and 'size' parameters may be used to download the software in chunks. " + "For example, device may request first 16 KB of software using 'chunk'=0 and 'size'=16384. " + "Next 16KB using 'chunk'=1 and 'size'=16384. The last chunk should have less bytes then requested using 'size' parameter. \n\n" + - REQUIRE_ACCESS_TOKEN, - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + REQUIRE_ACCESS_TOKEN) @RequestMapping(value = "/{deviceToken}/software", method = RequestMethod.GET) public DeferredResult getSoftware( @Parameter(description = ACCESS_TOKEN_PARAM_DESCRIPTION, required = true , schema = @Schema(defaultValue = "YOUR_DEVICE_ACCESS_TOKEN")) @@ -418,12 +408,10 @@ public class DeviceApiController implements TbTransportService { " \"credentialsType\":\"ACCESS_TOKEN\",\n" + " \"credentialsValue\":\"DEVICE_ACCESS_TOKEN\",\n" + " \"status\":\"SUCCESS\"\n" + - "}" + MARKDOWN_CODE_BLOCK_END - , - responses = @ApiResponse(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE))) + "}" + MARKDOWN_CODE_BLOCK_END) @RequestMapping(value = "/provision", method = RequestMethod.POST) public DeferredResult provisionDevice( - @Parameter(description = "JSON with provision request. See API call description for example.") + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "JSON with provision request. See API call description for example.") @RequestBody String json) { DeferredResult responseWriter = new DeferredResult<>(); transportContext.getTransportService().process(JsonConverter.convertToProvisionRequestMsg(json), diff --git a/pom.xml b/pom.xml index a9b7efc653..d2450e0a65 100755 --- a/pom.xml +++ b/pom.xml @@ -92,8 +92,8 @@ 4.8.0 3.0.0-M9 3.0.2 - 2.1.0 - 2.2.9 + 2.4.0TB + 2.2.20 0.7 1.18.2 1.69 @@ -111,7 +111,7 @@ 3.2.0 4.1.1 2.7.7 - 2.0 + 2.2 1.11.747 1.105.0 2.1.0 @@ -1775,7 +1775,7 @@ ${curator.version} - org.springdoc + org.thingsboard springdoc-openapi-starter-webmvc-ui ${springdoc-swagger.version} From 8a58fd49b544d5de63038d87df5e8092f40df4b7 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Mon, 25 Mar 2024 11:28:59 +0200 Subject: [PATCH 381/397] Fix import in DefaultEntityServiceRegistry --- .../server/dao/entity/DefaultEntityServiceRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java b/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java index ed0f14ad6d..8202d49db8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityServiceRegistry.java @@ -15,12 +15,12 @@ */ package org.thingsboard.server.dao.entity; +import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; -import javax.annotation.PostConstruct; import java.util.HashMap; import java.util.List; import java.util.Map; From bec63ab1bf64486128e09ffc72dee564664f694e Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 25 Mar 2024 12:28:04 +0200 Subject: [PATCH 382/397] Swagger doc improvement. --- .../org/thingsboard/server/controller/DashboardController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java index dda88eceb6..013575361d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DashboardController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DashboardController.java @@ -176,7 +176,7 @@ public class DashboardController extends BaseController { @RequestMapping(value = "/dashboard", method = RequestMethod.POST) @ResponseBody public Dashboard saveDashboard( - @Parameter(description = "A JSON value representing the dashboard.") + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the dashboard.") @RequestBody Dashboard dashboard) throws Exception { dashboard.setTenantId(getTenantId()); checkEntity(dashboard.getId(), dashboard, Resource.DASHBOARD); From 8a890a451218f6e9615899cba09fc96c5dd05391 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 25 Mar 2024 12:45:28 +0200 Subject: [PATCH 383/397] Fix compilation error --- .../server/dao/sql/alarm/JpaAlarmCommentDaoTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java index f6ef6e8940..037377dc7a 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmCommentDaoTest.java @@ -81,7 +81,7 @@ public class JpaAlarmCommentDaoTest extends AbstractJpaDaoTest { private void saveAlarmComment(UUID id, UUID alarmId, UUID userId, AlarmCommentType type) { AlarmComment alarmComment = new AlarmComment(); alarmComment.setId(new AlarmCommentId(id)); - alarmComment.setAlarmId(TenantId.fromUUID(alarmId)); + alarmComment.setAlarmId(new AlarmId(alarmId)); alarmComment.setUserId(new UserId(userId)); alarmComment.setType(type); alarmComment.setComment(JacksonUtil.newObjectNode().put("text", RandomStringUtils.randomAlphanumeric(10))); From 2e20ad6dc659aaeb7aa38d683725e23761ca88fb Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Mon, 25 Mar 2024 12:51:58 +0200 Subject: [PATCH 384/397] Add tenantId tag to Rule Engine consumer stats --- .../queue/TbRuleEngineConsumerStats.java | 21 ++++++++++--------- .../common/stats/DefaultStatsFactory.java | 14 +++++++++---- .../server/common/stats/StatsFactory.java | 4 +++- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/TbRuleEngineConsumerStats.java b/application/src/main/java/org/thingsboard/server/service/queue/TbRuleEngineConsumerStats.java index c860a00237..5479677f39 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/TbRuleEngineConsumerStats.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/TbRuleEngineConsumerStats.java @@ -18,7 +18,6 @@ package org.thingsboard.server.service.queue; import io.micrometer.core.instrument.Timer; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.queue.Queue; import org.thingsboard.server.common.msg.queue.RuleEngineException; import org.thingsboard.server.common.stats.StatsCounter; import org.thingsboard.server.common.stats.StatsFactory; @@ -45,6 +44,7 @@ public class TbRuleEngineConsumerStats { public static final String FAILED_MSGS = "failedMsgs"; public static final String SUCCESSFUL_ITERATIONS = "successfulIterations"; public static final String FAILED_ITERATIONS = "failedIterations"; + public static final String TENANT_ID_TAG = "tenantId"; private final StatsFactory statsFactory; @@ -73,14 +73,15 @@ public class TbRuleEngineConsumerStats { this.statsFactory = statsFactory; String statsKey = StatsType.RULE_ENGINE.getName() + "." + queueName; - this.totalMsgCounter = statsFactory.createStatsCounter(statsKey, TOTAL_MSGS); - this.successMsgCounter = statsFactory.createStatsCounter(statsKey, SUCCESSFUL_MSGS); - this.timeoutMsgCounter = statsFactory.createStatsCounter(statsKey, TIMEOUT_MSGS); - this.failedMsgCounter = statsFactory.createStatsCounter(statsKey, FAILED_MSGS); - this.tmpTimeoutMsgCounter = statsFactory.createStatsCounter(statsKey, TMP_TIMEOUT); - this.tmpFailedMsgCounter = statsFactory.createStatsCounter(statsKey, TMP_FAILED); - this.successIterationsCounter = statsFactory.createStatsCounter(statsKey, SUCCESSFUL_ITERATIONS); - this.failedIterationsCounter = statsFactory.createStatsCounter(statsKey, FAILED_ITERATIONS); + String tenant = tenantId == null || tenantId.isSysTenantId() ? "system" : tenantId.toString(); + this.totalMsgCounter = statsFactory.createStatsCounter(statsKey, TOTAL_MSGS, TENANT_ID_TAG, tenant); + this.successMsgCounter = statsFactory.createStatsCounter(statsKey, SUCCESSFUL_MSGS, TENANT_ID_TAG, tenant); + this.timeoutMsgCounter = statsFactory.createStatsCounter(statsKey, TIMEOUT_MSGS, TENANT_ID_TAG, tenant); + this.failedMsgCounter = statsFactory.createStatsCounter(statsKey, FAILED_MSGS, TENANT_ID_TAG, tenant); + this.tmpTimeoutMsgCounter = statsFactory.createStatsCounter(statsKey, TMP_TIMEOUT, TENANT_ID_TAG, tenant); + this.tmpFailedMsgCounter = statsFactory.createStatsCounter(statsKey, TMP_FAILED, TENANT_ID_TAG, tenant); + this.successIterationsCounter = statsFactory.createStatsCounter(statsKey, SUCCESSFUL_ITERATIONS, TENANT_ID_TAG, tenant); + this.failedIterationsCounter = statsFactory.createStatsCounter(statsKey, FAILED_ITERATIONS, TENANT_ID_TAG, tenant); counters.add(totalMsgCounter); counters.add(successMsgCounter); @@ -93,7 +94,7 @@ public class TbRuleEngineConsumerStats { counters.add(failedIterationsCounter); } - public Timer getTimer(TenantId tenantId, String status){ + public Timer getTimer(TenantId tenantId, String status) { return tenantMsgProcessTimers.computeIfAbsent(tenantId, id -> statsFactory.createTimer(StatsType.RULE_ENGINE.getName() + "." + queueName, "tenantId", tenantId.getId().toString(), diff --git a/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java b/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java index a6ec01d089..e3ef373014 100644 --- a/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java +++ b/common/stats/src/main/java/org/thingsboard/server/common/stats/DefaultStatsFactory.java @@ -19,6 +19,7 @@ import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tags; import io.micrometer.core.instrument.Timer; +import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -61,12 +62,17 @@ public class DefaultStatsFactory implements StatsFactory { @Override - public StatsCounter createStatsCounter(String key, String statsName) { + public StatsCounter createStatsCounter(String key, String statsName, String... otherTags) { + String[] tags = new String[]{STATS_NAME_TAG, statsName}; + if (otherTags.length > 0) { + if (otherTags.length % 2 != 0) { + throw new IllegalArgumentException("Invalid tags array size"); + } + tags = ArrayUtils.addAll(tags, otherTags); + } return new StatsCounter( new AtomicInteger(0), - metricsEnabled ? - meterRegistry.counter(key, STATS_NAME_TAG, statsName) - : STUB_COUNTER, + metricsEnabled ? meterRegistry.counter(key, tags) : STUB_COUNTER, statsName ); } diff --git a/common/stats/src/main/java/org/thingsboard/server/common/stats/StatsFactory.java b/common/stats/src/main/java/org/thingsboard/server/common/stats/StatsFactory.java index 8e6989016b..b9bf0b97fb 100644 --- a/common/stats/src/main/java/org/thingsboard/server/common/stats/StatsFactory.java +++ b/common/stats/src/main/java/org/thingsboard/server/common/stats/StatsFactory.java @@ -18,7 +18,8 @@ package org.thingsboard.server.common.stats; import io.micrometer.core.instrument.Timer; public interface StatsFactory { - StatsCounter createStatsCounter(String key, String statsName); + + StatsCounter createStatsCounter(String key, String statsName, String... otherTags); DefaultCounter createDefaultCounter(String key, String... tags); @@ -27,4 +28,5 @@ public interface StatsFactory { MessagesStats createMessagesStats(String key); Timer createTimer(String key, String... tags); + } From 6890b18dfb6d73dee43b7d162f02e4a3338a88bf Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 25 Mar 2024 13:10:58 +0200 Subject: [PATCH 385/397] Swagger doc improvement. --- .../thingsboard/server/controller/AlarmCommentController.java | 2 +- .../org/thingsboard/server/controller/AlarmController.java | 2 +- .../org/thingsboard/server/controller/AssetController.java | 2 +- .../org/thingsboard/server/controller/CustomerController.java | 2 +- .../org/thingsboard/server/controller/DeviceController.java | 2 +- .../thingsboard/server/controller/TelemetryController.java | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java index 65f5c1c543..15918f0a08 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmCommentController.java @@ -74,7 +74,7 @@ public class AlarmCommentController extends BaseController { @RequestMapping(value = "/alarm/{alarmId}/comment", method = RequestMethod.POST) @ResponseBody public AlarmComment saveAlarmComment(@Parameter(description = ALARM_ID_PARAM_DESCRIPTION) - @PathVariable(ALARM_ID) String strAlarmId, @Parameter(description = "A JSON value representing the comment.") @RequestBody AlarmComment alarmComment) throws ThingsboardException { + @PathVariable(ALARM_ID) String strAlarmId, @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the comment.") @RequestBody AlarmComment alarmComment) throws ThingsboardException { checkParameter(ALARM_ID, strAlarmId); AlarmId alarmId = new AlarmId(toUUID(strAlarmId)); Alarm alarm = checkAlarmInfoId(alarmId, Operation.WRITE); diff --git a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java index ba22663467..e78313f6d8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AlarmController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AlarmController.java @@ -143,7 +143,7 @@ public class AlarmController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/alarm", method = RequestMethod.POST) @ResponseBody - public Alarm saveAlarm(@Parameter(description = "A JSON value representing the alarm.") @RequestBody Alarm alarm) throws ThingsboardException { + public Alarm saveAlarm(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the alarm.") @RequestBody Alarm alarm) throws ThingsboardException { alarm.setTenantId(getTenantId()); checkNotNull(alarm.getOriginator()); checkEntity(alarm.getId(), alarm, Resource.ALARM); diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 751f3fd812..8c03d34e8e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -139,7 +139,7 @@ public class AssetController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset", method = RequestMethod.POST) @ResponseBody - public Asset saveAsset(@Parameter(description = "A JSON value representing the asset.") @RequestBody Asset asset) throws Exception { + public Asset saveAsset(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the asset.") @RequestBody Asset asset) throws Exception { asset.setTenantId(getTenantId()); checkEntity(asset.getId(), asset, Resource.ASSET); return tbAssetService.save(asset, getCurrentUser()); diff --git a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java index c24c345f76..a46cbe7dba 100644 --- a/application/src/main/java/org/thingsboard/server/controller/CustomerController.java +++ b/application/src/main/java/org/thingsboard/server/controller/CustomerController.java @@ -130,7 +130,7 @@ public class CustomerController extends BaseController { @PreAuthorize("hasAuthority('TENANT_ADMIN')") @RequestMapping(value = "/customer", method = RequestMethod.POST) @ResponseBody - public Customer saveCustomer(@Parameter(description = "A JSON value representing the customer.") @RequestBody Customer customer) throws Exception { + public Customer saveCustomer(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the customer.") @RequestBody Customer customer) throws Exception { customer.setTenantId(getTenantId()); checkEntity(customer.getId(), customer, Resource.CUSTOMER); return tbCustomerService.save(customer, getCurrentUser()); diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 23518c96bf..fedbd48503 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -177,7 +177,7 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device", method = RequestMethod.POST) @ResponseBody - public Device saveDevice(@Parameter(description = "A JSON value representing the device.") @RequestBody Device device, + public Device saveDevice(@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "A JSON value representing the device.") @RequestBody Device device, @Parameter(description = "Optional value of the device credentials to be used during device creation. " + "If omitted, access token will be auto-generated.") @RequestParam(name = "accessToken", required = false) String accessToken) throws Exception { device.setTenantId(getCurrentUser().getTenantId()); diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index 4e28caa3ba..c73ac09cf1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -427,7 +427,7 @@ public class TelemetryController extends BaseController { @Parameter(description = ENTITY_TYPE_PARAM_DESCRIPTION, required = true, schema = @Schema(defaultValue = "DEVICE")) @PathVariable("entityType") String entityType, @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @Parameter(description = TELEMETRY_SCOPE_DESCRIPTION, required = true, schema = @Schema(allowableValues = "ANY")) @PathVariable("scope")String scope, - @Parameter(description = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody String requestBody) throws ThingsboardException { + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody String requestBody) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveTelemetry(getTenantId(), entityId, requestBody, 0L); } @@ -452,7 +452,7 @@ public class TelemetryController extends BaseController { @Parameter(description = ENTITY_ID_PARAM_DESCRIPTION, required = true) @PathVariable("entityId") String entityIdStr, @Parameter(description = TELEMETRY_SCOPE_DESCRIPTION, required = true, schema = @Schema(allowableValues = "ANY")) @PathVariable("scope")AttributeScope scope, @Parameter(description = "A long value representing TTL (Time to Live) parameter.", required = true)@PathVariable("ttl")Long ttl, - @Parameter(description = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody String requestBody) throws ThingsboardException { + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = TELEMETRY_JSON_REQUEST_DESCRIPTION, required = true)@RequestBody String requestBody) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndId(entityType, entityIdStr); return saveTelemetry(getTenantId(), entityId, requestBody, ttl); } From 753bacd2dce7b58bcbe45596da59098a1fb8fc32 Mon Sep 17 00:00:00 2001 From: rusikv Date: Mon, 25 Mar 2024 16:31:56 +0200 Subject: [PATCH 386/397] UI: oauth settings style improvement --- .../pages/admin/oauth2-settings.component.html | 8 ++++---- .../pages/admin/oauth2-settings.component.scss | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html index acaf58895e..2e85f8b54b 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html @@ -29,8 +29,8 @@
    -
    -
    +
    +
    {{ 'admin.oauth2.enable' | translate }} @@ -38,9 +38,9 @@ {{ 'admin.oauth2.edge-enable' | translate }}
    -
    +
    -
    +
    diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.scss b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.scss index a476f438e3..639fb877f2 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.scss +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.scss @@ -13,7 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@import '../../../../../scss/constants'; + :host{ + .gap-xs-12 { + @media #{$mat-xs} { + gap: 12px; + } + } + + .mdc-evolution-chip-set .mdc-evolution-chip { + margin-top: 0; + margin-bottom: 0; + } + .checkbox-row { margin-top: 1em; } @@ -31,7 +44,7 @@ } .container{ - margin-bottom: 1em; + margin-bottom: 16px; .tb-highlight{ margin: 0; From 2efd411a36d835498f59191774f24d8202214c7b Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Mon, 25 Mar 2024 15:34:57 +0100 Subject: [PATCH 387/397] Check alarm status node: log severity DEBUG for "Failed to parse alarm" for known runtime exceptions. The ERROR severity will fire only on unexpected exception types. This will prevent flooding the error logger --- .../engine/filter/TbCheckAlarmStatusNode.java | 9 +++++++-- .../filter/TbCheckAlarmStatusNodeTest.java | 13 +++++++++++++ .../src/test/resources/logback-test.xml | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 rule-engine/rule-engine-components/src/test/resources/logback-test.xml 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 08a1776ba3..8d7f12d14d 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 @@ -32,6 +32,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; import javax.annotation.Nullable; +import java.util.Objects; @Slf4j @RuleNode( @@ -57,7 +58,7 @@ public class TbCheckAlarmStatusNode implements TbNode { public void onMsg(TbContext ctx, TbMsg msg) throws TbNodeException { try { Alarm alarm = JacksonUtil.fromString(msg.getData(), Alarm.class); - + Objects.requireNonNull(alarm, "alarm is null"); ListenableFuture latest = ctx.getAlarmService().findAlarmByIdAsync(ctx.getTenantId(), alarm.getId()); Futures.addCallback(latest, new FutureCallback<>() { @@ -78,7 +79,11 @@ public class TbCheckAlarmStatusNode implements TbNode { } }, ctx.getDbCallbackExecutor()); } catch (Exception e) { - log.error("Failed to parse alarm: [{}]", msg.getData()); + if (e instanceof IllegalArgumentException || e instanceof NullPointerException) { + log.debug("Failed to parse alarm: [{}] error [{}]", msg.getData(), e.getMessage()); + } else { + log.error("Failed to parse alarm: [{}]", msg.getData(), e); + } throw new TbNodeException(e); } } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java index c79f962818..1fc0b84172 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java @@ -38,6 +38,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -158,6 +159,18 @@ class TbCheckAlarmStatusNodeTest { assertThat(value).isInstanceOf(TbNodeException.class).hasMessage("No such alarm found."); } + @Test + void givenUnparseableAlarm_whenOnMsg_then_Failure() { + String msgData = "{\"Number\":1113718,\"id\":8.1}"; + TbMsg msg = getTbMsg(msgData); + + assertThatThrownBy(() -> node.onMsg(ctx, msg)) + .as("onMsg") + .isInstanceOf(TbNodeException.class) + .hasCauseInstanceOf(IllegalArgumentException.class) + .hasMessage("java.lang.IllegalArgumentException: The given string value cannot be transformed to Json object: {\"Number\":1113718,\"id\":8.1}"); + } + private TbMsg getTbMsg(String msgData) { return TbMsg.newMsg(TbMsgType.POST_ATTRIBUTES_REQUEST, DEVICE_ID, TbMsgMetaData.EMPTY, msgData); } diff --git a/rule-engine/rule-engine-components/src/test/resources/logback-test.xml b/rule-engine/rule-engine-components/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..0695fe1e1a --- /dev/null +++ b/rule-engine/rule-engine-components/src/test/resources/logback-test.xml @@ -0,0 +1,16 @@ + + + + + + %d{ISO8601} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + From add2bea56a9cd5a54fdfe7dc16b78fde37e4c9c2 Mon Sep 17 00:00:00 2001 From: Sergey Matvienko Date: Tue, 26 Mar 2024 09:04:37 +0100 Subject: [PATCH 388/397] Check alarm status node: added tenant and ruleChainName to the log to make a log useful in multi-tenant deployments --- .../rule/engine/filter/TbCheckAlarmStatusNode.java | 4 ++-- .../rule/engine/filter/TbCheckAlarmStatusNodeTest.java | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) 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 8d7f12d14d..1d2f665376 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 @@ -80,9 +80,9 @@ public class TbCheckAlarmStatusNode implements TbNode { }, ctx.getDbCallbackExecutor()); } catch (Exception e) { if (e instanceof IllegalArgumentException || e instanceof NullPointerException) { - log.debug("Failed to parse alarm: [{}] error [{}]", msg.getData(), e.getMessage()); + log.debug("[{}][{}] Failed to parse alarm: [{}] error [{}]", ctx.getTenantId(), ctx.getRuleChainName(), msg.getData(), e.getMessage()); } else { - log.error("Failed to parse alarm: [{}]", msg.getData(), e); + log.error("[{}][{}] Failed to parse alarm: [{}]", ctx.getTenantId(), ctx.getRuleChainName(), msg.getData(), e); } throw new TbNodeException(e); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java index 1fc0b84172..5b71db5dfb 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNodeTest.java @@ -41,6 +41,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.willReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -163,6 +164,7 @@ class TbCheckAlarmStatusNodeTest { void givenUnparseableAlarm_whenOnMsg_then_Failure() { String msgData = "{\"Number\":1113718,\"id\":8.1}"; TbMsg msg = getTbMsg(msgData); + willReturn("Default Rule Chain").given(ctx).getRuleChainName(); assertThatThrownBy(() -> node.onMsg(ctx, msg)) .as("onMsg") From 646c8679a662c56f6c33dc2908c4af6a8902ec81 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Tue, 26 Mar 2024 12:19:21 +0200 Subject: [PATCH 389/397] Fix oauth support: send to edge, when propagate to edge is false --- .../service/edge/EdgeEventSourcingListener.java | 3 --- .../oauth2/OAuth2MsgConstructor.java | 1 + .../edge/rpc/fetch/OAuth2EdgeEventFetcher.java | 7 +++---- .../thingsboard/server/edge/OAuth2EdgeTest.java | 17 +++++++++-------- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java index b48b4ac3b2..6c2f81a200 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java @@ -160,9 +160,6 @@ public class EdgeEventSourcingListener { private boolean isValidSaveEntityEventForEdgeProcessing(SaveEntityEvent event) { Object entity = event.getEntity(); Object oldEntity = event.getOldEntity(); - if (entity instanceof OAuth2Info oAuth2Info) { - return oAuth2Info.isEdgeEnabled(); - } switch (event.getEntityId().getEntityType()) { case RULE_CHAIN: if (entity instanceof RuleChain ruleChain) { diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/oauth2/OAuth2MsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/oauth2/OAuth2MsgConstructor.java index a141e618f4..c628b042a2 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/oauth2/OAuth2MsgConstructor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/oauth2/OAuth2MsgConstructor.java @@ -28,4 +28,5 @@ public class OAuth2MsgConstructor { public OAuth2UpdateMsg constructOAuth2UpdateMsg(OAuth2Info oAuth2Info) { return OAuth2UpdateMsg.newBuilder().setEntity(JacksonUtil.toString(oAuth2Info)).build(); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java index e4ef6cfdb6..4412f91183 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java @@ -47,11 +47,10 @@ public class OAuth2EdgeEventFetcher implements EdgeEventFetcher { public PageData fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) { List result = new ArrayList<>(); OAuth2Info oAuth2Info = oAuth2Service.findOAuth2Info(); - if (oAuth2Info.isEdgeEnabled()) { - result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.OAUTH2, - EdgeEventActionType.ADDED, null, JacksonUtil.valueToTree(oAuth2Info))); - } + result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.OAUTH2, + EdgeEventActionType.ADDED, null, JacksonUtil.valueToTree(oAuth2Info))); // returns PageData object to be in sync with other fetchers return new PageData<>(result, 1, result.size(), false); } + } diff --git a/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java index f10338b37b..b3cc133f4b 100644 --- a/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java @@ -46,12 +46,6 @@ public class OAuth2EdgeTest extends AbstractEdgeTest { edgeImitator.expectMessageAmount(1); OAuth2Info oAuth2Info = createDefaultOAuth2Info(); oAuth2Info = doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class); - Assert.assertFalse(edgeImitator.waitForMessages(10)); - - // enable edge support - edgeImitator.expectMessageAmount(1); - oAuth2Info.setEdgeEnabled(true); - oAuth2Info = doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class); Assert.assertTrue(edgeImitator.waitForMessages()); AbstractMessage latestMessage = edgeImitator.getLatestMessage(); Assert.assertTrue(latestMessage instanceof OAuth2UpdateMsg); @@ -59,16 +53,23 @@ public class OAuth2EdgeTest extends AbstractEdgeTest { OAuth2Info result = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true); Assert.assertEquals(oAuth2Info, result); - // disable oauth suppor + // disable oauth support + edgeImitator.expectMessageAmount(1); oAuth2Info.setEnabled(false); oAuth2Info.setEdgeEnabled(false); doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class); + Assert.assertTrue(edgeImitator.waitForMessages()); + latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof OAuth2UpdateMsg); + oAuth2UpdateMsg = (OAuth2UpdateMsg) latestMessage; + result = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true); + Assert.assertEquals(oAuth2Info, result); loginTenantAdmin(); } private OAuth2Info createDefaultOAuth2Info() { - return new OAuth2Info(true, false, Lists.newArrayList( + return new OAuth2Info(true, true, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("domain").scheme(SchemeType.MIXED).build() From a7eee8fe6268f851081f18f8374310c7be54a9bc Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 26 Mar 2024 13:01:03 +0200 Subject: [PATCH 390/397] UI: Time-series chart dark mode improvement --- .../home/components/widget/lib/chart/time-series-chart.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 462825087e..65a323e4b6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -139,7 +139,8 @@ export class TbTimeSeriesChart { this.settings = mergeDeep({} as TimeSeriesChartSettings, timeSeriesChartDefaultSettings, this.inputSettings as TimeSeriesChartSettings); - const dashboardPageElement = this.ctx.$containerParent.parents('.tb-dashboard-page'); + const $dashboardPageElement = this.ctx.$containerParent.parents('.tb-dashboard-page'); + const dashboardPageElement = $($dashboardPageElement[$dashboardPageElement.length-1]); this.darkMode = this.settings.darkMode || dashboardPageElement.hasClass('dark'); this.setupYAxes(); this.setupData(); From 8a0de018a3d5340f24a06552393c4c7385a8ac2e Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 26 Mar 2024 13:02:11 +0200 Subject: [PATCH 391/397] UI: Fixed draggeble marker and not draw new poligon --- ui-ngx/package.json | 22 +++++++++++----------- ui-ngx/yarn.lock | 34 +++++++++++++++++----------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/ui-ngx/package.json b/ui-ngx/package.json index a74a1f2953..46cd5dd3cd 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -30,7 +30,7 @@ "@date-io/date-fns": "1.3.7", "@flowjs/flow.js": "^2.14.1", "@flowjs/ngx-flow": "~0.6.0", - "@geoman-io/leaflet-geoman-free": "^2.13.0", + "@geoman-io/leaflet-geoman-free": "2.14.2", "@iplab/ngx-color-picker": "^15.0.2", "@juggle/resize-observer": "^3.4.0", "@mat-datetimepicker/core": "~11.0.3", @@ -67,11 +67,11 @@ "jstree": "^3.3.15", "jstree-bootstrap-theme": "^1.0.1", "jszip": "^3.10.1", - "leaflet": "~1.8.0", - "leaflet-polylinedecorator": "^1.6.0", - "leaflet-providers": "^1.13.0", - "leaflet.gridlayer.googlemutant": "^0.13.5", - "leaflet.markercluster": "^1.5.3", + "leaflet": "1.8.0", + "leaflet-polylinedecorator": "1.6.0", + "leaflet-providers": "1.13.0", + "leaflet.gridlayer.googlemutant": "0.14.1", + "leaflet.markercluster": "1.5.3", "libphonenumber-js": "^1.10.4", "marked": "^4.0.17", "moment": "^2.29.4", @@ -130,11 +130,11 @@ "@types/jasminewd2": "^2.0.10", "@types/jquery": "^3.5.16", "@types/js-beautify": "^1.13.3", - "@types/leaflet": "~1.8.0", - "@types/leaflet-polylinedecorator": "^1.6.1", - "@types/leaflet-providers": "^1.2.1", - "@types/leaflet.gridlayer.googlemutant": "^0.4.6", - "@types/leaflet.markercluster": "^1.5.1", + "@types/leaflet": "1.8.0", + "@types/leaflet-polylinedecorator": "1.6.4", + "@types/leaflet-providers": "1.2.4", + "@types/leaflet.gridlayer.googlemutant": "0.4.9", + "@types/leaflet.markercluster": "1.5.4", "@types/lodash": "^4.14.192", "@types/marked": "^4.0.8", "@types/node": "~18.15.11", diff --git a/ui-ngx/yarn.lock b/ui-ngx/yarn.lock index ca5c179ad5..33362767bd 100644 --- a/ui-ngx/yarn.lock +++ b/ui-ngx/yarn.lock @@ -1582,10 +1582,10 @@ dependencies: tslib "^2.2.0" -"@geoman-io/leaflet-geoman-free@^2.13.0": - version "2.16.0" - resolved "https://registry.yarnpkg.com/@geoman-io/leaflet-geoman-free/-/leaflet-geoman-free-2.16.0.tgz#c8a92fcc2cdd5770ebf43f8ef9f03cc8ef842359" - integrity sha512-BnKAAoTXraWVFfhX/0gT/iBgAz1BPfpbdQ9dJamEFI4lIku9UNXXluu/E0k7YkZETq0tENX2GPnKLB4p+VgrSw== +"@geoman-io/leaflet-geoman-free@2.14.2": + version "2.14.2" + resolved "https://registry.yarnpkg.com/@geoman-io/leaflet-geoman-free/-/leaflet-geoman-free-2.14.2.tgz#c84c2115c263f34d11dc0b43859551639fe3d56b" + integrity sha512-6lIyG8RvSVdFjVjiQgBPyNASjymSyqzsiUeBW0pA+q41lB5fAg4SDC6SfJvWdEyDHa81Jb5FWjUkCc9O+u0gbg== dependencies: "@turf/boolean-contains" "^6.5.0" "@turf/kinks" "^6.5.0" @@ -3079,28 +3079,28 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/leaflet-polylinedecorator@^1.6.1": +"@types/leaflet-polylinedecorator@1.6.4": version "1.6.4" resolved "https://registry.yarnpkg.com/@types/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.4.tgz#2270b84585bd28bbf1fef237be8480196c44ac06" integrity sha512-meH/jC58Drt/9aqLhuzMCUQjHgMTud+UuQBK5gT6E8M6OfM/rftz/VgvdxOCCAQC9isrp4pqahDgEswesb5X3A== dependencies: "@types/leaflet" "*" -"@types/leaflet-providers@^1.2.1": +"@types/leaflet-providers@1.2.4": version "1.2.4" resolved "https://registry.yarnpkg.com/@types/leaflet-providers/-/leaflet-providers-1.2.4.tgz#284e8a197d4c2dbfeda436842e03b2adb502be16" integrity sha512-4wYEpreixp+G5t510s202eQ5eubOmxHevIfCNrzUZbzp50XQsC9lSetX7MnPl3ANRJnUBbCWOzZ9EQFiH0Jm+g== dependencies: "@types/leaflet" "*" -"@types/leaflet.gridlayer.googlemutant@^0.4.6": +"@types/leaflet.gridlayer.googlemutant@0.4.9": version "0.4.9" resolved "https://registry.yarnpkg.com/@types/leaflet.gridlayer.googlemutant/-/leaflet.gridlayer.googlemutant-0.4.9.tgz#9090ddf4578ce631d22b8aafc5ed12525b4fbf90" integrity sha512-u/5Avs1KKkeABRDixGbGp2ldFs67+fYIATpkvvFgN+LQPNfq7dFd5adkksshiQBfYJ4SaQg1VJgN2dNirIC0aQ== dependencies: "@types/leaflet" "*" -"@types/leaflet.markercluster@^1.5.1": +"@types/leaflet.markercluster@1.5.4": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.4.tgz#2ab43417cf3f6a42d0f1baf4e1c8f659cf1dc3a1" integrity sha512-tfMP8J62+wfsVLDLGh5Zh1JZxijCaBmVsMAX78MkLPwvPitmZZtSin5aWOVRhZrCS+pEOZwNzexbfWXlY+7yjg== @@ -3114,7 +3114,7 @@ dependencies: "@types/geojson" "*" -"@types/leaflet@~1.8.0": +"@types/leaflet@1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@types/leaflet/-/leaflet-1.8.0.tgz#dc92d3e868fb6d5067b4b59fa08cd4441f84fabe" integrity sha512-+sXFmiJTFdhaXXIGFlV5re9AdqtAODoXbGAvxx02e5SHXL3ir7ClP5J7pahO8VmzKY3dth4RUS1nf2BTT+DW1A== @@ -7750,14 +7750,14 @@ lcov-parse@1.0.0: resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" integrity sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ== -leaflet-polylinedecorator@^1.6.0: +leaflet-polylinedecorator@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/leaflet-polylinedecorator/-/leaflet-polylinedecorator-1.6.0.tgz#9ef79fd1b5302d67b72efe959a8ecd2553f27266" integrity sha512-kn3krmZRetgvN0wjhgYL8kvyLS0tUogAl0vtHuXQnwlYNjbl7aLQpkoFUo8UB8gVZoB0dhI4Tb55VdTJAcYzzQ== dependencies: leaflet-rotatedmarker "^0.2.0" -leaflet-providers@^1.13.0: +leaflet-providers@1.13.0: version "1.13.0" resolved "https://registry.yarnpkg.com/leaflet-providers/-/leaflet-providers-1.13.0.tgz#10c843a23d5823a65096d40ad53f27029e13434b" integrity sha512-f/sN5wdgBbVA2jcCYzScIfYNxKdn2wBJP9bu+5cRX9Xj6g8Bt1G9Sr8WgJAt/ckIFIc3LVVxCBNFpSCfTuUElg== @@ -7767,17 +7767,17 @@ leaflet-rotatedmarker@^0.2.0: resolved "https://registry.yarnpkg.com/leaflet-rotatedmarker/-/leaflet-rotatedmarker-0.2.0.tgz#4467f49f98d1bfd56959bd9c6705203dd2601277" integrity sha512-yc97gxLXwbZa+Gk9VCcqI0CkvIBC9oNTTjFsHqq4EQvANrvaboib4UdeQLyTnEqDpaXHCqzwwVIDHtvz2mUiDg== -leaflet.gridlayer.googlemutant@^0.13.5: - version "0.13.5" - resolved "https://registry.yarnpkg.com/leaflet.gridlayer.googlemutant/-/leaflet.gridlayer.googlemutant-0.13.5.tgz#7182c26f479e726bff8b85a7ebf9d3f44dd3ea57" - integrity sha512-DHUEXpo1t0WZ9tpdLUHHkrTK7LldCXr/gqkV5E/4hHidDJB2srceLLCZj4PV/pl0jPdTkVBT+Lr8nL9EZDB5hw== +leaflet.gridlayer.googlemutant@0.14.1: + version "0.14.1" + resolved "https://registry.yarnpkg.com/leaflet.gridlayer.googlemutant/-/leaflet.gridlayer.googlemutant-0.14.1.tgz#c282209aa1a39eb2f87d8aaa4e9894181c9e20a0" + integrity sha512-/OYxEjmgxO1U1KOhTzg+m8c0b95J0943LU8DXQmdJu/x2f+1Ur78rvEPO2QCS0cmwZ3m6FvE5I3zXnBzJNWRCA== -leaflet.markercluster@^1.5.3: +leaflet.markercluster@1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz#9cdb52a4eab92671832e1ef9899669e80efc4056" integrity sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA== -leaflet@~1.8.0: +leaflet@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.8.0.tgz#4615db4a22a304e8e692cae9270b983b38a2055e" integrity sha512-gwhMjFCQiYs3x/Sf+d49f10ERXaEFCPr+nVTryhAW8DWbMGqJqt9G4XuIaHmFW08zYvhgdzqXGr8AlW8v8dQkA== From 89780d381a86ca61295d84d3d2720172fd3def4d Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 26 Mar 2024 15:31:17 +0200 Subject: [PATCH 392/397] UI: Fixed not opened image gallery when used multiple-gallery-image-input.component.ts --- ...ultiple-gallery-image-input.component.html | 5 +- .../multiple-gallery-image-input.component.ts | 49 ++++++++----------- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.html b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.html index 4a60b29ba9..ea6a4cc603 100644 --- a/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.html +++ b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.html @@ -85,12 +85,11 @@
    - diff --git a/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.ts b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.ts index 260a7667f8..a1183acf88 100644 --- a/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.ts +++ b/ui-ngx/src/app/shared/components/image/multiple-gallery-image-input.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { ChangeDetectorRef, Component, forwardRef, Input, OnDestroy, Renderer2, ViewContainerRef } from '@angular/core'; +import { ChangeDetectorRef, Component, forwardRef, Input, OnDestroy } from '@angular/core'; import { PageComponent } from '@shared/components/page.component'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @@ -24,10 +24,13 @@ import { DndDropEvent } from 'ngx-drag-drop'; import { isUndefined } from '@core/utils'; import { coerceBoolean } from '@shared/decorators/coercion'; import { ImageLinkType } from '@shared/components/image/gallery-image-input.component'; -import { TbPopoverService } from '@shared/components/popover.service'; -import { MatButton } from '@angular/material/button'; -import { ImageGalleryComponent } from '@shared/components/image/image-gallery.component'; -import { prependTbImagePrefixToUrls, removeTbImagePrefixFromUrls } from '@shared/models/resource.models'; +import { + ImageResourceInfo, + prependTbImagePrefixToUrls, + removeTbImagePrefixFromUrls +} from '@shared/models/resource.models'; +import { MatDialog } from '@angular/material/dialog'; +import { ImageGalleryDialogComponent } from '@shared/components/image/image-gallery-dialog.component'; @Component({ selector: 'tb-multiple-gallery-image-input', @@ -66,10 +69,8 @@ export class MultipleGalleryImageInputComponent extends PageComponent implements private propagateChange = null; constructor(protected store: Store, - private cd: ChangeDetectorRef, - private renderer: Renderer2, - private viewContainerRef: ViewContainerRef, - private popoverService: TbPopoverService) { + private dialog: MatDialog, + private cd: ChangeDetectorRef) { super(store); } @@ -130,31 +131,21 @@ export class MultipleGalleryImageInputComponent extends PageComponent implements this.updateModel(); } - toggleGallery($event: Event, browseGalleryButton: MatButton) { + toggleGallery($event: Event) { if ($event) { $event.stopPropagation(); } - const trigger = browseGalleryButton._elementRef.nativeElement; - if (this.popoverService.hasPopover(trigger)) { - this.popoverService.hidePopover(trigger); - } else { - const ctx: any = { - pageMode: false, - popoverMode: true, - mode: 'grid', - selectionMode: true - }; - const imageGalleryPopover = this.popoverService.displayPopover(trigger, this.renderer, - this.viewContainerRef, ImageGalleryComponent, 'top', true, null, - ctx, - {}, - {}, {}, true); - imageGalleryPopover.tbComponentRef.instance.imageSelected.subscribe((image) => { - imageGalleryPopover.hide(); + this.dialog.open(ImageGalleryDialogComponent, { + autoFocus: false, + disableClose: false, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'] + }).afterClosed().subscribe((image) => { + if (image) { this.imageUrls.push(image.link); this.updateModel(); - }); - } + } + }); } imageDragStart(index: number) { From 16d1e353feeb22c51cedd84a703942aec38be134 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Tue, 26 Mar 2024 17:10:34 +0200 Subject: [PATCH 393/397] Fix oauth --- .../edge/EdgeEventSourcingListener.java | 62 ++++++++++--------- .../processor/oauth2/OAuth2EdgeProcessor.java | 1 - .../server/edge/AbstractEdgeTest.java | 15 +++++ .../server/edge/OAuth2EdgeTest.java | 2 + 4 files changed, 49 insertions(+), 31 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java index 6c2f81a200..d975217e1f 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java @@ -160,39 +160,41 @@ public class EdgeEventSourcingListener { private boolean isValidSaveEntityEventForEdgeProcessing(SaveEntityEvent event) { Object entity = event.getEntity(); Object oldEntity = event.getOldEntity(); - switch (event.getEntityId().getEntityType()) { - case RULE_CHAIN: - if (entity instanceof RuleChain ruleChain) { - return RuleChainType.EDGE.equals(ruleChain.getType()); - } - break; - case USER: - if (entity instanceof User user) { - if (Authority.SYS_ADMIN.equals(user.getAuthority())) { - return false; + if (event.getEntityId() != null) { + switch (event.getEntityId().getEntityType()) { + case RULE_CHAIN: + if (entity instanceof RuleChain ruleChain) { + return RuleChainType.EDGE.equals(ruleChain.getType()); + } + break; + case USER: + if (entity instanceof User user) { + if (Authority.SYS_ADMIN.equals(user.getAuthority())) { + return false; + } + if (oldEntity != null) { + User oldUser = (User) oldEntity; + cleanUpUserAdditionalInfo(oldUser); + cleanUpUserAdditionalInfo(user); + return !user.equals(oldUser); + } } - if (oldEntity != null) { - User oldUser = (User) oldEntity; - cleanUpUserAdditionalInfo(oldUser); - cleanUpUserAdditionalInfo(user); - return !user.equals(oldUser); + break; + case OTA_PACKAGE: + if (entity instanceof OtaPackageInfo otaPackageInfo) { + return otaPackageInfo.hasUrl() || otaPackageInfo.isHasData(); } - } - break; - case OTA_PACKAGE: - if (entity instanceof OtaPackageInfo otaPackageInfo) { - return otaPackageInfo.hasUrl() || otaPackageInfo.isHasData(); - } - break; - case ALARM: - if (entity instanceof AlarmApiCallResult || entity instanceof Alarm) { + break; + case ALARM: + if (entity instanceof AlarmApiCallResult || entity instanceof Alarm) { + return false; + } + break; + case TENANT: + return !event.getCreated(); + case API_USAGE_STATE, EDGE: return false; - } - break; - case TENANT: - return !event.getCreated(); - case API_USAGE_STATE, EDGE: - return false; + } } // Default: If the entity doesn't match any of the conditions, consider it as valid. return true; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/oauth2/OAuth2EdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/oauth2/OAuth2EdgeProcessor.java index 1c62ad5de8..ce0600b491 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/oauth2/OAuth2EdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/oauth2/OAuth2EdgeProcessor.java @@ -55,7 +55,6 @@ public class OAuth2EdgeProcessor extends BaseEdgeProcessor { if (oAuth2Info == null) { return Futures.immediateFuture(null); } - EdgeEventType type = EdgeEventType.valueOf(edgeNotificationMsg.getType()); EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); return processActionForAllEdges(tenantId, type, actionType, null, JacksonUtil.toJsonNode(edgeNotificationMsg.getBody()), null); diff --git a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java index 0787d08fa7..e7f664477c 100644 --- a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java @@ -63,6 +63,7 @@ import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.oauth2.OAuth2Info; import org.thingsboard.server.common.data.ota.ChecksumAlgorithm; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.data.page.PageData; @@ -85,6 +86,7 @@ import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg; import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.v1.EdgeConfiguration; +import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg; import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg; import org.thingsboard.server.gen.edge.v1.RuleChainMetadataRequestMsg; import org.thingsboard.server.gen.edge.v1.RuleChainMetadataUpdateMsg; @@ -140,6 +142,7 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { installation(); edgeImitator = new EdgeImitator("localhost", 7070, edge.getRoutingKey(), edge.getSecret()); + edgeImitator.ignoreType(OAuth2UpdateMsg.class); edgeImitator.expectMessageAmount(21); edgeImitator.connect(); @@ -538,6 +541,18 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { Assert.assertTrue(customer.isPublic()); } + private void validateOAuth2() throws Exception { + Optional oAuth2UpdateMsgOpt = edgeImitator.findMessageByType(OAuth2UpdateMsg.class); + Assert.assertTrue(oAuth2UpdateMsgOpt.isPresent()); + OAuth2UpdateMsg oAuth2UpdateMsg = oAuth2UpdateMsgOpt.get(); + OAuth2Info oAuth2Info = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true); + Assert.assertNotNull(oAuth2Info); + OAuth2Info auth2Info = doGet("/api/oauth2/config", OAuth2Info.class); + Assert.assertNotNull(auth2Info); + Assert.assertEquals(oAuth2Info, auth2Info); + testAutoGeneratedCodeByProtobuf(oAuth2UpdateMsg); + } + private void validateSyncCompleted() { Optional syncCompletedMsgOpt = edgeImitator.findMessageByType(SyncCompletedMsg.class); Assert.assertTrue(syncCompletedMsgOpt.isPresent()); diff --git a/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java index b3cc133f4b..b5ed5e788c 100644 --- a/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java @@ -43,6 +43,7 @@ public class OAuth2EdgeTest extends AbstractEdgeTest { loginSysAdmin(); // enable oauth, verify nothing sent to edge + edgeImitator.allowIgnoredTypes(); edgeImitator.expectMessageAmount(1); OAuth2Info oAuth2Info = createDefaultOAuth2Info(); oAuth2Info = doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class); @@ -65,6 +66,7 @@ public class OAuth2EdgeTest extends AbstractEdgeTest { result = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true); Assert.assertEquals(oAuth2Info, result); + edgeImitator.ignoreType(OAuth2UpdateMsg.class); loginTenantAdmin(); } From 11f16dd3e26f3afd0c04b76a01fa75f0fb53e5aa Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 26 Mar 2024 18:01:51 +0200 Subject: [PATCH 394/397] UI: Update echarts dependency to version 5.5.0-TB --- ui-ngx/package.json | 2 +- ui-ngx/patches/echarts+5.5.0.patch | 426 ------------------ .../bar-chart-with-labels-widget.component.ts | 5 +- .../widget/lib/chart/echarts-widget.models.ts | 90 ++-- .../lib/chart/range-chart-widget.component.ts | 5 +- .../lib/chart/time-series-chart.models.ts | 5 +- .../widget/lib/chart/time-series-chart.ts | 24 +- ui-ngx/yarn.lock | 7 +- 8 files changed, 65 insertions(+), 499 deletions(-) delete mode 100644 ui-ngx/patches/echarts+5.5.0.patch diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 606864b7cd..a5304207f5 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -55,7 +55,7 @@ "core-js": "^3.29.1", "date-fns": "2.0.0-alpha.27", "dayjs": "1.11.4", - "echarts": "^5.5.0", + "echarts": "https://github.com/thingsboard/echarts/archive/5.5.0-TB.tar.gz", "flot": "https://github.com/thingsboard/flot.git#0.9-work", "flot.curvedlines": "https://github.com/MichaelZinsmaier/CurvedLines.git#master", "font-awesome": "^4.7.0", diff --git a/ui-ngx/patches/echarts+5.5.0.patch b/ui-ngx/patches/echarts+5.5.0.patch deleted file mode 100644 index 4f1ebed81a..0000000000 --- a/ui-ngx/patches/echarts+5.5.0.patch +++ /dev/null @@ -1,426 +0,0 @@ -diff --git a/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js b/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js -index d6c05f3..aafb0b8 100644 ---- a/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js -+++ b/node_modules/echarts/lib/component/dataZoom/DataZoomModel.js -@@ -362,7 +362,10 @@ var DataZoomModel = /** @class */function (_super) { - return axisProxy.getDataValueWindow(); - } - } else { -- return this.getAxisProxy(axisDim, axisIndex).getDataValueWindow(); -+ var axisProxy = this.getAxisProxy(axisDim, axisIndex); -+ if (axisProxy) { -+ return axisProxy.getDataValueWindow(); -+ } - } - }; - /** -@@ -381,10 +384,10 @@ var DataZoomModel = /** @class */function (_super) { - var axisInfo = this._targetAxisInfoMap.get(axisDim); - for (var j = 0; j < axisInfo.indexList.length; j++) { - var proxy = this.getAxisProxy(axisDim, axisInfo.indexList[j]); -- if (proxy.hostedBy(this)) { -+ if (proxy && proxy.hostedBy(this)) { - return proxy; - } -- if (!firstProxy) { -+ if (proxy && !firstProxy) { - firstProxy = proxy; - } - } -diff --git a/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js b/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js -index 06469b2..cf0b2ea 100644 ---- a/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js -+++ b/node_modules/echarts/lib/component/dataZoom/InsideZoomView.js -@@ -96,11 +96,14 @@ var getRangeHandlers = { - range[0] = (range[0] - percentPoint) * scale + percentPoint; - range[1] = (range[1] - percentPoint) * scale + percentPoint; - // Restrict range. -- var minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); -- sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan); -- this.range = range; -- if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { -- return range; -+ var proxy = this.dataZoomModel.findRepresentativeAxisProxy(); -+ if (proxy) { -+ var minMaxSpan = proxy.getMinMaxSpan(); -+ sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan); -+ this.range = range; -+ if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { -+ return range; -+ } - } - }, - pan: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e) { -diff --git a/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js b/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js -index 98912e0..0cda6be 100644 ---- a/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js -+++ b/node_modules/echarts/lib/component/dataZoom/SliderZoomView.js -@@ -64,7 +64,7 @@ var DEFAULT_MOVE_HANDLE_SIZE = 7; - var HORIZONTAL = 'horizontal'; - var VERTICAL = 'vertical'; - var LABEL_GAP = 5; --var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter']; -+var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter', 'custom']; - var REALTIME_ANIMATION_CONFIG = { - easing: 'cubicOut', - duration: 100, -@@ -359,30 +359,33 @@ var SliderZoomView = /** @class */function (_super) { - var result; - var ecModel = this.ecModel; - dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { -- var seriesModels = dataZoomModel.getAxisProxy(axisDim, axisIndex).getTargetSeriesModels(); -- each(seriesModels, function (seriesModel) { -- if (result) { -- return; -- } -- if (showDataShadow !== true && indexOf(SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')) < 0) { -- return; -- } -- var thisAxis = ecModel.getComponent(getAxisMainType(axisDim), axisIndex).axis; -- var otherDim = getOtherDim(axisDim); -- var otherAxisInverse; -- var coordSys = seriesModel.coordinateSystem; -- if (otherDim != null && coordSys.getOtherAxis) { -- otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse; -- } -- otherDim = seriesModel.getData().mapDimension(otherDim); -- result = { -- thisAxis: thisAxis, -- series: seriesModel, -- thisDim: axisDim, -- otherDim: otherDim, -- otherAxisInverse: otherAxisInverse -- }; -- }, this); -+ var axisProxy = dataZoomModel.getAxisProxy(axisDim, axisIndex); -+ if (axisProxy) { -+ var seriesModels = axisProxy.getTargetSeriesModels(); -+ each(seriesModels, function (seriesModel) { -+ if (result) { -+ return; -+ } -+ if (showDataShadow !== true && indexOf(SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')) < 0) { -+ return; -+ } -+ var thisAxis = ecModel.getComponent(getAxisMainType(axisDim), axisIndex).axis; -+ var otherDim = getOtherDim(axisDim); -+ var otherAxisInverse; -+ var coordSys = seriesModel.coordinateSystem; -+ if (otherDim != null && coordSys.getOtherAxis) { -+ otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse; -+ } -+ otherDim = seriesModel.getData().mapDimension(otherDim); -+ result = { -+ thisAxis: thisAxis, -+ series: seriesModel, -+ thisDim: axisDim, -+ otherDim: otherDim, -+ otherAxisInverse: otherAxisInverse -+ }; -+ }, this); -+ } - }, this); - return result; - }; -@@ -530,12 +533,17 @@ var SliderZoomView = /** @class */function (_super) { - var dataZoomModel = this.dataZoomModel; - var handleEnds = this._handleEnds; - var viewExtend = this._getViewExtent(); -- var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); -- var percentExtent = [0, 100]; -- sliderMove(delta, handleEnds, viewExtend, dataZoomModel.get('zoomLock') ? 'all' : handleIndex, minMaxSpan.minSpan != null ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null, minMaxSpan.maxSpan != null ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null); -- var lastRange = this._range; -- var range = this._range = asc([linearMap(handleEnds[0], viewExtend, percentExtent, true), linearMap(handleEnds[1], viewExtend, percentExtent, true)]); -- return !lastRange || lastRange[0] !== range[0] || lastRange[1] !== range[1]; -+ var proxy = dataZoomModel.findRepresentativeAxisProxy(); -+ if (proxy) { -+ var minMaxSpan = proxy.getMinMaxSpan(); -+ var percentExtent = [0, 100]; -+ sliderMove(delta, handleEnds, viewExtend, dataZoomModel.get('zoomLock') ? 'all' : handleIndex, minMaxSpan.minSpan != null ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null, minMaxSpan.maxSpan != null ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null); -+ var lastRange = this._range; -+ var range = this._range = asc([linearMap(handleEnds[0], viewExtend, percentExtent, true), linearMap(handleEnds[1], viewExtend, percentExtent, true)]); -+ return !lastRange || lastRange[0] !== range[0] || lastRange[1] !== range[1]; -+ } else { -+ return false; -+ } - }; - SliderZoomView.prototype._updateView = function (nonRealtime) { - var displaybles = this._displayables; -diff --git a/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js b/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js -index ce98fed..e154118 100644 ---- a/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js -+++ b/node_modules/echarts/lib/component/dataZoom/dataZoomProcessor.js -@@ -90,7 +90,10 @@ var dataZoomProcessor = { - // init stage and not after action dispatch handler, because - // reset should be called after seriesData.restoreData. - dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { -- dataZoomModel.getAxisProxy(axisDim, axisIndex).reset(dataZoomModel); -+ var axisProxy = dataZoomModel.getAxisProxy(axisDim, axisIndex); -+ if (axisProxy) { -+ axisProxy.reset(dataZoomModel); -+ } - }); - // Caution: data zoom filtering is order sensitive when using - // percent range and no min/max/scale set on axis. -@@ -107,7 +110,10 @@ var dataZoomProcessor = { - // So we should filter x-axis after reset x-axis immediately, - // and then reset y-axis and filter y-axis. - dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { -- dataZoomModel.getAxisProxy(axisDim, axisIndex).filterData(dataZoomModel, api); -+ var axisProxy = dataZoomModel.getAxisProxy(axisDim, axisIndex); -+ if (axisProxy) { -+ axisProxy.filterData(dataZoomModel, api); -+ } - }); - }); - ecModel.eachComponent('dataZoom', function (dataZoomModel) { -diff --git a/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js b/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js -index cf8d6bc..f9b9f90 100644 ---- a/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js -+++ b/node_modules/echarts/lib/component/toolbox/feature/DataZoom.js -@@ -109,9 +109,12 @@ var DataZoomFeature = /** @class */function (_super) { - var axisModel = axis.model; - var dataZoomModel = findDataZoom(dimName, axisModel, ecModel); - // Restrict range. -- var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan(); -- if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) { -- minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan); -+ var proxy = dataZoomModel.findRepresentativeAxisProxy(axisModel); -+ if (proxy) { -+ var minMaxSpan = proxy.getMinMaxSpan(); -+ if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) { -+ minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan); -+ } - } - dataZoomModel && (snapshot[dataZoomModel.id] = { - dataZoomId: dataZoomModel.id, -diff --git a/node_modules/echarts/lib/component/tooltip/TooltipView.js b/node_modules/echarts/lib/component/tooltip/TooltipView.js -index b8a9b95..11e49c0 100644 ---- a/node_modules/echarts/lib/component/tooltip/TooltipView.js -+++ b/node_modules/echarts/lib/component/tooltip/TooltipView.js -@@ -360,7 +360,7 @@ var TooltipView = /** @class */function (_super) { - each(itemCoordSys.dataByAxis, function (axisItem) { - var axisModel = ecModel.getComponent(axisItem.axisDim + 'Axis', axisItem.axisIndex); - var axisValue = axisItem.value; -- if (!axisModel || axisValue == null) { -+ if (!axisModel || !axisModel.axis || axisValue == null) { - return; - } - var axisValueLabel = axisPointerViewHelper.getValueLabel(axisValue, axisModel.axis, ecModel, axisItem.seriesDataIndices, axisItem.valueLabelOpt); -diff --git a/node_modules/echarts/lib/coord/axisHelper.js b/node_modules/echarts/lib/coord/axisHelper.js -index a76c66b..e5b7ee5 100644 ---- a/node_modules/echarts/lib/coord/axisHelper.js -+++ b/node_modules/echarts/lib/coord/axisHelper.js -@@ -187,7 +187,9 @@ export function createScaleByModel(model, axisType) { - }); - default: - // case 'value'/'interval', 'log', or others. -- return new (Scale.getClass(axisType) || IntervalScale)(); -+ return new (Scale.getClass(axisType) || IntervalScale)({ -+ ticksGenerator: model.get('ticksGenerator') -+ }); - } - } - } -diff --git a/node_modules/echarts/lib/coord/cartesian/Grid.js b/node_modules/echarts/lib/coord/cartesian/Grid.js -index 5b18f02..39a57f8 100644 ---- a/node_modules/echarts/lib/coord/cartesian/Grid.js -+++ b/node_modules/echarts/lib/coord/cartesian/Grid.js -@@ -91,11 +91,11 @@ var Grid = /** @class */function () { - var scale = axis.scale; - if ( - // Only value and log axis without interval support alignTicks. -- isIntervalOrLogScale(scale) && model.get('alignTicks') && model.get('interval') == null) { -+ isIntervalOrLogScale(scale) && model.get('alignTicks') && model.get('interval') == null && model.get('ticksGenerator') == null) { - axisNeedsAlign.push(axis); - } else { - niceScaleExtent(scale, model); -- if (isIntervalOrLogScale(scale)) { -+ if (isIntervalOrLogScale(scale) && !scale.isBlank()) { - // Can only align to interval or log axis. - alignTo = axis; - } -@@ -105,10 +105,15 @@ var Grid = /** @class */function () { - // All axes has set alignTicks. Pick the first one. - // PENDING. Should we find the axis that both set interval, min, max and align to this one? - if (axisNeedsAlign.length) { -- if (!alignTo) { -- alignTo = axisNeedsAlign.pop(); -- niceScaleExtent(alignTo.scale, alignTo.model); -+ while (!alignTo && axisNeedsAlign.length) { -+ var axis = axisNeedsAlign.pop(); -+ niceScaleExtent(axis.scale, axis.model); -+ if (!axis.scale.isBlank()) { -+ alignTo = axis; -+ } - } -+ } -+ if (axisNeedsAlign.length && alignTo) { - each(axisNeedsAlign, function (axis) { - alignScaleTicks(axis.scale, axis.model, alignTo.scale); - }); -diff --git a/node_modules/echarts/lib/data/SeriesData.js b/node_modules/echarts/lib/data/SeriesData.js -index 98d5ce8..1c293a6 100644 ---- a/node_modules/echarts/lib/data/SeriesData.js -+++ b/node_modules/echarts/lib/data/SeriesData.js -@@ -900,13 +900,16 @@ var SeriesData = /** @class */function () { - var dimInfo = data._dimInfos[dim]; - // Currently, only dimensions that has ordinalMeta can create inverted indices. - var ordinalMeta = dimInfo.ordinalMeta; -+ var stack = dimInfo.stack; - var store = data._store; -- if (ordinalMeta) { -- invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array(ordinalMeta.categories.length); -- // The default value of TypedArray is 0. To avoid miss -- // mapping to 0, we should set it as INDEX_NOT_FOUND. -- for (var i = 0; i < invertedIndices.length; i++) { -- invertedIndices[i] = INDEX_NOT_FOUND; -+ if (ordinalMeta || stack) { -+ invertedIndices = invertedIndicesMap[dim] = stack ? new Array(store.count()) : new CtorInt32Array(ordinalMeta.categories.length); -+ if (ordinalMeta) { -+ // The default value of TypedArray is 0. To avoid miss -+ // mapping to 0, we should set it as INDEX_NOT_FOUND. -+ for (var i = 0; i < invertedIndices.length; i++) { -+ invertedIndices[i] = INDEX_NOT_FOUND; -+ } - } - for (var i = 0; i < store.count(); i++) { - // Only support the case that all values are distinct. -diff --git a/node_modules/echarts/lib/data/Source.js b/node_modules/echarts/lib/data/Source.js -index 7dda49b..2dd2b98 100644 ---- a/node_modules/echarts/lib/data/Source.js -+++ b/node_modules/echarts/lib/data/Source.js -@@ -252,7 +252,8 @@ function normalizeDimensionsOption(dimensionsDefine) { - var item = { - name: rawItem.name, - displayName: rawItem.displayName, -- type: rawItem.type -+ type: rawItem.type, -+ stack: rawItem.stack - }; - // User can set null in dimensions. - // We don't auto specify name, otherwise a given name may -diff --git a/node_modules/echarts/lib/data/helper/createDimensions.js b/node_modules/echarts/lib/data/helper/createDimensions.js -index 00d7eb7..dd514b1 100644 ---- a/node_modules/echarts/lib/data/helper/createDimensions.js -+++ b/node_modules/echarts/lib/data/helper/createDimensions.js -@@ -110,6 +110,9 @@ source, opt) { - } - dimDefItem.type != null && (resultItem.type = dimDefItem.type); - dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName); -+ if (dimDefItem.stack) { -+ resultItem.stack = true; -+ } - var newIdx = resultList.length; - indicesMap[dimIdx] = newIdx; - resultItem.storeDimIndex = dimIdx; -diff --git a/node_modules/echarts/lib/data/helper/dataStackHelper.js b/node_modules/echarts/lib/data/helper/dataStackHelper.js -index c25de1b..ea8300d 100644 ---- a/node_modules/echarts/lib/data/helper/dataStackHelper.js -+++ b/node_modules/echarts/lib/data/helper/dataStackHelper.js -@@ -91,7 +91,7 @@ export function enableDataStack(seriesModel, dimensionsInput, opt) { - } - if (mayStack && !dimensionInfo.isExtraCoord) { - // Find the first ordinal dimension as the stackedByDimInfo. -- if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) { -+ if (!byIndex && !stackedByDimInfo && (dimensionInfo.ordinalMeta || dimensionInfo.stack)) { - stackedByDimInfo = dimensionInfo; - } - // Find the first stackable dimension as the stackedDimInfo. -diff --git a/node_modules/echarts/lib/scale/Interval.js b/node_modules/echarts/lib/scale/Interval.js -index 1094662..363c0a5 100644 ---- a/node_modules/echarts/lib/scale/Interval.js -+++ b/node_modules/echarts/lib/scale/Interval.js -@@ -46,12 +46,17 @@ import * as numberUtil from '../util/number.js'; - import * as formatUtil from '../util/format.js'; - import Scale from './Scale.js'; - import * as helper from './helper.js'; -+import { isFunction } from 'zrender/lib/core/util.js'; - var roundNumber = numberUtil.round; - var IntervalScale = /** @class */function (_super) { - __extends(IntervalScale, _super); -- function IntervalScale() { -- var _this = _super !== null && _super.apply(this, arguments) || this; -+ function IntervalScale(setting) { -+ var _this = _super.call(this, setting) || this; - _this.type = 'interval'; -+ var ticksGenerator = _this.getSetting('ticksGenerator'); -+ if (isFunction(ticksGenerator)) { -+ _this._ticksGenerator = ticksGenerator; -+ } - // Step is calculated in adjustExtent. - _this._interval = 0; - _this._intervalPrecision = 2; -@@ -104,7 +109,17 @@ var IntervalScale = /** @class */function (_super) { - var extent = this._extent; - var niceTickExtent = this._niceExtent; - var intervalPrecision = this._intervalPrecision; -- var ticks = []; -+ var ticksGenerator = this._ticksGenerator; -+ var ticks; -+ if (ticksGenerator) { -+ try { -+ ticks = ticksGenerator(extent, interval, niceTickExtent, intervalPrecision); -+ if (ticks) { -+ return ticks; -+ } -+ } catch (_e) {} -+ } -+ ticks = []; - // If interval is 0, return []; - if (!interval) { - return ticks; -diff --git a/node_modules/echarts/types/dist/shared.d.ts b/node_modules/echarts/types/dist/shared.d.ts -index ca74097..ef41ce2 100644 ---- a/node_modules/echarts/types/dist/shared.d.ts -+++ b/node_modules/echarts/types/dist/shared.d.ts -@@ -2422,6 +2422,9 @@ interface AxisBaseOptionCommon extends ComponentOption, AnimationOptionMixin { - max: number; - }) => ScaleDataValue); - } -+ -+declare type NumericAxisTicksGenerator = (extent?: number[], interval?: number, niceTickExtent?: number[], intervalPrecision?: number) => {value: number}[]; -+ - interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon { - boundaryGap?: [number | string, number | string]; - /** -@@ -2447,6 +2450,8 @@ interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon { - * Will be ignored if interval is set. - */ - alignTicks?: boolean; -+ -+ ticksGenerator?: NumericAxisTicksGenerator; - } - interface CategoryAxisBaseOption extends AxisBaseOptionCommon { - type?: 'category'; -@@ -6412,6 +6417,7 @@ declare type DimensionDefinition = { - type?: DataStoreDimensionType; - name?: DimensionName; - displayName?: string; -+ stack?: boolean; - }; - declare type DimensionDefinitionLoose = DimensionDefinition['name'] | DimensionDefinition; - declare const SOURCE_FORMAT_ORIGINAL: "original"; -diff --git a/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts b/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts -index c5c2792..d524b70 100644 ---- a/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts -+++ b/node_modules/echarts/types/src/coord/axisCommonTypes.d.ts -@@ -56,6 +56,9 @@ export interface AxisBaseOptionCommon extends ComponentOption, AnimationOptionMi - max: number; - }) => ScaleDataValue); - } -+ -+export declare type NumericAxisTicksGenerator = (extent?: number[], interval?: number, niceTickExtent?: number[], intervalPrecision?: number) => {value: number}[]; -+ - export interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon { - boundaryGap?: [number | string, number | string]; - /** -@@ -81,6 +84,8 @@ export interface NumericAxisBaseOptionCommon extends AxisBaseOptionCommon { - * Will be ignored if interval is set. - */ - alignTicks?: boolean; -+ -+ ticksGenerator?: NumericAxisTicksGenerator; - } - export interface CategoryAxisBaseOption extends AxisBaseOptionCommon { - type?: 'category'; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts index da7f4d4e40..e2779f2821 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/bar-chart-with-labels-widget.component.ts @@ -54,7 +54,7 @@ import { echartsModule, EChartsOption, EChartsSeriesItem, - echartsTooltipFormatter, + echartsTooltipFormatter, timeAxisBandWidthCalculator, toNamedData } from '@home/components/widget/lib/chart/echarts-widget.models'; import { AggregationType, IntervalMath } from '@shared/models/time/time.models'; @@ -424,7 +424,8 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft onZero: false }, min: this.ctx.defaultSubscription.timeWindow.minTime, - max: this.ctx.defaultSubscription.timeWindow.maxTime + max: this.ctx.defaultSubscription.timeWindow.maxTime, + bandWidthCalculator: timeAxisBandWidthCalculator }, yAxis: { type: 'value', diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts index 7fdd1fbfff..816f45a7e8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/echarts-widget.models.ts @@ -15,11 +15,9 @@ /// import * as echarts from 'echarts/core'; -import { Axis } from 'echarts'; import AxisModel from 'echarts/types/src/coord/cartesian/AxisModel'; import { estimateLabelUnionRect } from 'echarts/lib/coord/axisHelper'; import { formatValue, isDefinedAndNotNull } from '@core/utils'; -import TimeScale from 'echarts/types/src/scale/Time'; import { DataZoomComponent, DataZoomComponentOption, @@ -51,7 +49,7 @@ import { IntervalMath, WidgetTimewindow } from '@shared/models/time/time.models'; -import { CallbackDataParams } from 'echarts/types/dist/shared'; +import { CallbackDataParams, TimeAxisBandWidthCalculator } from 'echarts/types/dist/shared'; import { Renderer2 } from '@angular/core'; import { DateFormatProcessor, DateFormatSettings, Font } from '@shared/models/widget-settings.models'; import GlobalModel from 'echarts/types/src/model/Global'; @@ -63,53 +61,6 @@ class EChartsModule { init() { if (!this.initialized) { - const axisGetBandWidth = Axis.prototype.getBandWidth; - - Axis.prototype.getBandWidth = function(){ - const model: AxisModel = this.model; - const axisOption = model.option; - if (this.scale.type === 'time') { - let interval: number; - const seriesDataIndices = axisOption.axisPointer?.seriesDataIndices; - if (seriesDataIndices?.length) { - const seriesDataIndex = seriesDataIndices[0]; - const series = model.ecModel.getSeriesByIndex(seriesDataIndex.seriesIndex); - if (series) { - const values = series.getData().getValues(seriesDataIndex.dataIndex); - const start = values[2]; - const end = values[3]; - if (typeof start === 'number' && typeof end === 'number') { - interval = Math.max(end - start, 1); - } - } - } - if (!interval) { - const tbTimeWindow: WidgetTimewindow = (axisOption as any).tbTimeWindow; - if (isDefinedAndNotNull(tbTimeWindow)) { - if (axisOption.axisPointer?.value && typeof axisOption.axisPointer?.value === 'number') { - const intervalArray = calculateAggIntervalWithWidgetTimeWindow(tbTimeWindow, axisOption.axisPointer.value); - const start = intervalArray[0]; - const end = intervalArray[1]; - interval = Math.max(end - start, 1); - } else { - interval = IntervalMath.numberValue(tbTimeWindow.interval); - } - } - } - if (interval) { - const timeScale: TimeScale = this.scale; - const axisExtent: [number, number] = this._extent; - const dataExtent = timeScale.getExtent(); - const size = Math.abs(axisExtent[1] - axisExtent[0]); - return interval * (size / (dataExtent[1] - dataExtent[0])); - } else { - return axisGetBandWidth.call(this); - } - } else { - return axisGetBandWidth.call(this); - } - }; - echarts.use([ TooltipComponent, GridComponent, @@ -124,7 +75,6 @@ class EChartsModule { CanvasRenderer, SVGRenderer ]); - this.initialized = true; } } @@ -160,6 +110,44 @@ export type EChartsSeriesItem = { decimals?: number; }; +export const timeAxisBandWidthCalculator: TimeAxisBandWidthCalculator = (model) => { + let interval: number; + const axisOption = model.option; + const seriesDataIndices = axisOption.axisPointer?.seriesDataIndices; + if (seriesDataIndices?.length) { + const seriesDataIndex = seriesDataIndices[0]; + const series = model.ecModel.getSeriesByIndex(seriesDataIndex.seriesIndex); + if (series) { + const values = series.getData().getValues(seriesDataIndex.dataIndex); + const start = values[2]; + const end = values[3]; + if (typeof start === 'number' && typeof end === 'number') { + interval = Math.max(end - start, 1); + } + } + } + if (!interval) { + const tbTimeWindow: WidgetTimewindow = (axisOption as any).tbTimeWindow; + if (isDefinedAndNotNull(tbTimeWindow)) { + if (axisOption.axisPointer?.value && typeof axisOption.axisPointer?.value === 'number') { + const intervalArray = calculateAggIntervalWithWidgetTimeWindow(tbTimeWindow, axisOption.axisPointer.value); + const start = intervalArray[0]; + const end = intervalArray[1]; + interval = Math.max(end - start, 1); + } else { + interval = IntervalMath.numberValue(tbTimeWindow.interval); + } + } + } + if (interval) { + const timeScale = model.axis.scale; + const axisExtent = model.axis.getExtent(); + const dataExtent = timeScale.getExtent(); + const size = Math.abs(axisExtent[1] - axisExtent[0]); + return interval * (size / (dataExtent[1] - dataExtent[0])); + } +}; + export const getXAxis = (chart: ECharts): Axis2D => { const model: GlobalModel = (chart as any).getModel(); const models = model.queryComponents({mainType: 'xAxis'}); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts index 1705074a1e..1ef756f1f7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/range-chart-widget.component.ts @@ -50,7 +50,7 @@ import { ECharts, echartsModule, EChartsOption, - echartsTooltipFormatter, + echartsTooltipFormatter, timeAxisBandWidthCalculator, toNamedData } from '@home/components/widget/lib/chart/echarts-widget.models'; import { CallbackDataParams } from 'echarts/types/dist/shared'; @@ -356,7 +356,8 @@ export class RangeChartWidgetComponent implements OnInit, OnDestroy, AfterViewIn onZero: false }, min: this.ctx.defaultSubscription.timeWindow.minTime, - max: this.ctx.defaultSubscription.timeWindow.maxTime + max: this.ctx.defaultSubscription.timeWindow.maxTime, + bandWidthCalculator: timeAxisBandWidthCalculator }, yAxis: { type: 'value', diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts index 6f985466c4..e931349bca 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.models.ts @@ -20,7 +20,7 @@ import { EChartsSeriesItem, EChartsTooltipTrigger, EChartsTooltipWidgetSettings, - measureThresholdLabelOffset + measureThresholdLabelOffset, timeAxisBandWidthCalculator } from '@home/components/widget/lib/chart/echarts-widget.models'; import { autoDateFormat, @@ -969,7 +969,8 @@ export const createTimeSeriesXAxisOption = (settings: TimeSeriesChartXAxisSettin } }, min, - max + max, + bandWidthCalculator: timeAxisBandWidthCalculator }; }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 65a323e4b6..bd9005c497 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -140,8 +140,8 @@ export class TbTimeSeriesChart { timeSeriesChartDefaultSettings, this.inputSettings as TimeSeriesChartSettings); const $dashboardPageElement = this.ctx.$containerParent.parents('.tb-dashboard-page'); - const dashboardPageElement = $($dashboardPageElement[$dashboardPageElement.length-1]); - this.darkMode = this.settings.darkMode || dashboardPageElement.hasClass('dark'); + const dashboardPageElement = $dashboardPageElement.length ? $($dashboardPageElement[$dashboardPageElement.length-1]) : null; + this.darkMode = this.settings.darkMode || dashboardPageElement?.hasClass('dark'); this.setupYAxes(); this.setupData(); this.setupThresholds(); @@ -155,15 +155,17 @@ export class TbTimeSeriesChart { }); this.shapeResize$.observe(this.chartElement); } - this.darkModeObserver = new MutationObserver(mutations => { - for(let mutation of mutations) { - if (mutation.type === 'attributes' && mutation.attributeName === 'class') { - const darkMode = dashboardPageElement.hasClass('dark'); - this.setDarkMode(darkMode); + if (dashboardPageElement) { + this.darkModeObserver = new MutationObserver(mutations => { + for (const mutation of mutations) { + if (mutation.type === 'attributes' && mutation.attributeName === 'class') { + const darkMode = dashboardPageElement.hasClass('dark'); + this.setDarkMode(darkMode); + } } - } - }); - this.darkModeObserver.observe(dashboardPageElement[0], { attributes: true }); + }); + this.darkModeObserver.observe(dashboardPageElement[0], {attributes: true}); + } } public update(): void { @@ -270,7 +272,7 @@ export class TbTimeSeriesChart { } this.yMinSubject.complete(); this.yMaxSubject.complete(); - this.darkModeObserver.disconnect(); + this.darkModeObserver?.disconnect(); } public resize(): void { diff --git a/ui-ngx/yarn.lock b/ui-ngx/yarn.lock index 33362767bd..ddcd48243b 100644 --- a/ui-ngx/yarn.lock +++ b/ui-ngx/yarn.lock @@ -5437,10 +5437,9 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -echarts@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/echarts/-/echarts-5.5.0.tgz#c13945a7f3acdd67c134d8a9ac67e917830113ac" - integrity sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw== +"echarts@https://github.com/thingsboard/echarts/archive/5.5.0-TB.tar.gz": + version "5.5.0-TB" + resolved "https://github.com/thingsboard/echarts/archive/5.5.0-TB.tar.gz#d1017728576b3fd65532eb17e503d1349f7feaed" dependencies: tslib "2.3.0" zrender "5.5.0" From 79803292b6956e6cd805a1fb033e9be73ff5be0c Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Tue, 26 Mar 2024 18:03:54 +0200 Subject: [PATCH 395/397] Fix time series charts initialization --- .../widget/lib/chart/time-series-chart.ts | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts index 462825087e..bd9005c497 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/chart/time-series-chart.ts @@ -139,8 +139,9 @@ export class TbTimeSeriesChart { this.settings = mergeDeep({} as TimeSeriesChartSettings, timeSeriesChartDefaultSettings, this.inputSettings as TimeSeriesChartSettings); - const dashboardPageElement = this.ctx.$containerParent.parents('.tb-dashboard-page'); - this.darkMode = this.settings.darkMode || dashboardPageElement.hasClass('dark'); + const $dashboardPageElement = this.ctx.$containerParent.parents('.tb-dashboard-page'); + const dashboardPageElement = $dashboardPageElement.length ? $($dashboardPageElement[$dashboardPageElement.length-1]) : null; + this.darkMode = this.settings.darkMode || dashboardPageElement?.hasClass('dark'); this.setupYAxes(); this.setupData(); this.setupThresholds(); @@ -154,15 +155,17 @@ export class TbTimeSeriesChart { }); this.shapeResize$.observe(this.chartElement); } - this.darkModeObserver = new MutationObserver(mutations => { - for(let mutation of mutations) { - if (mutation.type === 'attributes' && mutation.attributeName === 'class') { - const darkMode = dashboardPageElement.hasClass('dark'); - this.setDarkMode(darkMode); + if (dashboardPageElement) { + this.darkModeObserver = new MutationObserver(mutations => { + for (const mutation of mutations) { + if (mutation.type === 'attributes' && mutation.attributeName === 'class') { + const darkMode = dashboardPageElement.hasClass('dark'); + this.setDarkMode(darkMode); + } } - } - }); - this.darkModeObserver.observe(dashboardPageElement[0], { attributes: true }); + }); + this.darkModeObserver.observe(dashboardPageElement[0], {attributes: true}); + } } public update(): void { @@ -269,7 +272,7 @@ export class TbTimeSeriesChart { } this.yMinSubject.complete(); this.yMaxSubject.complete(); - this.darkModeObserver.disconnect(); + this.darkModeObserver?.disconnect(); } public resize(): void { From 8235b144a525bea23bb8e88c33d120aa03d8233a Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Wed, 27 Mar 2024 10:14:24 +0200 Subject: [PATCH 396/397] Fix EdgeControllerTest --- .../server/controller/EdgeControllerTest.java | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java index 61d86994eb..73a3a2e25e 100644 --- a/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/EdgeControllerTest.java @@ -76,6 +76,7 @@ import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg; import org.thingsboard.server.gen.edge.v1.DeviceProfileUpdateMsg; import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg; import org.thingsboard.server.gen.edge.v1.EdgeVersion; +import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg; import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg; import org.thingsboard.server.gen.edge.v1.RuleChainUpdateMsg; import org.thingsboard.server.gen.edge.v1.SyncCompletedMsg; @@ -631,7 +632,7 @@ public class EdgeControllerTest extends AbstractControllerTest { List loadedEdges = new ArrayList<>(); PageLink pageLink = new PageLink(23); - PageData pageData = null; + PageData pageData; do { pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/edges?", new TypeReference<>() { @@ -885,6 +886,7 @@ public class EdgeControllerTest extends AbstractControllerTest { EdgeImitator edgeImitator = new EdgeImitator(EDGE_HOST, EDGE_PORT, edge.getRoutingKey(), edge.getSecret()); edgeImitator.ignoreType(UserCredentialsUpdateMsg.class); + edgeImitator.ignoreType(OAuth2UpdateMsg.class); edgeImitator.expectMessageAmount(24); edgeImitator.connect(); @@ -973,8 +975,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popQueueMsg(List messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { - if (message instanceof QueueUpdateMsg) { - QueueUpdateMsg queueUpdateMsg = (QueueUpdateMsg) message; + if (message instanceof QueueUpdateMsg queueUpdateMsg) { Queue queue = JacksonUtil.fromString(queueUpdateMsg.getEntity(), Queue.class, true); Assert.assertNotNull(queue); if (msgType.equals(queueUpdateMsg.getMsgType()) && name.equals(queue.getName())) { @@ -988,8 +989,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popRuleChainMsg(List messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { - if (message instanceof RuleChainUpdateMsg) { - RuleChainUpdateMsg ruleChainUpdateMsg = (RuleChainUpdateMsg) message; + if (message instanceof RuleChainUpdateMsg ruleChainUpdateMsg) { RuleChain ruleChain = JacksonUtil.fromString(ruleChainUpdateMsg.getEntity(), RuleChain.class, true); Assert.assertNotNull(ruleChain); if (msgType.equals(ruleChainUpdateMsg.getMsgType()) @@ -1005,8 +1005,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popAdminSettingsMsg(List messages, String key) { for (AbstractMessage message : messages) { - if (message instanceof AdminSettingsUpdateMsg) { - AdminSettingsUpdateMsg adminSettingsUpdateMsg = (AdminSettingsUpdateMsg) message; + if (message instanceof AdminSettingsUpdateMsg adminSettingsUpdateMsg) { AdminSettings adminSettings = JacksonUtil.fromString(adminSettingsUpdateMsg.getEntity(), AdminSettings.class, true); Assert.assertNotNull(adminSettings); if (key.equals(adminSettings.getKey())) { @@ -1020,8 +1019,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popDeviceProfileMsg(List messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { - if (message instanceof DeviceProfileUpdateMsg) { - DeviceProfileUpdateMsg deviceProfileUpdateMsg = (DeviceProfileUpdateMsg) message; + if (message instanceof DeviceProfileUpdateMsg deviceProfileUpdateMsg) { DeviceProfile deviceProfile = JacksonUtil.fromString(deviceProfileUpdateMsg.getEntity(), DeviceProfile.class, true); Assert.assertNotNull(deviceProfile); if (msgType.equals(deviceProfileUpdateMsg.getMsgType()) @@ -1036,8 +1034,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popDeviceMsg(List messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { - if (message instanceof DeviceUpdateMsg) { - DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) message; + if (message instanceof DeviceUpdateMsg deviceUpdateMsg) { Device device = JacksonUtil.fromString(deviceUpdateMsg.getEntity(), Device.class, true); Assert.assertNotNull(device); if (msgType.equals(deviceUpdateMsg.getMsgType()) @@ -1052,8 +1049,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popAssetProfileMsg(List messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { - if (message instanceof AssetProfileUpdateMsg) { - AssetProfileUpdateMsg assetProfileUpdateMsg = (AssetProfileUpdateMsg) message; + if (message instanceof AssetProfileUpdateMsg assetProfileUpdateMsg) { AssetProfile assetProfile = JacksonUtil.fromString(assetProfileUpdateMsg.getEntity(), AssetProfile.class, true); Assert.assertNotNull(assetProfile); if (msgType.equals(assetProfileUpdateMsg.getMsgType()) @@ -1068,8 +1064,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popAssetMsg(List messages, UpdateMsgType msgType, String name) { for (AbstractMessage message : messages) { - if (message instanceof AssetUpdateMsg) { - AssetUpdateMsg assetUpdateMsg = (AssetUpdateMsg) message; + if (message instanceof AssetUpdateMsg assetUpdateMsg) { Asset asset = JacksonUtil.fromString(assetUpdateMsg.getEntity(), Asset.class, true); Assert.assertNotNull(asset); if (msgType.equals(assetUpdateMsg.getMsgType()) @@ -1084,8 +1079,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popUserMsg(List messages, UpdateMsgType msgType, String email, Authority authority) { for (AbstractMessage message : messages) { - if (message instanceof UserUpdateMsg) { - UserUpdateMsg userUpdateMsg = (UserUpdateMsg) message; + if (message instanceof UserUpdateMsg userUpdateMsg) { User user = JacksonUtil.fromString(userUpdateMsg.getEntity(), User.class, true); Assert.assertNotNull(user); if (msgType.equals(userUpdateMsg.getMsgType()) @@ -1101,8 +1095,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popCustomerMsg(List messages, UpdateMsgType msgType, String title) { for (AbstractMessage message : messages) { - if (message instanceof CustomerUpdateMsg) { - CustomerUpdateMsg customerUpdateMsg = (CustomerUpdateMsg) message; + if (message instanceof CustomerUpdateMsg customerUpdateMsg) { Customer customer = JacksonUtil.fromString(customerUpdateMsg.getEntity(), Customer.class, true); Assert.assertNotNull(customer); if (msgType.equals(customerUpdateMsg.getMsgType()) @@ -1117,8 +1110,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popTenantMsg(List messages, TenantId tenantId1) { for (AbstractMessage message : messages) { - if (message instanceof TenantUpdateMsg) { - TenantUpdateMsg tenantUpdateMsg = (TenantUpdateMsg) message; + if (message instanceof TenantUpdateMsg tenantUpdateMsg) { Tenant tenant = JacksonUtil.fromString(tenantUpdateMsg.getEntity(), Tenant.class, true); Assert.assertNotNull(tenant); if (UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE.equals(tenantUpdateMsg.getMsgType()) @@ -1133,8 +1125,7 @@ public class EdgeControllerTest extends AbstractControllerTest { private boolean popTenantProfileMsg(List messages, TenantProfileId tenantProfileId) { for (AbstractMessage message : messages) { - if (message instanceof TenantProfileUpdateMsg) { - TenantProfileUpdateMsg tenantProfileUpdateMsg = (TenantProfileUpdateMsg) message; + if (message instanceof TenantProfileUpdateMsg tenantProfileUpdateMsg) { TenantProfile tenantProfile = JacksonUtil.fromString(tenantProfileUpdateMsg.getEntity(), TenantProfile.class, true); Assert.assertNotNull(tenantProfile); if (UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE.equals(tenantProfileUpdateMsg.getMsgType()) @@ -1236,4 +1227,5 @@ public class EdgeControllerTest extends AbstractControllerTest { edgeUpgradeInstructionsService.setAppVersion("3.6.2.6"); Assert.assertTrue(edgeUpgradeInstructionsService.isUpgradeAvailable(savedEdge.getTenantId(), savedEdge.getId())); } + } From 8b60deece6683ddd49e320f284d90f60ee170138 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Wed, 27 Mar 2024 14:19:26 +0200 Subject: [PATCH 397/397] Fixed comment in OAuth2EdgeTest --- .../test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java index b5ed5e788c..c25410b562 100644 --- a/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java @@ -42,7 +42,7 @@ public class OAuth2EdgeTest extends AbstractEdgeTest { public void testOAuth2Support() throws Exception { loginSysAdmin(); - // enable oauth, verify nothing sent to edge + // enable oauth edgeImitator.allowIgnoredTypes(); edgeImitator.expectMessageAmount(1); OAuth2Info oAuth2Info = createDefaultOAuth2Info();
    diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.ts index ef5bb27610..312dd5a6fc 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-error-dialog.component.ts @@ -22,7 +22,7 @@ import { Router } from '@angular/router'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { NotificationDeliveryMethod, - NotificationDeliveryMethodTranslateMap, + NotificationDeliveryMethodInfoMap, NotificationRequest } from '@shared/models/notification.models'; @@ -39,7 +39,7 @@ export class SentErrorDialogComponent extends DialogComponent, protected router: Router, diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html index edb294bba8..71daee5343 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html @@ -29,7 +29,7 @@
    @@ -88,7 +88,7 @@ [matTooltip]="getDeliveryMethodsTooltip(deliveryMethods)" matTooltipPosition="above"> - {{ notificationDeliveryMethodTranslateMap.get(deliveryMethods) | translate }} + {{ notificationDeliveryMethodInfoMap.get(deliveryMethods).name | translate }} chevron_right @@ -101,7 +101,7 @@ [matTooltipDisabled]="getDeliveryMethodsTemplatesControl(deliveryMethods).enabled" matTooltipPosition="above"> - {{ notificationDeliveryMethodTranslateMap.get(deliveryMethods) | translate }} + {{ notificationDeliveryMethodInfoMap.get(deliveryMethods).name | translate }} @@ -145,338 +145,16 @@ - - {{ 'notification.delivery-method.web' | translate }} -
    - {{ 'notification.input-fields-support-templatization' | translate}} - -
    -
    - - notification.subject - - - {{ 'notification.subject-required' | translate }} - - - - notification.message - - - {{ 'notification.message-required' | translate }} - - -
    -
    - - {{ 'icon.icon' | translate }} - -
    - - - - -
    -
    -
    - - - - - {{ 'notification.action-button' | translate }} - - - - -
    - - notification.button-text - - - {{ 'notification.button-text-required' | translate }} - - - {{ 'notification.button-text-max-length' | translate : - {length: webTemplateForm.get('additionalConfig.actionButtonConfig.text').getError('maxlength').requiredLength} - }} - - -
    -
    - - notification.action-type - - - {{ actionButtonLinkTypeTranslateMap.get(actionButtonLinkType) | translate }} - - - - - notification.link - - - {{ 'notification.link-required' | translate }} - - - - - - - - -
    - - {{ 'notification.set-entity-from-notification' | translate }} - -
    -
    -
    -
    -
    -
    - - {{ 'notification.delivery-method.email' | translate }} - -
    - {{ 'notification.input-fields-support-templatization' | translate}} - -
    -
    - - notification.subject - - - {{ 'notification.subject-required' | translate }} - - - notification.message - - - {{ 'notification.message-required' | translate }} - -
    -
    -
    - - {{ 'notification.delivery-method.sms' | translate }} -
    - {{ 'notification.input-field-support-templatization' | translate}} - -
    -
    - - notification.message - - - {{ 'notification.message-required' | translate }} - - - {{ 'notification.message-max-length' | translate : - {length: smsTemplateForm.get('body').getError('maxlength').requiredLength} - }} - - -
    -
    - - {{ 'notification.delivery-method.slack' | translate }} -
    - {{ 'notification.input-field-support-templatization' | translate}} - -
    -
    - - notification.message - - - {{ 'notification.message-required' | translate }} - - -
    -
    - - {{ 'notification.delivery-method.microsoft-teams' | translate }} -
    - {{ 'notification.input-fields-support-templatization' | translate}} - -
    -
    - - notification.subject - - - - notification.message - - - {{ 'notification.message-required' | translate }} - - -
    -
    -
    notification.theme-color
    - -
    -
    - - - - - {{ 'notification.action-button' | translate }} - - - - -
    - - notification.button-text - - - {{ 'notification.button-text-required' | translate }} - - - {{ 'notification.button-text-max-length' | translate : - {length: microsoftTeamsTemplateForm.get('button.text').getError('maxlength').requiredLength} - }} - - -
    -
    - - notification.action-type - - - {{ actionButtonLinkTypeTranslateMap.get(actionButtonLinkType) | translate }} - - - - - notification.link - - - {{ 'notification.link-required' | translate }} - - - - - - - - -
    - - {{ 'notification.set-entity-from-notification' | translate }} - -
    -
    -
    -
    -
    -
    - - {{ 'notification.delivery-method.mobile-app' | translate }} -
    - {{ 'notification.input-field-support-templatization' | translate}} - -
    -
    - - notification.subject - - - {{ 'notification.subject-required' | translate }} - - - - notification.message - - - {{ 'notification.message-required' | translate }} - - + + {{ 'notification.compose' | translate }} + + +
    diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss index c91c33a9d0..b5527b9adc 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss @@ -16,7 +16,7 @@ @import "../../../../../../scss/constants"; :host { - width: 930px; + width: 775px; height: 100%; max-width: 100%; max-height: 100vh; diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts index 0262ef88cb..98fd3ba61d 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts @@ -24,7 +24,6 @@ import { import { Component, Inject, OnDestroy, ViewChild } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { Router } from '@angular/router'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog'; import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { NotificationService } from '@core/http/notification.service'; @@ -47,6 +46,7 @@ import { Authority } from '@shared/models/authority.enum'; import { AuthUser } from '@shared/models/user.model'; import { getCurrentAuthUser } from '@core/auth/auth.selectors'; import { TranslateService } from '@ngx-translate/core'; +import { Router } from '@angular/router'; export interface RequestNotificationDialogData { request?: NotificationRequest; @@ -98,7 +98,7 @@ export class SentNotificationDialogComponent extends } }); - this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-sm']) + this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-xs']) .pipe(map(({matches}) => matches ? 'horizontal' : 'vertical')); this.notificationRequestForm = this.fb.group({ @@ -150,11 +150,9 @@ export class SentNotificationDialogComponent extends let useTemplate = true; if (isDefinedAndNotNull(this.data.request.template)) { useTemplate = false; - // eslint-disable-next-line guard-for-in - for (const method in this.data.request.template.configuration.deliveryMethodsTemplates) { - this.deliveryMethodFormsMap.get(NotificationDeliveryMethod[method]) - .patchValue(this.data.request.template.configuration.deliveryMethodsTemplates[method]); - } + this.notificationTemplateConfigurationForm.patchValue({ + deliveryMethodsTemplates: this.data.request.template.configuration.deliveryMethodsTemplates + }, {emitEvent: false}); } this.notificationRequestForm.get('useTemplate').setValue(useTemplate, {onlySelf : true}); } @@ -178,6 +176,9 @@ export class SentNotificationDialogComponent extends changeStep($event: StepperSelectionEvent) { this.selectedIndex = $event.selectedIndex; + if ($event.previouslySelectedIndex > $event.selectedIndex) { + $event.previouslySelectedStep.interacted = false; + } if (this.selectedIndex === this.maxStepperIndex) { this.getPreview(); } diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts index e4395cdb72..97b353555a 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-table-config.resolver.ts @@ -21,7 +21,7 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; import { - NotificationDeliveryMethodTranslateMap, + NotificationDeliveryMethodInfoMap, NotificationRequest, NotificationRequestInfo, NotificationRequestStats, @@ -94,7 +94,7 @@ export class SentTableConfigResolver implements Resolve this.requestStatusStyle(request.status)), new EntityTableColumn('deliveryMethods', 'notification.delivery-method.delivery-method', '15%', (request) => request.deliveryMethods - .map((deliveryMethod) => this.translate.instant(NotificationDeliveryMethodTranslateMap.get(deliveryMethod))).join(', '), + .map((deliveryMethod) => this.translate.instant(NotificationDeliveryMethodInfoMap.get(deliveryMethod).name)).join(', '), () => ({}), false), new EntityTableColumn('templateName', 'notification.template', '70%') ); diff --git a/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.html b/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.html index 502ea1f828..90482be72f 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.html @@ -54,7 +54,7 @@ (change)="changeInstanceTypeCheckBox($event.checked, deliveryMethods)" [indeterminate]="getIndeterminate(deliveryMethods)" (click)="$event.stopPropagation()"> - {{ notificationDeliveryMethodTranslateMap.get(deliveryMethods) | translate }} + {{ notificationDeliveryMethodInfoMap.get(deliveryMethods).name | translate }}
    diff --git a/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.ts b/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.ts index 4d839541c8..c2d3afe890 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/settings/notification-settings.component.ts @@ -25,7 +25,7 @@ import { ActivatedRoute } from '@angular/router'; import { deepClone, isDefinedAndNotNull } from '@core/utils'; import { NotificationDeliveryMethod, - NotificationDeliveryMethodTranslateMap, + NotificationDeliveryMethodInfoMap, NotificationUserSettings } from '@shared/models/notification.models'; import { NotificationService } from '@core/http/notification.service'; @@ -41,7 +41,7 @@ export class NotificationSettingsComponent extends PageComponent implements OnIn notificationSettings: UntypedFormGroup; notificationDeliveryMethods: NotificationDeliveryMethod[]; - notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap; + notificationDeliveryMethodInfoMap = NotificationDeliveryMethodInfoMap; private deliveryMethods = new Set([ NotificationDeliveryMethod.SLACK, diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.html b/ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.html new file mode 100644 index 0000000000..a856f1eb7d --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.html @@ -0,0 +1,398 @@ + +
    +
    notification.customize-messages
    +
    + {{ 'notification.input-fields-support-templatization' | translate}} + +
    +
    +
    +
    + + + + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.WEB).icon }} + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.WEB).name | translate }} + + + + + notification.subject + + + {{ 'notification.subject-required' | translate }} + + + + notification.message + + + {{ 'notification.message-required' | translate }} + + +
    +
    + + {{ 'icon.icon' | translate }} + +
    + + + + +
    +
    +
    + + + + + {{ 'notification.action-button' | translate }} + + + + +
    + + notification.button-text + + + {{ 'notification.button-text-required' | translate }} + + + {{ 'notification.button-text-max-length' | translate : + {length: templateConfigurationForm.get('WEB.additionalConfig.actionButtonConfig.text').getError('maxlength').requiredLength} + }} + + +
    +
    + + notification.action-type + + + {{ actionButtonLinkTypeTranslateMap.get(actionButtonLinkType) | translate }} + + + + + notification.link + + + {{ 'notification.link-required' | translate }} + + + + + + + + +
    + + {{ 'notification.set-entity-from-notification' | translate }} + +
    +
    +
    +
    +
    +
    +
    +
    + + + + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.MOBILE_APP).icon }} + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.MOBILE_APP).name | translate }} + + + + + notification.subject + + + {{ 'notification.subject-required' | translate }} + + + + notification.message + + + {{ 'notification.message-required' | translate }} + + +
    + + + + + {{ 'notification.open-dashboard-on-click-notification' | translate }} + + + + +
    + + + + +
    + + {{ 'notification.set-entity-from-notification' | translate }} + +
    +
    +
    +
    +
    +
    +
    + + + + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.SMS).icon }} + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.SMS).name | translate }} + + + + + notification.message + + + + {{ 'notification.message-required' | translate }} + + + {{ 'notification.message-max-length' | translate : + {length: templateConfigurationForm.get('SMS.body').getError('maxlength').requiredLength} + }} + + + + +
    +
    + + + + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.MICROSOFT_TEAMS).icon }} + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.MICROSOFT_TEAMS).name | translate }} + + + + + notification.subject + + + + notification.message + + + {{ 'notification.message-required' | translate }} + + +
    +
    +
    notification.theme-color
    + +
    +
    + + + + + {{ 'notification.action-button' | translate }} + + + + +
    + + notification.button-text + + + {{ 'notification.button-text-required' | translate }} + + + {{'notification.button-text-max-length' | translate : + {length: templateConfigurationForm.get('MICROSOFT_TEAMS.button.text').getError('maxlength').requiredLength} + }} + + +
    +
    + + notification.action-type + + + {{ actionButtonLinkTypeTranslateMap.get(actionButtonLinkType) | translate }} + + + + + notification.link + + + {{ 'notification.link-required' | translate }} + + + + + + + + +
    + + {{ 'notification.set-entity-from-notification' | translate }} + +
    +
    +
    +
    +
    +
    +
    +
    + + + + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.SLACK).icon }} + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.SLACK).name | translate }} + + + + + notification.message + + + {{ 'notification.message-required' | translate }} + + + + +
    +
    + + + + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.EMAIL).icon }} + {{ NotificationDeliveryMethodInfoMap.get(NotificationDeliveryMethod.EMAIL).name | translate }} + + + + + notification.subject + + + {{ 'notification.subject-required' | translate }} + + + notification.message + + + + {{ 'notification.message-required' | translate }} + + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.scss b/ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.scss new file mode 100644 index 0000000000..b69b950a42 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.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 { + .tb-template-header { + margin-bottom: 12px; + .tb-hint-available-params { + color: rgba(0,0,0,0.54); + letter-spacing: 0.4px; + + .content { + vertical-align: middle; + } + } + } + + .template-tittle { + gap: 12px; + font-weight: normal; + tb-icon { + color: rgba(0, 0, 0, .38); + } + } + + .tb-mat-error { + font-size: 13px; + } + + .tb-title { + font-size: 16px; + line-height: 24px; + + &.tb-required::after { + font-size: initial; + content: "*"; + } + + &.tb-error { + color: var(--mdc-theme-error, #f44336); + + &.tb-required::after { + color: var(--mdc-theme-error, #f44336); + } + } + } +} + +:host ::ng-deep { + .tb-form-panel .mat-expansion-panel.tb-settings { + & > .mat-expansion-panel-content > .mat-expansion-panel-body { + gap: 0; + } + } +} diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.ts b/ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.ts new file mode 100644 index 0000000000..5be07216d5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/notification/template/notification-template-configuration.component.ts @@ -0,0 +1,312 @@ +/// +/// 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, + ValidationErrors, + Validator, + Validators +} from '@angular/forms'; +import { + ActionButtonLinkType, + ActionButtonLinkTypeTranslateMap, + DeliveryMethodsTemplates, + NotificationDeliveryMethod, + NotificationDeliveryMethodInfoMap, + NotificationTemplateTypeTranslateMap, + NotificationType +} from '@shared/models/notification.models'; +import { takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; +import { isDefinedAndNotNull } from '@core/utils'; +import { coerceBoolean } from '@shared/decorators/coercion'; + +@Component({ + selector: 'tb-template-configuration', + templateUrl: './notification-template-configuration.component.html', + styleUrls: ['./notification-template-configuration.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => NotificationTemplateConfigurationComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => NotificationTemplateConfigurationComponent), + multi: true, + } + ] +}) +export class NotificationTemplateConfigurationComponent implements OnDestroy, ControlValueAccessor, Validator { + + templateConfigurationForm: FormGroup; + + NotificationDeliveryMethodInfoMap = NotificationDeliveryMethodInfoMap; + + @Input() + set predefinedDeliveryMethodsTemplate(value: Partial) { + if (isDefinedAndNotNull(value)) { + this.templateConfigurationForm.patchValue(value, {emitEvent: false}); + this.updateDisabledForms(); + this.templateConfigurationForm.updateValueAndValidity(); + } + } + + @Input() + notificationType: NotificationType; + + @Input() + @coerceBoolean() + interacted: boolean; + + readonly NotificationDeliveryMethod = NotificationDeliveryMethod; + readonly NotificationTemplateTypeTranslateMap = NotificationTemplateTypeTranslateMap; + + readonly actionButtonLinkType = ActionButtonLinkType; + readonly actionButtonLinkTypes = Object.keys(ActionButtonLinkType) as ActionButtonLinkType[]; + readonly actionButtonLinkTypeTranslateMap = ActionButtonLinkTypeTranslateMap; + + tinyMceOptions: Record = { + base_url: '/assets/tinymce', + suffix: '.min', + plugins: ['link table image imagetools code fullscreen'], + menubar: 'edit insert tools view format table', + toolbar: 'fontselect fontsizeselect | formatselect | bold italic strikethrough forecolor backcolor ' + + '| link | table | image | alignleft aligncenter alignright alignjustify ' + + '| numlist bullist outdent indent | removeformat | code | fullscreen', + toolbar_mode: 'sliding', + height: 400, + autofocus: false, + branding: false + }; + + private propagateChange = (v: any) => { }; + private readonly destroy$ = new Subject(); + + constructor(private fb: FormBuilder) { + this.templateConfigurationForm = this.buildForm(); + this.templateConfigurationForm.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + this.propagateChange(value); + }); + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + + writeValue(value: any) { + this.templateConfigurationForm.patchValue(value, {emitEvent: false}); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean) { + if (isDisabled) { + this.templateConfigurationForm.disable({emitEvent: false}); + } else { + this.updateDisabledForms(); + } + } + + validate(): ValidationErrors { + return this.templateConfigurationForm.valid ? null : { + templateConfiguration: { + valid: false, + }, + }; + } + + private updateDisabledForms(){ + Object.values(NotificationDeliveryMethod).forEach((method) => { + const form = this.templateConfigurationForm.get(method); + if (!form.get('enabled').value) { + form.disable({emitEvent: false}); + } else { + form.enable({emitEvent: false}); + switch (method) { + case NotificationDeliveryMethod.WEB: + form.get('additionalConfig.icon.enabled').updateValueAndValidity({onlySelf: true}); + form.get('additionalConfig.actionButtonConfig.enabled').updateValueAndValidity({onlySelf: true}); + break; + case NotificationDeliveryMethod.MICROSOFT_TEAMS: + form.get('button.enabled').updateValueAndValidity({onlySelf: true}); + break; + case NotificationDeliveryMethod.MOBILE_APP: + form.get('additionalConfig.onClick.enabled').updateValueAndValidity({onlySelf: true}); + } + } + }); + } + + private buildForm(): FormGroup { + const form = this.fb.group({}); + + Object.values(NotificationDeliveryMethod).forEach((method) => { + form.addControl(method, this.buildDeliveryMethodControl(method), {emitEvent: false}); + }); + + return form; + } + + private buildDeliveryMethodControl(deliveryMethod: NotificationDeliveryMethod): FormGroup { + let deliveryMethodForm: FormGroup; + switch (deliveryMethod) { + case NotificationDeliveryMethod.WEB: + deliveryMethodForm = this.fb.group({ + subject: ['', Validators.required], + body: ['', Validators.required], + additionalConfig: this.fb.group({ + icon: this.fb.group({ + enabled: [false], + icon: [{value: 'notifications', disabled: true}, Validators.required], + color: [{value: '#757575', disabled: true}] + }), + actionButtonConfig: this.createButtonConfigForm() + }) + }); + + deliveryMethodForm.get('additionalConfig.icon.enabled').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + if (value) { + deliveryMethodForm.get('additionalConfig.icon.icon').enable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.icon.color').enable({emitEvent: false}); + } else { + deliveryMethodForm.get('additionalConfig.icon.icon').disable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.icon.color').disable({emitEvent: false}); + } + }); + break; + case NotificationDeliveryMethod.EMAIL: + deliveryMethodForm = this.fb.group({ + subject: ['', Validators.required], + body: ['', Validators.required] + }); + break; + case NotificationDeliveryMethod.SMS: + deliveryMethodForm = this.fb.group({ + body: ['', [Validators.required, Validators.maxLength(320)]] + }); + break; + case NotificationDeliveryMethod.SLACK: + deliveryMethodForm = this.fb.group({ + body: ['', Validators.required] + }); + break; + case NotificationDeliveryMethod.MOBILE_APP: + deliveryMethodForm = this.fb.group({ + subject: ['', Validators.required], + body: ['', Validators.required], + additionalConfig: this.fb.group({ + onClick: this.fb.group({ + enabled: [false], + linkType: [{value: ActionButtonLinkType.DASHBOARD, disabled: true}], + dashboardId: [{value: null, disabled: true}, Validators.required], + dashboardState: [{value: null, disabled: true}], + setEntityIdInState: [{value: true, disabled: true}] + }) + }) + }); + deliveryMethodForm.get('additionalConfig.onClick.enabled').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + if (value) { + deliveryMethodForm.get('additionalConfig.onClick.linkType').enable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.onClick.dashboardId').enable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.onClick.dashboardState').enable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.onClick.setEntityIdInState').enable({emitEvent: false}); + } else { + deliveryMethodForm.get('additionalConfig.onClick.linkType').disable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.onClick.dashboardId').disable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.onClick.dashboardState').disable({emitEvent: false}); + deliveryMethodForm.get('additionalConfig.onClick.setEntityIdInState').disable({emitEvent: false}); + } + }); + break; + case NotificationDeliveryMethod.MICROSOFT_TEAMS: + deliveryMethodForm = this.fb.group({ + subject: [''], + body: ['', Validators.required], + themeColor: [''], + button: this.createButtonConfigForm() + }); + break; + default: + throw new Error(`Not configured templated for notification delivery method: ${deliveryMethod}`); + } + deliveryMethodForm.addControl('enabled', this.fb.control(false), {emitEvent: false}); + deliveryMethodForm.addControl('method', this.fb.control(deliveryMethod), {emitEvent: false}); + return deliveryMethodForm; + } + + private createButtonConfigForm(): FormGroup { + const form = this.fb.group({ + enabled: [false], + text: [{value: '', disabled: true}, [Validators.required, Validators.maxLength(50)]], + linkType: [ActionButtonLinkType.LINK], + link: [{value: '', disabled: true}, Validators.required], + dashboardId: [{value: null, disabled: true}, Validators.required], + dashboardState: [{value: null, disabled: true}], + setEntityIdInState: [{value: true, disabled: true}] + }); + + form.get('enabled').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + if (value) { + form.enable({emitEvent: false}); + form.get('linkType').updateValueAndValidity({onlySelf: true}); + } else { + form.disable({emitEvent: false}); + form.get('enabled').enable({emitEvent: false}); + } + }); + + form.get('linkType').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + const isEnabled = form.get('enabled').value; + if (isEnabled) { + if (value === ActionButtonLinkType.LINK) { + form.get('link').enable({emitEvent: false}); + form.get('dashboardId').disable({emitEvent: false}); + form.get('dashboardState').disable({emitEvent: false}); + form.get('setEntityIdInState').disable({emitEvent: false}); + } else { + form.get('link').disable({emitEvent: false}); + form.get('dashboardId').enable({emitEvent: false}); + form.get('dashboardState').enable({emitEvent: false}); + form.get('setEntityIdInState').enable({emitEvent: false}); + } + } + }); + return form; + } +} diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-configuration.ts b/ui-ngx/src/app/modules/home/pages/notification/template/template-configuration.ts index a53a3eada5..3da842661d 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-configuration.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-configuration.ts @@ -16,10 +16,9 @@ import { FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms'; import { - ActionButtonLinkType, - ActionButtonLinkTypeTranslateMap, + DeliveryMethodsTemplates, NotificationDeliveryMethod, - NotificationDeliveryMethodTranslateMap, + NotificationDeliveryMethodInfoMap, NotificationTemplate, NotificationTemplateTypeTranslateMap, NotificationType @@ -27,47 +26,25 @@ import { import { takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { Directive, OnDestroy } from '@angular/core'; +import { deepClone, deepTrim } from '@core/utils'; import { DialogComponent } from '@shared/components/dialog.component'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { Router } from '@angular/router'; import { MatDialogRef } from '@angular/material/dialog'; -import { deepClone, deepTrim } from '@core/utils'; -import tinymce from 'tinymce'; @Directive() // tslint:disable-next-line:directive-class-suffix export abstract class TemplateConfiguration extends DialogComponent implements OnDestroy{ templateNotificationForm: FormGroup; - webTemplateForm: FormGroup; - emailTemplateForm: FormGroup; - smsTemplateForm: FormGroup; - slackTemplateForm: FormGroup; - microsoftTeamsTemplateForm: FormGroup; - mobileTemplateForm: FormGroup; + notificationTemplateConfigurationForm: FormGroup; notificationDeliveryMethods = Object.keys(NotificationDeliveryMethod) as NotificationDeliveryMethod[]; - notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap; + notificationDeliveryMethodInfoMap = NotificationDeliveryMethodInfoMap; notificationTemplateTypeTranslateMap = NotificationTemplateTypeTranslateMap; - actionButtonLinkType = ActionButtonLinkType; - actionButtonLinkTypes = Object.keys(ActionButtonLinkType) as ActionButtonLinkType[]; - actionButtonLinkTypeTranslateMap = ActionButtonLinkTypeTranslateMap; - - tinyMceOptions: Record = { - base_url: '/assets/tinymce', - suffix: '.min', - plugins: ['link table image imagetools code fullscreen'], - menubar: 'edit insert tools view format table', - toolbar: 'fontselect fontsizeselect | formatselect | bold italic strikethrough forecolor backcolor ' + - '| link | table | image | alignleft aligncenter alignright alignjustify ' + - '| numlist bullist outdent indent | removeformat | code | fullscreen', - toolbar_mode: 'sliding', - height: 400, - autofocus: false, - branding: false - }; + deliveryConfiguration: Partial; protected readonly destroy$ = new Subject(); @@ -87,69 +64,22 @@ export abstract class TemplateConfiguration extends DialogComponent< }) }); - this.notificationDeliveryMethods.forEach(method => { - (this.templateNotificationForm.get('configuration.deliveryMethodsTemplates') as FormGroup) - .addControl(method, this.fb.group({enabled: method === NotificationDeliveryMethod.WEB}), {emitEvent: false}); - }); - - this.webTemplateForm = this.fb.group({ - subject: ['', Validators.required], - body: ['', Validators.required], - additionalConfig: this.fb.group({ - icon: this.fb.group({ - enabled: [false], - icon: [{value: 'notifications', disabled: true}, Validators.required], - color: [{value: '#757575', disabled: true}] - }), - actionButtonConfig: this.createButtonConfigForm() - }) - }); - - this.webTemplateForm.get('additionalConfig.icon.enabled').valueChanges.pipe( + this.templateNotificationForm.get('configuration.deliveryMethodsTemplates').valueChanges.pipe( takeUntil(this.destroy$) ).subscribe((value) => { - if (value) { - this.webTemplateForm.get('additionalConfig.icon.icon').enable({emitEvent: false}); - this.webTemplateForm.get('additionalConfig.icon.color').enable({emitEvent: false}); - } else { - this.webTemplateForm.get('additionalConfig.icon.icon').disable({emitEvent: false}); - this.webTemplateForm.get('additionalConfig.icon.color').disable({emitEvent: false}); - } + this.deliveryConfiguration = value; }); - this.emailTemplateForm = this.fb.group({ - subject: ['', Validators.required], - body: ['', Validators.required] + this.notificationTemplateConfigurationForm = this.fb.group({ + deliveryMethodsTemplates: null }); - this.smsTemplateForm = this.fb.group({ - body: ['', [Validators.required, Validators.maxLength(320)]] - }); - - this.slackTemplateForm = this.fb.group({ - body: ['', Validators.required] - }); - - this.mobileTemplateForm = this.fb.group({ - subject: ['', Validators.required], - body: ['', Validators.required] - }); - - this.microsoftTeamsTemplateForm = this.fb.group({ - subject: [''], - body: ['', Validators.required], - themeColor: [''], - button: this.createButtonConfigForm() + this.notificationDeliveryMethods.forEach(method => { + (this.templateNotificationForm.get('configuration.deliveryMethodsTemplates') as FormGroup) + .addControl(method, this.fb.group({enabled: method === NotificationDeliveryMethod.WEB}), {emitEvent: false}); }); - this.deliveryMethodFormsMap = new Map([ - [NotificationDeliveryMethod.WEB, this.webTemplateForm], - [NotificationDeliveryMethod.EMAIL, this.emailTemplateForm], - [NotificationDeliveryMethod.SMS, this.smsTemplateForm], - [NotificationDeliveryMethod.SLACK, this.slackTemplateForm], - [NotificationDeliveryMethod.MICROSOFT_TEAMS, this.microsoftTeamsTemplateForm], - [NotificationDeliveryMethod.MOBILE_APP, this.mobileTemplateForm] - ]); + this.deliveryConfiguration = this.templateNotificationForm.get('configuration.deliveryMethodsTemplates').value; } ngOnDestroy() { @@ -169,58 +99,8 @@ export abstract class TemplateConfiguration extends DialogComponent< } protected getNotificationTemplateValue(): NotificationTemplate { - const template: NotificationTemplate = deepClone(this.templateNotificationForm.value); - this.notificationDeliveryMethods.forEach(method => { - if (template.configuration.deliveryMethodsTemplates[method]?.enabled) { - Object.assign(template.configuration.deliveryMethodsTemplates[method], this.deliveryMethodFormsMap.get(method).value, {method}); - } else { - delete template.configuration.deliveryMethodsTemplates[method]; - } - }); + const template = deepClone(this.templateNotificationForm.value); + template.configuration = deepClone(this.notificationTemplateConfigurationForm.value); return deepTrim(template); } - - private createButtonConfigForm(): FormGroup { - const form = this.fb.group({ - enabled: [false], - text: [{value: '', disabled: true}, [Validators.required, Validators.maxLength(50)]], - linkType: [ActionButtonLinkType.LINK], - link: [{value: '', disabled: true}, Validators.required], - dashboardId: [{value: null, disabled: true}, Validators.required], - dashboardState: [{value: null, disabled: true}], - setEntityIdInState: [{value: true, disabled: true}], - }); - - form.get('enabled').valueChanges.pipe( - takeUntil(this.destroy$) - ).subscribe((value) => { - if (value) { - form.enable({emitEvent: false}); - form.get('linkType').updateValueAndValidity({onlySelf: true}); - } else { - form.disable({emitEvent: false}); - form.get('enabled').enable({emitEvent: false}); - } - }); - - form.get('linkType').valueChanges.pipe( - takeUntil(this.destroy$) - ).subscribe((value) => { - const isEnabled = form.get('enabled').value; - if (isEnabled) { - if (value === ActionButtonLinkType.LINK) { - form.get('link').enable({emitEvent: false}); - form.get('dashboardId').disable({emitEvent: false}); - form.get('dashboardState').disable({emitEvent: false}); - form.get('setEntityIdInState').disable({emitEvent: false}); - } else { - form.get('link').disable({emitEvent: false}); - form.get('dashboardId').enable({emitEvent: false}); - form.get('dashboardState').enable({emitEvent: false}); - form.get('setEntityIdInState').enable({emitEvent: false}); - } - } - }); - return form; - } } diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html index 3df482f633..09e673bb4b 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html @@ -29,14 +29,14 @@
    check - {{ 'notification.basic-settings' | translate }} + {{ 'notification.setup' | translate }}
    notification.name @@ -62,339 +62,22 @@ class="delivery-method-container" [formGroupName]="deliveryMethods"> - {{ notificationDeliveryMethodTranslateMap.get(deliveryMethods) | translate }} + {{ notificationDeliveryMethodInfoMap.get(deliveryMethods).name | translate }}
    - - {{ 'notification.delivery-method.web' | translate }} -
    - {{ 'notification.input-fields-support-templatization' | translate}} - -
    -
    - - notification.subject - - - {{ 'notification.subject-required' | translate }} - - - - notification.message - - - {{ 'notification.message-required' | translate }} - - -
    -
    - - {{ 'icon.icon' | translate }} - -
    - - - - -
    -
    -
    - - - - - {{ 'notification.action-button' | translate }} - - - - -
    - - notification.button-text - - - {{ 'notification.button-text-required' | translate }} - - - {{ 'notification.button-text-max-length' | translate : - {length: webTemplateForm.get('additionalConfig.actionButtonConfig.text').getError('maxlength').requiredLength} - }} - - -
    -
    - - notification.action-type - - - {{ actionButtonLinkTypeTranslateMap.get(actionButtonLinkType) | translate }} - - - - - notification.link - - - {{ 'notification.link-required' | translate }} - - - - - - - - -
    - - {{ 'notification.set-entity-from-notification' | translate }} - -
    -
    -
    -
    -
    -
    - - {{ 'notification.delivery-method.email' | translate }} - -
    - {{ 'notification.input-fields-support-templatization' | translate}} - -
    -
    - - notification.subject - - - {{ 'notification.subject-required' | translate }} - - - notification.message - - - {{ 'notification.message-required' | translate }} - -
    -
    -
    - - {{ 'notification.delivery-method.sms' | translate }} -
    - {{ 'notification.input-field-support-templatization' | translate}} - -
    -
    - - notification.message - - - {{ 'notification.message-required' | translate }} - - - {{ 'notification.message-max-length' | translate : - {length: smsTemplateForm.get('body').getError('maxlength').requiredLength} - }} - - -
    -
    - - {{ 'notification.delivery-method.slack' | translate }} -
    - {{ 'notification.input-field-support-templatization' | translate}} - -
    -
    - - notification.message - - - {{ 'notification.message-required' | translate }} - - -
    -
    - - {{ 'notification.delivery-method.microsoft-teams' | translate }} -
    - {{ 'notification.input-fields-support-templatization' | translate}} - -
    -
    - - notification.subject - - - - notification.message - - - {{ 'notification.message-required' | translate }} - - -
    -
    -
    notification.theme-color
    - -
    -
    - - - - - {{ 'notification.action-button' | translate }} - - - - -
    - - notification.button-text - - - {{ 'notification.button-text-required' | translate }} - - - {{ 'notification.button-text-max-length' | translate : - {length: microsoftTeamsTemplateForm.get('button.text').getError('maxlength').requiredLength} - }} - - -
    -
    - - notification.action-type - - - {{ actionButtonLinkTypeTranslateMap.get(actionButtonLinkType) | translate }} - - - - - notification.link - - - {{ 'notification.link-required' | translate }} - - - - - - - - -
    - - {{ 'notification.set-entity-from-notification' | translate }} - -
    -
    -
    -
    -
    -
    - - {{ 'notification.delivery-method.mobile-app' | translate }} -
    - {{ 'notification.input-field-support-templatization' | translate}} - -
    -
    - - notification.subject - - - {{ 'notification.subject-required' | translate }} - - - - notification.message - - - {{ 'notification.message-required' | translate }} - - + + {{ 'notification.compose' | translate }} + + +
    diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.scss index 51afcfbe33..0e28d5d5e3 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.scss @@ -17,7 +17,7 @@ @import "../../../../../../theme"; :host { - width: 840px; + width: 775px; height: 100%; max-width: 100%; max-height: 100vh; @@ -62,25 +62,10 @@ } } - .tb-mat-error { - font-size: 13px; - } - .tb-hint { padding: 0 0 8px; } - .tb-hint-available-params { - border-radius: 6px; - background-color: rgba(48, 86, 128, 0.04); - margin-bottom: 8px; - padding: 8px 16px; - - .content { - vertical-align: middle; - } - } - .delivery-methods-container { margin-bottom: 20px; display: flex; @@ -125,13 +110,5 @@ } } } - - .tb-form-panel .mat-expansion-panel.tb-settings { - padding: 11px 16px; - - & > .mat-expansion-panel-content > .mat-expansion-panel-body { - gap: 0; - } - } } } diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts index cda2309ffd..a2d62c023a 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts @@ -14,13 +14,13 @@ /// limitations under the License. /// -import { NotificationDeliveryMethod, NotificationTemplate, NotificationType } from '@shared/models/notification.models'; +import { NotificationTemplate, NotificationType } from '@shared/models/notification.models'; import { Component, Inject, OnDestroy, ViewChild } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { Router } from '@angular/router'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { FormBuilder } from '@angular/forms'; +import { FormBuilder, FormGroup } from '@angular/forms'; import { NotificationService } from '@core/http/notification.service'; import { deepClone, isDefinedAndNotNull } from '@core/utils'; import { Observable } from 'rxjs'; @@ -31,8 +31,7 @@ import { BreakpointObserver } from '@angular/cdk/layout'; import { MediaBreakpoints } from '@shared/models/constants'; import { TranslateService } from '@ngx-translate/core'; import { TemplateConfiguration } from '@home/pages/notification/template/template-configuration'; -import { AuthState } from '@core/auth/auth.models'; -import { getCurrentAuthState } from '@core/auth/auth.selectors'; +import { getCurrentAuthUser } from '@core/auth/auth.selectors'; import { AuthUser } from '@shared/models/user.model'; import { Authority } from '@shared/models/authority.enum'; @@ -62,9 +61,10 @@ export class TemplateNotificationDialogComponent selectedIndex = 0; hideSelectType = false; + notificationTemplateConfigurationForm: FormGroup; + private readonly templateNotification: NotificationTemplate; - private authState: AuthState = getCurrentAuthState(this.store); - private authUser: AuthUser = this.authState.authUser; + private authUser: AuthUser = getCurrentAuthUser(this.store); constructor(protected store: Store, protected router: Router, @@ -78,7 +78,7 @@ export class TemplateNotificationDialogComponent this.notificationTypes = this.allowNotificationType(); - this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-sm']) + this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-xs']) .pipe(map(({matches}) => matches ? 'horizontal' : 'vertical')); if (isDefinedAndNotNull(this.data?.predefinedType)) { @@ -99,11 +99,9 @@ export class TemplateNotificationDialogComponent } this.templateNotificationForm.reset({}, {emitEvent: false}); this.templateNotificationForm.patchValue(this.templateNotification, {emitEvent: false}); - // eslint-disable-next-line guard-for-in - for (const method in this.templateNotification.configuration.deliveryMethodsTemplates) { - this.deliveryMethodFormsMap.get(NotificationDeliveryMethod[method]) - .patchValue(this.templateNotification.configuration.deliveryMethodsTemplates[method]); - } + this.notificationTemplateConfigurationForm.patchValue({ + deliveryMethodsTemplates: this.templateNotification.configuration.deliveryMethodsTemplates + }, {emitEvent: false}); } } @@ -119,6 +117,9 @@ export class TemplateNotificationDialogComponent changeStep($event: StepperSelectionEvent) { this.selectedIndex = $event.selectedIndex; + if ($event.previouslySelectedIndex > $event.selectedIndex) { + $event.previouslySelectedStep.interacted = false; + } } backStep() { diff --git a/ui-ngx/src/app/shared/components/notification/template-autocomplete.component.html b/ui-ngx/src/app/shared/components/notification/template-autocomplete.component.html index 4298cef045..97a17f07a2 100644 --- a/ui-ngx/src/app/shared/components/notification/template-autocomplete.component.html +++ b/ui-ngx/src/app/shared/components/notification/template-autocomplete.component.html @@ -51,7 +51,7 @@ - {{ notificationDeliveryMethodTranslateMap.get(method.key) | translate }} + {{ notificationDeliveryMethodInfoMap.get(method.key).name | translate }} diff --git a/ui-ngx/src/app/shared/components/notification/template-autocomplete.component.ts b/ui-ngx/src/app/shared/components/notification/template-autocomplete.component.ts index 9c83b3443c..12fcae7693 100644 --- a/ui-ngx/src/app/shared/components/notification/template-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/notification/template-autocomplete.component.ts @@ -28,7 +28,7 @@ import { PageLink } from '@shared/models/page/page-link'; import { Direction } from '@shared/models/page/sort-order'; import { emptyPageData } from '@shared/models/page/page-data'; import { - NotificationDeliveryMethodTranslateMap, + NotificationDeliveryMethodInfoMap, NotificationTemplate, NotificationType } from '@shared/models/notification.models'; @@ -55,7 +55,7 @@ import { coerceBoolean } from '@shared/decorators/coercion'; }) export class TemplateAutocompleteComponent implements ControlValueAccessor, OnInit { - notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap; + notificationDeliveryMethodInfoMap = NotificationDeliveryMethodInfoMap; selectTemplateFormGroup: FormGroup; @Input() diff --git a/ui-ngx/src/app/shared/components/slack-conversation-autocomplete.component.ts b/ui-ngx/src/app/shared/components/slack-conversation-autocomplete.component.ts index 0d73933c8f..39da44a13c 100644 --- a/ui-ngx/src/app/shared/components/slack-conversation-autocomplete.component.ts +++ b/ui-ngx/src/app/shared/components/slack-conversation-autocomplete.component.ts @@ -24,11 +24,7 @@ import { TranslateService } from '@ngx-translate/core'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { EntityService } from '@core/http/entity.service'; import { TruncatePipe } from '@shared/pipe/truncate.pipe'; -import { - NotificationDeliveryMethodTranslateMap, - SlackChanelType, - SlackConversation -} from '@shared/models/notification.models'; +import { SlackChanelType, SlackConversation } from '@shared/models/notification.models'; import { NotificationService } from '@core/http/notification.service'; import { isEqual } from '@core/utils'; @@ -44,7 +40,6 @@ import { isEqual } from '@core/utils'; }) export class SlackConversationAutocompleteComponent implements ControlValueAccessor, OnInit, OnChanges { - notificationDeliveryMethodTranslateMap = NotificationDeliveryMethodTranslateMap; conversationSlackFormGroup: FormGroup; @Input() diff --git a/ui-ngx/src/app/shared/models/notification.models.ts b/ui-ngx/src/app/shared/models/notification.models.ts index 4d352d352d..44451bc800 100644 --- a/ui-ngx/src/app/shared/models/notification.models.ts +++ b/ui-ngx/src/app/shared/models/notification.models.ts @@ -311,9 +311,11 @@ export interface NotificationTemplate extends Omit([ - [NotificationDeliveryMethod.WEB, 'notification.delivery-method.web'], - [NotificationDeliveryMethod.SMS, 'notification.delivery-method.sms'], - [NotificationDeliveryMethod.EMAIL, 'notification.delivery-method.email'], - [NotificationDeliveryMethod.SLACK, 'notification.delivery-method.slack'], - [NotificationDeliveryMethod.MOBILE_APP, 'notification.delivery-method.mobile-app'], - [NotificationDeliveryMethod.MICROSOFT_TEAMS, 'notification.delivery-method.microsoft-teams'] +export const NotificationDeliveryMethodInfoMap = new Map([ + [NotificationDeliveryMethod.WEB, + { + name: 'notification.delivery-method.web', + icon: 'mdi:bell-badge' + } + ], + [NotificationDeliveryMethod.SMS, + { + name: 'notification.delivery-method.sms', + icon: 'mdi:message-processing' + } + ], + [NotificationDeliveryMethod.EMAIL, + { + name: 'notification.delivery-method.email', + icon: 'mdi:email' + }], + [NotificationDeliveryMethod.SLACK, + { + name: 'notification.delivery-method.slack', + icon: 'mdi:slack' + } + ], + [NotificationDeliveryMethod.MOBILE_APP, + { + name: 'notification.delivery-method.mobile-app', + icon: 'mdi:cellphone-text' + }], + [NotificationDeliveryMethod.MICROSOFT_TEAMS, + { + name: 'notification.delivery-method.microsoft-teams', + icon: 'mdi:microsoft-teams' + }] ]); export enum NotificationRequestStatus { 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 47d6d97556..f22a599aa8 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3233,7 +3233,6 @@ "new-platform-version-trigger-settings": "New platform version trigger settings", "rate-limits-trigger-settings": "Exceeded rate limits trigger settings", "at-least-one-should-be-selected": "At least one should be selected", - "basic-settings": "Basic settings", "button-text": "Button text", "button-text-required": "Button text is required", "button-text-max-length": "Button text should be less than or equal to {{ length }} characters", @@ -3245,6 +3244,7 @@ "copy-template": "Copy template", "create-new": "Create new", "created": "Created", + "customize-messages": "Customize messages", "delete-notification-text": "Be careful, after the confirmation the notification will become unrecoverable.", "delete-notification-title": "Are you sure you want to delete the notification?", "delete-notifications-text": "Be careful, after the confirmation notifications will become unrecoverable.", @@ -3353,6 +3353,7 @@ "notify-only-user-comments": "Notify only user comments", "only-rule-chain-lifecycle-failures": "Only rule chain lifecycle failures", "only-rule-node-lifecycle-failures": "Only rule node lifecycle failures", + "open-dashboard-on-click-notification": "Open dashboard on click notification", "platform-users": "Platform users", "rate-limits": "Rate limits", "rate-limits-hint": "If the field is empty, the trigger will be applied to all rate limits", @@ -3405,6 +3406,7 @@ "selected-template": "{ count, plural, =1 {1 template} other {# templates} } selected", "send-notification": "Send notification", "sent": "Sent", + "setup": "Setup", "notification-sent": "Notifications / Sent", "set-entity-from-notification": "Set entity from notification to dashboard state", "slack-chanel-type": "Slack channel type", From 0cd012667220690b2bd185409ba809de15e4b5fe Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Thu, 8 Feb 2024 17:12:29 +0200 Subject: [PATCH 198/397] changed default value for CASSANDRA_QUERY_SET_NULL_VALUES_ENABLED from false to true --- application/src/main/resources/thingsboard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 4aab3760a3..0df8f29566 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -309,7 +309,7 @@ cassandra: # Interval in milliseconds for printing Cassandra query queue statistic rate_limit_print_interval_ms: "${CASSANDRA_QUERY_RATE_LIMIT_PRINT_MS:10000}" # set all data type values except target to null for the same ts on save - set_null_values_enabled: "${CASSANDRA_QUERY_SET_NULL_VALUES_ENABLED:false}" + set_null_values_enabled: "${CASSANDRA_QUERY_SET_NULL_VALUES_ENABLED:true}" # log one of cassandra queries with specified frequency (0 - logging is disabled) print_queries_freq: "${CASSANDRA_QUERY_PRINT_FREQ:0}" tenant_rate_limits: From c1f16769f47a1d606a16ba61769ae30993660084 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Fri, 9 Feb 2024 14:15:24 +0200 Subject: [PATCH 199/397] Fix partition change event ignored --- .../actors/service/DefaultActorService.java | 6 ++++++ .../AbstractPartitionBasedService.java | 13 ++++++++----- .../queue/DefaultTbCoreConsumerService.java | 18 ++++++++---------- .../DefaultTbRuleEngineConsumerService.java | 18 ++++++++---------- .../processing/AbstractConsumerService.java | 5 +++++ .../discovery/TbApplicationEventListener.java | 12 +++++++++--- 6 files changed, 44 insertions(+), 28 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java b/application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java index 87831cb8f6..0ecdb183b5 100644 --- a/application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java +++ b/application/src/main/java/org/thingsboard/server/actors/service/DefaultActorService.java @@ -31,6 +31,7 @@ import org.thingsboard.server.actors.app.AppActor; import org.thingsboard.server.actors.app.AppInitMsg; import org.thingsboard.server.actors.stats.StatsActor; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; +import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.queue.discovery.TbApplicationEventListener; import org.thingsboard.server.queue.discovery.event.PartitionChangeEvent; import org.thingsboard.server.queue.util.AfterStartUp; @@ -124,6 +125,11 @@ public class DefaultActorService extends TbApplicationEventListener extends */ @Override protected void onTbApplicationEvent(PartitionChangeEvent partitionChangeEvent) { - if (getServiceType().equals(partitionChangeEvent.getServiceType())) { - log.debug("onTbApplicationEvent, processing event: {}", partitionChangeEvent); - subscribeQueue.add(partitionChangeEvent.getPartitions()); - scheduledExecutor.submit(this::pollInitStateFromDB); - } + log.debug("onTbApplicationEvent, processing event: {}", partitionChangeEvent); + subscribeQueue.add(partitionChangeEvent.getPartitions()); + scheduledExecutor.submit(this::pollInitStateFromDB); + } + + @Override + protected boolean filterTbApplicationEvent(PartitionChangeEvent event) { + return getServiceType().equals(event.getServiceType()); } protected void pollInitStateFromDB() { diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index f544c4fe25..f846d8ce28 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -220,16 +220,14 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService tpi.newByTopic(usageStatsConsumer.getTopic())) - .collect(Collectors.toSet())); - } + log.info("Subscribing to partitions: {}", event.getPartitions()); + this.mainConsumer.subscribe(event.getPartitions()); + this.usageStatsConsumer.subscribe( + event + .getPartitions() + .stream() + .map(tpi -> tpi.newByTopic(usageStatsConsumer.getTopic())) + .collect(Collectors.toSet())); this.firmwareStatesConsumer.subscribe(); } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java index 6a205ed5a2..236b85e205 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java @@ -110,16 +110,14 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< @Override protected void onTbApplicationEvent(PartitionChangeEvent event) { - if (event.getServiceType().equals(getServiceType())) { - event.getPartitionsMap().forEach((queueKey, partitions) -> { - var consumer = consumers.get(queueKey); - if (consumer != null) { - consumer.update(partitions); - } else { - log.warn("Received invalid partition change event for {} that is not managed by this service", queueKey); - } - }); - } + event.getPartitionsMap().forEach((queueKey, partitions) -> { + var consumer = consumers.get(queueKey); + if (consumer != null) { + consumer.update(partitions); + } else { + log.warn("Received invalid partition change event for {} that is not managed by this service", queueKey); + } + }); } @AfterStartUp(order = AfterStartUp.REGULAR_SERVICE) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java index a8252e7fa0..8a728d6579 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/processing/AbstractConsumerService.java @@ -108,6 +108,11 @@ public abstract class AbstractConsumerService implements ApplicationListener { private int lastProcessedSequenceNumber = Integer.MIN_VALUE; private final Lock seqNumberLock = new ReentrantLock(); + private final Logger log = LoggerFactory.getLogger(getClass()); + @Override public void onApplicationEvent(T event) { + if (!filterTbApplicationEvent(event)) { + log.trace("Skipping event due to filter: {}", event); + return; + } boolean validUpdate = false; seqNumberLock.lock(); try { @@ -40,7 +46,7 @@ public abstract class TbApplicationEventListener i } finally { seqNumberLock.unlock(); } - if (validUpdate && filterTbApplicationEvent(event)) { + if (validUpdate) { try { onTbApplicationEvent(event); } catch (Exception e) { From 1132415729e2be5ab3966f9a738f2c04661a8899 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Fri, 9 Feb 2024 14:24:03 +0200 Subject: [PATCH 200/397] Fix generator node stopping --- .../rule/engine/debug/TbMsgGeneratorNode.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) 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 b31c98bc0f..54bfbe4b88 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 @@ -72,7 +72,6 @@ public class TbMsgGeneratorNode implements TbNode { @Override public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { - log.trace("init generator with config {}", configuration); this.config = TbNodeUtils.convert(configuration, TbMsgGeneratorNodeConfiguration.class); this.delay = TimeUnit.SECONDS.toMillis(config.getPeriodInSeconds()); this.currentMsgCount = 0; @@ -82,17 +81,18 @@ public class TbMsgGeneratorNode implements TbNode { } else { originatorId = ctx.getSelfId(); } + log.debug("[{}] Initializing generator with config {}", originatorId, configuration); updateGeneratorState(ctx); } @Override public void onPartitionChangeMsg(TbContext ctx, PartitionChangeMsg msg) { - log.trace("onPartitionChangeMsg, PartitionChangeMsg {}, config {}", msg, config); + log.debug("[{}] Handling partition change msg: {}", originatorId, msg); updateGeneratorState(ctx); } private void updateGeneratorState(TbContext ctx) { - log.trace("updateGeneratorState, config {}", config); + log.trace("[{}] Updating generator state, config {}", originatorId, config); if (ctx.isLocalEntity(originatorId)) { if (initialized.compareAndSet(false, true)) { this.scriptEngine = ctx.createScriptEngine(config.getScriptLang(), @@ -106,7 +106,7 @@ public class TbMsgGeneratorNode implements TbNode { @Override public void onMsg(TbContext ctx, TbMsg msg) { - log.trace("onMsg, config {}, msg {}", config, msg); + log.trace("[{}] onMsg. Expected msg id: {}, msg: {}, config: {}", originatorId, nextTickId, msg, config); if (initialized.get() && msg.isTypeOf(TbMsgType.GENERATOR_NODE_SELF_MSG) && msg.getId().equals(nextTickId)) { TbStopWatch sw = TbStopWatch.create(); withCallback(generate(ctx, msg), @@ -130,7 +130,6 @@ public class TbMsgGeneratorNode implements TbNode { } private void scheduleTickMsg(TbContext ctx, TbMsg msg) { - log.trace("scheduleTickMsg, config {}", config); long curTs = System.currentTimeMillis(); if (lastScheduledTs == 0L) { lastScheduledTs = curTs; @@ -141,6 +140,7 @@ public class TbMsgGeneratorNode implements TbNode { getCustomerIdFromMsg(msg), TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING); nextTickId = tickMsg.getId(); ctx.tellSelf(tickMsg, curDelay); + log.trace("[{}] Scheduled tick msg with delay {}, msg: {}, config: {}", originatorId, curDelay, tickMsg, config); } private ListenableFuture generate(TbContext ctx, TbMsg msg) { @@ -167,8 +167,11 @@ public class TbMsgGeneratorNode implements TbNode { @Override public void destroy() { - log.trace("destroy, config {}", config); + log.debug("[{}] Stopping generator", originatorId); + initialized.set(false); prevMsg = null; + nextTickId = null; + lastScheduledTs = 0; if (scriptEngine != null) { scriptEngine.destroy(); scriptEngine = null; From 9fa36c7a2d5109b4cdbe9adcad7daec3426a2f72 Mon Sep 17 00:00:00 2001 From: nick Date: Fri, 9 Feb 2024 16:18:30 +0200 Subject: [PATCH 201/397] lwm2m: delete from Root Application:"org.eclipse.leshan.server.observation.ObservationServiceImpl --- .../observation/ObservationServiceImpl.java | 296 ------------------ ...cLwm2MIntegrationObserveCompositeTest.java | 8 +- .../sql/RpcLwm2mIntegrationObserveTest.java | 20 +- .../DefaultLwM2mDownlinkMsgHandler.java | 31 +- 4 files changed, 39 insertions(+), 316 deletions(-) delete mode 100644 application/src/main/java/org/eclipse/leshan/server/observation/ObservationServiceImpl.java diff --git a/application/src/main/java/org/eclipse/leshan/server/observation/ObservationServiceImpl.java b/application/src/main/java/org/eclipse/leshan/server/observation/ObservationServiceImpl.java deleted file mode 100644 index 89a2f07179..0000000000 --- a/application/src/main/java/org/eclipse/leshan/server/observation/ObservationServiceImpl.java +++ /dev/null @@ -1,296 +0,0 @@ -/** - * Copyright © 2016-2024 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (c) 2016 Sierra Wireless and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v2.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v20.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.html. - * - * Contributors: - * Sierra Wireless - initial API and implementation - * Michał Wadowski (Orange) - Add Observe-Composite feature. - */ -package org.eclipse.leshan.server.observation; - -import lombok.extern.slf4j.Slf4j; -import org.eclipse.leshan.core.node.LwM2mPath; -import org.eclipse.leshan.core.observation.CompositeObservation; -import org.eclipse.leshan.core.observation.Observation; -import org.eclipse.leshan.core.observation.SingleObservation; -import org.eclipse.leshan.core.peer.LwM2mPeer; -import org.eclipse.leshan.core.response.ObserveCompositeResponse; -import org.eclipse.leshan.core.response.ObserveResponse; -import org.eclipse.leshan.server.endpoint.LwM2mServerEndpoint; -import org.eclipse.leshan.server.endpoint.LwM2mServerEndpointsProvider; -import org.eclipse.leshan.server.profile.ClientProfile; -import org.eclipse.leshan.server.registration.Registration; -import org.eclipse.leshan.server.registration.RegistrationStore; -import org.eclipse.leshan.server.registration.RegistrationUpdate; -import org.eclipse.leshan.server.registration.UpdatedRegistration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * Implementation of the {@link ObservationService} accessing the persisted observation via the provided - * {@link RegistrationStore}. - * - * When a new observation is added or changed or canceled, the registered listeners are notified. - */ -@Slf4j -public class ObservationServiceImpl implements ObservationService, LwM2mNotificationReceiver { - - private final Logger LOG = LoggerFactory.getLogger(ObservationServiceImpl.class); - - private final RegistrationStore registrationStore; - private final LwM2mServerEndpointsProvider endpointProvider; - private final boolean updateRegistrationOnNotification; - - private final List listeners = new CopyOnWriteArrayList<>();; - - /** - * Creates an instance of {@link ObservationServiceImpl} - */ - public ObservationServiceImpl(RegistrationStore store, LwM2mServerEndpointsProvider endpointProvider) { - this(store, endpointProvider, false); - } - - /** - * Creates an instance of {@link ObservationServiceImpl} - * - * @param updateRegistrationOnNotification will activate registration update on observe notification. - * - * @since 1.1 - */ - public ObservationServiceImpl(RegistrationStore store, LwM2mServerEndpointsProvider endpointProvider, - boolean updateRegistrationOnNotification) { - this.registrationStore = store; - this.updateRegistrationOnNotification = updateRegistrationOnNotification; - this.endpointProvider = endpointProvider; - } - - @Override - public int cancelObservations(Registration registration) { - // check registration id - String registrationId = registration.getId(); - if (registrationId == null) - return 0; - - Collection observations = registrationStore.removeObservations(registrationId); - if (observations == null) - return 0; - - for (Observation observation : observations) { - cancel(observation); - } - - return observations.size(); - } - - @Override - public int cancelObservations(Registration registration, String nodePath) { - if (registration == null || registration.getId() == null || nodePath == null || nodePath.isEmpty()) - return 0; - - Set observations = getObservationsForCancel(registration.getId(), nodePath); - for (Observation observation : observations) { - cancelObservation(observation); - } - return observations.size(); - } - - @Override - public int cancelCompositeObservations(Registration registration, String[] nodePaths) { - if (registration == null || registration.getId() == null || nodePaths == null || nodePaths.length == 0) - return 0; - - Set observations = getCompositeObservationsForCancel(registration.getId(), nodePaths); - for (Observation observation : observations) { - cancelObservation(observation); - } - return observations.size(); - } - - @Override - public void cancelObservation(Observation observation) { - if (observation == null) - return; - - registrationStore.removeObservation(observation.getRegistrationId(), observation.getId()); - cancel(observation); - } - - private void cancel(Observation observation) { - List endpoints = endpointProvider.getEndpoints(); - for (LwM2mServerEndpoint lwM2mEndpoint : endpoints) { - lwM2mEndpoint.cancelObservation(observation); - } - - for (ObservationListener listener : listeners) { - listener.cancelled(observation); - } - } - - @Override - public Set getObservations(Registration registration) { - return getObservations(registration.getId()); - } - - private Set getObservations(String registrationId) { - if (registrationId == null) - return Collections.emptySet(); - - return new HashSet<>(registrationStore.getObservations(registrationId)); - } - - private Set getCompositeObservationsForCancel(String registrationId, String[] nodePaths) { - if (registrationId == null || nodePaths == null) - return Collections.emptySet(); - - // array of String to array of LWM2M path - List lwPaths = new ArrayList<>(nodePaths.length); - for (int i = 0; i < nodePaths.length; i++) { - lwPaths.add(new LwM2mPath(nodePaths[i])); - } - - // search composite-observation - Set result = new HashSet<>(); - for (Observation obs : getObservations(registrationId)) { - if (obs instanceof CompositeObservation) { - if (lwPaths.equals(((CompositeObservation) obs).getPaths())) { - result.add(obs); - } - } - } - return result; - } - - private Set getObservationsForCancel(String registrationId, String nodePath) { - if (registrationId == null || nodePath == null) - return Collections.emptySet(); - - Set result = new HashSet<>(); - LwM2mPath lwPath = new LwM2mPath(nodePath); - for (Observation obs : getObservations(registrationId)) { - if (obs instanceof SingleObservation) { - LwM2mPath lwPathObs = ((SingleObservation) obs).getPath(); - if (lwPath.equals(lwPathObs) || lwPathObs.startWith(lwPath)) { // nodePath = "3", lwPathObs = "3/0/9": cancel for tne all lwPathObs - result.add(obs); - } else if (!lwPath.equals(lwPathObs) && lwPath.startWith(lwPathObs)) { // nodePath = "3/0/9", lwPathObs = "3": error... - String errorMsg = String.format( - "Unexpected error : There is registration with id [%s] existing observation [%s] includes input observation [%s]!", - registrationId, lwPathObs, lwPath); - throw new IllegalStateException(errorMsg); - } - } - } - - return result; - } - - @Override - public void addListener(ObservationListener listener) { - listeners.add(listener); - } - - @Override - public void removeListener(ObservationListener listener) { - listeners.remove(listener); - } - - private Registration updateRegistrationOnRegistration(Observation observation, LwM2mPeer sender, - ClientProfile profile) { - if (updateRegistrationOnNotification) { - RegistrationUpdate regUpdate = new RegistrationUpdate(observation.getRegistrationId(), sender, null, null, - null, null, null, null, null, null, null, null); - UpdatedRegistration updatedRegistration = registrationStore.updateRegistration(regUpdate); - if (updatedRegistration == null || updatedRegistration.getUpdatedRegistration() == null) { - String errorMsg = String.format( - "Unexpected error: There is no registration with id %s for this observation %s", - observation.getRegistrationId(), observation); - LOG.error(errorMsg); - throw new IllegalStateException(errorMsg); - } - return updatedRegistration.getUpdatedRegistration(); - } - return profile.getRegistration(); - } - - // ********** NotificationListener interface **********// - @Override - public void onNotification(SingleObservation observation, LwM2mPeer sender, ClientProfile profile, - ObserveResponse response) { - try { - Registration updatedRegistration = updateRegistrationOnRegistration(observation, sender, profile); - for (ObservationListener listener : listeners) { - listener.onResponse(observation, updatedRegistration, response); - } - } catch (Exception e) { - for (ObservationListener listener : listeners) { - listener.onError(observation, profile.getRegistration(), e); - } - } - } - - @Override - public void onNotification(CompositeObservation observation, LwM2mPeer sender, ClientProfile profile, - ObserveCompositeResponse response) { - try { - Registration updatedRegistration = updateRegistrationOnRegistration(observation, sender, profile); - for (ObservationListener listener : listeners) { - listener.onResponse(observation, updatedRegistration, response); - } - } catch (Exception e) { - for (ObservationListener listener : listeners) { - listener.onError(observation, profile.getRegistration(), e); - } - } - } - - @Override - public void onError(Observation observation, LwM2mPeer sender, ClientProfile profile, Exception error) { - for (ObservationListener listener : listeners) { - listener.onError(observation, profile.getRegistration(), error); - } - } - - @Override - public void newObservation(Observation observation, Registration registration) { - for (ObservationListener listener : listeners) { - listener.newObservation(observation, registration); - } - } - - @Override - public void cancelled(Observation observation) { - for (ObservationListener listener : listeners) { - listener.cancelled(observation); - } - - } -} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2MIntegrationObserveCompositeTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2MIntegrationObserveCompositeTest.java index 86cd8186c7..94ee1eb48e 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2MIntegrationObserveCompositeTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2MIntegrationObserveCompositeTest.java @@ -355,8 +355,8 @@ public class RpcLwm2MIntegrationObserveCompositeTest extends AbstractRpcLwM2MInt } /** - * ObserveComposite {"ids":["/3/0/9", "/3/0/14", "/5/0/3", "/19/1/0/0"]} - Ok - * ObserveCompositeCancel {"ids":["/3", "/19/1/0/0"]} - Ok + * ObserveComposite {"ids":["/3/0/9", "/5/0/5", "/5/0/3", "/5/0/7", "/19/1/0/0"]} - Ok + * ObserveCompositeCancel {"ids":["/5", "/19/1/0/0"]} - Ok * last Observation * @throws Exception */ @@ -380,7 +380,7 @@ public class RpcLwm2MIntegrationObserveCompositeTest extends AbstractRpcLwM2MInt actualResult = sendCompositeRPCByIds("ObserveCompositeCancel", expectedIds); rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); - assertEquals("4", rpcActualResult.get("value").asText()); + assertEquals("4", rpcActualResult.get("value").asText()); // CNT = 4 ("/5/0/5", "/5/0/3", "/5/0/7", "/19/1/0/0"9) String actualResultReadAll = sendCompositeRPCByKeys("ObserveReadAll", null); ObjectNode rpcActualResultReadAll = JacksonUtil.fromString(actualResultReadAll, ObjectNode.class); @@ -411,7 +411,7 @@ public class RpcLwm2MIntegrationObserveCompositeTest extends AbstractRpcLwM2MInt actualResult = sendCompositeRPCByIds("ObserveCompositeCancel", expectedIds); rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); - String expectedValue = "for observation path " + fromVersionedIdToObjectId(idVer_3_0_9) + ", that includes this observation path " + fromVersionedIdToObjectId(objectIdVer_3); + String expectedValue = "for observation path [" + fromVersionedIdToObjectId(objectIdVer_3) + "], that includes this observation path [" + fromVersionedIdToObjectId(idVer_3_0_9); assertTrue(rpcActualResult.get("error").asText().contains(expectedValue)); // ObserveCompositeCancel diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java index bf1ba41270..5a849e70e4 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/sql/RpcLwm2mIntegrationObserveTest.java @@ -333,9 +333,9 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO // cancel observe "/3_1.2/0/9" String expectedId_3_0_9 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_9; String actualResult = sendRpcObserve("ObserveCancel", expectedId_3_0_9); - String expectedValue = "existing observation [" + fromVersionedIdToObjectId(objectIdVer_3) + "] includes input observation [" + fromVersionedIdToObjectId(expectedId_3_0_9); + String expectedValue = "for observation path [" + fromVersionedIdToObjectId(objectIdVer_3) + "], that includes this observation path [" + fromVersionedIdToObjectId(expectedId_3_0_9); rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); - assertEquals(ResponseCode.INTERNAL_SERVER_ERROR.getName(), rpcActualResult.get("result").asText()); + assertEquals(ResponseCode.BAD_REQUEST.getName(), rpcActualResult.get("result").asText()); assertTrue(rpcActualResult.get("error").asText().contains(expectedValue)); // cancel observe "/3_1.2" @@ -346,29 +346,33 @@ public class RpcLwm2mIntegrationObserveTest extends AbstractRpcLwM2MIntegrationO } /** + * Observe {"id":"/3/0/0"} * Observe {"id":"/3/0/9"} - * ObserveCancel {"id":"/3"} + * ObserveCancel {"id":"/3"} - Ok, cnt = 2 */ @Test public void testObserveResource_ObserveCancelObject_Result_CONTENT_Count_1() throws Exception { sendCancelObserveAllWithAwait(deviceId); - + String expectedId_3_0_0 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_0; + sendRpcObserve("Observe", expectedId_3_0_0); String expectedId_3_0_9 = objectInstanceIdVer_3 + "/" + RESOURCE_ID_9; sendRpcObserve("Observe", expectedId_3_0_9); String actualResultReadAll = sendRpcObserve("ObserveReadAll", null); ObjectNode rpcActualResult = JacksonUtil.fromString(actualResultReadAll, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); String actualValuesReadAll = rpcActualResult.get("value").asText(); - assertEquals(1, actualValuesReadAll.split(",").length); - String expected = "\"SingleObservation:" + fromVersionedIdToObjectId(expectedId_3_0_9) + "\""; - assertTrue(actualValuesReadAll.contains(expected)); + assertEquals(2, actualValuesReadAll.split(",").length); + String expected_3_0_0 = "\"SingleObservation:" + fromVersionedIdToObjectId(expectedId_3_0_0) + "\""; + String expected_3_0_9 = "\"SingleObservation:" + fromVersionedIdToObjectId(expectedId_3_0_9) + "\""; + assertTrue(actualValuesReadAll.contains(expected_3_0_0)); + assertTrue(actualValuesReadAll.contains(expected_3_0_9)); // cancel observe "/3_1.2" String expectedId_3 = objectIdVer_3; String actualResult = sendRpcObserve("ObserveCancel", expectedId_3); rpcActualResult = JacksonUtil.fromString(actualResult, ObjectNode.class); assertEquals(ResponseCode.CONTENT.getName(), rpcActualResult.get("result").asText()); - assertEquals("1", rpcActualResult.get("value").asText()); + assertEquals("2", rpcActualResult.get("value").asText()); } private String sendRpcObserve(String method, String params) throws Exception { diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java index d8cd2b44ba..af127dba88 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/downlink/DefaultLwM2mDownlinkMsgHandler.java @@ -259,7 +259,7 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im for (Observation obs : observations) { LwM2mPath lwPathObs = ((SingleObservation) obs).getPath(); for (LwM2mPath nodePath : listPath) { - String validNodePath = validatePathCompositeCancel(nodePath, lwPathObs, client); + String validNodePath = validatePathObserveCancelAny(nodePath, lwPathObs, client); if (validNodePath != null) lwPaths.add(validNodePath); } }; @@ -273,13 +273,13 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im } } - private String validatePathCompositeCancel(LwM2mPath nodePath, LwM2mPath lwPathObs, LwM2mClient client) throws ThingsboardException { + private String validatePathObserveCancelAny(LwM2mPath nodePath, LwM2mPath lwPathObs, LwM2mClient client) throws ThingsboardException { if (nodePath.equals(lwPathObs) || lwPathObs.startWith(nodePath)) { // nodePath = "3", lwPathObs = "3/0/9": cancel for tne all lwPathObs - return nodePath.toString(); + return lwPathObs.toString(); } else if (!nodePath.equals(lwPathObs) && nodePath.startWith(lwPathObs)) { String errorMsg = String.format( - "Unexpected error: There is registration with Endpoint %s for observation path %s, that includes this observation path %s", - client.getRegistration().getEndpoint(), nodePath, lwPathObs); + "Unexpected error: There is registration with Endpoint %s for observation path [%s], that includes this observation path [%s]", + client.getRegistration().getEndpoint(), lwPathObs, nodePath); throw new ThingsboardException(errorMsg, ThingsboardErrorCode.BAD_REQUEST_PARAMS); } return null; @@ -335,9 +335,24 @@ public class DefaultLwM2mDownlinkMsgHandler extends LwM2MExecutorAwareService im @Override public void sendCancelObserveRequest(LwM2mClient client, TbLwM2MCancelObserveRequest request, DownlinkRequestCallback callback) { - validateVersionedId(client, request); - int observeCancelCnt = context.getServer().getObservationService().cancelObservations(client.getRegistration(), request.getObjectId()); - callback.onSuccess(request, observeCancelCnt); + try{ + validateVersionedId(client, request); + Set observations = context.getServer().getObservationService().getObservations(client.getRegistration()); + int observeCancelCnt = 0; + Set lwPaths = new HashSet<>(); + for (Observation obs : observations) { + LwM2mPath lwPathObs = ((SingleObservation) obs).getPath(); + LwM2mPath nodePath = new LwM2mPath(request.getObjectId()); + String validNodePath = validatePathObserveCancelAny(nodePath, lwPathObs, client); + if (validNodePath != null) lwPaths.add(validNodePath); + }; + for (String nodePath : lwPaths) { + observeCancelCnt += context.getServer().getObservationService().cancelObservations(client.getRegistration(), nodePath); + } + callback.onSuccess(request, observeCancelCnt); + } catch (ThingsboardException e){ + callback.onValidationError(request.toString(), e.getMessage()); + } } @Override From c2268595eb3e55fb42ee7af4e6ae93670f513a87 Mon Sep 17 00:00:00 2001 From: nick Date: Mon, 12 Feb 2024 13:31:38 +0200 Subject: [PATCH 202/397] lwm2m_coap: DTLS Cid Length --- .../src/main/resources/thingsboard.yml | 20 +++ .../lwm2m/AbstractLwM2MIntegrationTest.java | 7 +- .../transport/lwm2m/Lwm2mTestHelper.java | 6 +- .../lwm2m/client/DtlsSessionLogger.java | 81 +++++++++++ .../lwm2m/client/LwM2MTestClient.java | 38 +++-- .../ota/sql/OtaLwM2MIntegrationTest.java | 6 +- .../rpc/AbstractRpcLwM2MIntegrationTest.java | 2 +- .../AbstractSecurityLwM2MIntegrationTest.java | 4 +- ...ityLwM2MIntegrationDtlsCidLength0Test.java | 38 +++++ ...ityLwM2MIntegrationDtlsCidLength3Test.java | 37 +++++ ...LwM2MIntegrationDtlsCidLengthNullTest.java | 38 +++++ ...rityLwM2MIntegrationDtlsCidLengthTest.java | 133 ++++++++++++++++++ ...oSecLwM2MIntegrationDtlsCidLengthTest.java | 48 +++++++ .../PskLwm2mIntegrationDtlsCidLengthTest.java | 46 ++++++ ...oSecLwM2MIntegrationDtlsCidLengthTest.java | 48 +++++++ .../PskLwm2mIntegrationDtlsCidLengthTest.java | 47 +++++++ ...oSecLwM2MIntegrationDtlsCidLengthTest.java | 48 +++++++ .../PskLwm2mIntegrationDtlsCidLengthTest.java | 47 +++++++ .../server/coapserver/TbCoapDtlsSettings.java | 13 ++ .../LwM2MTransportBootstrapService.java | 7 +- .../config/LwM2MTransportServerConfig.java | 4 + .../server/DefaultLwM2mTransportService.java | 18 +-- .../lwm2m/utils/LwM2MTransportUtil.java | 14 ++ 23 files changed, 707 insertions(+), 43 deletions(-) create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/client/DtlsSessionLogger.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength0Test.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength3Test.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 0ddc86c5b7..0d401c5974 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1019,6 +1019,16 @@ transport: # CoAP DTLS bind port bind_port: "${COAP_DTLS_BIND_PORT:5684}" # Server DTLS credentials + # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # - A value that are > 4: MultiNodeConnectionIdGenerator is used + connection_id_length: "${COAP_DTLS_CONNECTION_ID_LENGTH:}" credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) type: "${COAP_DTLS_CREDENTIALS_TYPE:PEM}" @@ -1056,6 +1066,16 @@ transport: dtls: # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}" + # CoAP DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # - A value that are > 4: MultiNodeConnectionIdGenerator is used + connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:}" server: # LwM2M Server ID id: "${LWM2M_SERVER_ID:123}" diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 78f999080d..3d21a191a9 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -236,7 +236,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte getWsClient().waitForReply(); getWsClient().registerWaitForUpdate(); - createNewClient(security, null, coapConfig, false, endpoint); + createNewClient(security, null, coapConfig, false, endpoint, null); deviceId = device.getId().getId().toString(); awaitObserveReadAll(0, deviceId); String msg = getWsClient().waitForUpdate(); @@ -304,14 +304,15 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte this.resources = resources; } - public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, String endpoint) throws Exception { + public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, + String endpoint, Integer clientDtlsCidLength) throws Exception { this.clientDestroy(); lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); try (ServerSocket socket = new ServerSocket(0)) { int clientPort = socket.getLocalPort(); lwM2MTestClient.init(security, securityBs, coapConfig, clientPort, isRpc, - this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, isWriteAttribute); + this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, isWriteAttribute, clientDtlsCidLength); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java index 32e1444de6..b2ed3cc297 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/Lwm2mTestHelper.java @@ -53,7 +53,7 @@ public class Lwm2mTestHelper { public enum LwM2MClientState { - ON_INIT(1, "onInit"), + ON_INIT(0, "onInit"), ON_BOOTSTRAP_STARTED(1, "onBootstrapStarted"), ON_BOOTSTRAP_SUCCESS(2, "onBootstrapSuccess"), ON_BOOTSTRAP_FAILURE(3, "onBootstrapFailure"), @@ -70,7 +70,9 @@ public class Lwm2mTestHelper { ON_DEREGISTRATION_SUCCESS(13, "onDeregistrationSuccess"), ON_DEREGISTRATION_FAILURE(14, "onDeregistrationFailure"), ON_DEREGISTRATION_TIMEOUT(15, "onDeregistrationTimeout"), - ON_EXPECTED_ERROR(16, "onUnexpectedError"); + ON_EXPECTED_ERROR(16, "onUnexpectedError"), + ON_READ_CONNECTION_ID (17, "onReadConnection"), + ON_WRITE_CONNECTION_ID (18, "onWriteConnection"); public int code; public String type; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/DtlsSessionLogger.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/DtlsSessionLogger.java new file mode 100644 index 0000000000..d798dbc0d4 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/DtlsSessionLogger.java @@ -0,0 +1,81 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.client; + +import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.scandium.dtls.ClientHandshaker; +import org.eclipse.californium.scandium.dtls.DTLSContext; +import org.eclipse.californium.scandium.dtls.HandshakeException; +import org.eclipse.californium.scandium.dtls.Handshaker; +import org.eclipse.californium.scandium.dtls.SessionAdapter; +import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState; + +import java.util.Map; +import java.util.Set; + +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_READ_CONNECTION_ID; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_WRITE_CONNECTION_ID; + +@Slf4j +public class DtlsSessionLogger extends SessionAdapter { + + private final Set clientStates; + private final Map clientDtlsCid; + + public DtlsSessionLogger(Set clientStates, Map clientDtlsCid) { + this.clientStates = clientStates; + this.clientDtlsCid = clientDtlsCid; + } + + @Override + public void handshakeStarted(Handshaker handshaker) throws HandshakeException { + if (handshaker instanceof ClientHandshaker) { + log.info("DTLS Full Handshake initiated by client : STARTED ..."); + } + } + + @Override + public void contextEstablished(Handshaker handshaker, DTLSContext establishedContext) throws HandshakeException { + if (handshaker instanceof ClientHandshaker) { + log.warn("DTLS initiated by client: SUCCEED, WriteConnectionId: [{}], ReadConnectionId: [{}]", establishedContext.getWriteConnectionId(), establishedContext.getReadConnectionId()); + clientStates.add(ON_WRITE_CONNECTION_ID); + clientStates.add(ON_READ_CONNECTION_ID); + Integer lenWrite = establishedContext.getWriteConnectionId() == null ? null : establishedContext.getWriteConnectionId().getBytes().length; + Integer lenRead = establishedContext.getReadConnectionId() == null ? null : establishedContext.getReadConnectionId().getBytes().length; + clientDtlsCid.put(ON_WRITE_CONNECTION_ID, lenWrite); + clientDtlsCid.put(ON_READ_CONNECTION_ID, lenRead); + } + } + + @Override + public void handshakeFailed(Handshaker handshaker, Throwable error) { + // get cause + String cause; + if (error != null) { + if (error.getMessage() != null) { + cause = error.getMessage(); + } else { + cause = error.getClass().getName(); + } + } else { + cause = "unknown cause"; + } + + if (handshaker instanceof ClientHandshaker) { + log.info("DTLS Full Handshake initiated by client : FAILED ({})", cause); + } + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index 339c28067f..c3c1f5ff33 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -18,7 +18,6 @@ package org.thingsboard.server.transport.lwm2m.client; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.elements.config.Configuration; -import org.eclipse.californium.scandium.config.DtlsConfig; import org.eclipse.californium.scandium.config.DtlsConnectorConfig; import org.eclipse.leshan.client.LeshanClient; import org.eclipse.leshan.client.LeshanClientBuilder; @@ -62,11 +61,15 @@ import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; import java.io.IOException; import java.net.InetSocketAddress; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.ScheduledExecutorService; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY; import static org.eclipse.leshan.core.LwM2mId.ACCESS_CONTROL; import static org.eclipse.leshan.core.LwM2mId.DEVICE; import static org.eclipse.leshan.core.LwM2mId.FIRMWARE; @@ -103,6 +106,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INST import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.OBJECT_INSTANCE_ID_12; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.TEMPERATURE_SENSOR; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.resources; +import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.setDtlsConnectorConfigCidLength; @Slf4j @@ -119,12 +123,13 @@ public class LwM2MTestClient { private LwM2MLocationParams locationParams; private LwM2mTemperatureSensor lwM2MTemperatureSensor; private Set clientStates; + private Map clientDtlsCid; private LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; private LwM2mClientContext clientContext; public void init(Security security, Security securityBs,Configuration coapConfig, int port, boolean isRpc, LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler, - LwM2mClientContext clientContext, boolean isWriteAttribute) throws InvalidDDFFileException, IOException { + LwM2mClientContext clientContext, boolean isWriteAttribute, Integer cIdLength) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", leshanClient); this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler; this.clientContext = clientContext; @@ -188,6 +193,10 @@ public class LwM2MTestClient { protected DtlsConnectorConfig.Builder createRootDtlsConnectorConfigBuilder( Configuration configuration) { DtlsConnectorConfig.Builder builder = super.createRootDtlsConnectorConfigBuilder(configuration); + + // Add DTLS Session lifecycle logger + builder.setSessionListener(new DtlsSessionLogger(clientStates, clientDtlsCid)); + return builder; }; }; @@ -213,20 +222,18 @@ public class LwM2MTestClient { // Set some DTLS stuff // These configuration values are always overwritten by CLI therefore set them to transient. - clientCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY); - clientCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH); + clientCoapConfig.setTransient(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY); + clientCoapConfig.setTransient(DTLS_CONNECTION_ID_LENGTH); boolean supportDeprecatedCiphers = false; - clientCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !supportDeprecatedCiphers); - /** - * "Control usage of DTLS connection ID.", // - * "- 'on' to activate Connection ID support (same as -cid 0)", // - * "- 'off' to deactivate it", // - * "- Positive value define the size in byte of CID generated.", // - * "- 0 value means we accept to use CID but will not generated one for foreign peer.", // - * "Default: off" - */ - Integer cid = null; - clientCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, cid); + clientCoapConfig.set(DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, !supportDeprecatedCiphers); + + if (cIdLength!= null) { + setDtlsConnectorConfigCidLength(clientCoapConfig, cIdLength); + } + + if (cIdLength!= null) { + setDtlsConnectorConfigCidLength(clientCoapConfig, cIdLength); + } // Set Californium Configuration endpointsBuilder.setConfiguration(clientCoapConfig); @@ -279,6 +286,7 @@ public class LwM2MTestClient { builder.setSharedExecutor(executor); clientStates = new HashSet<>(); + clientDtlsCid = new HashMap<>(); clientStates.add(ON_INIT); leshanClient = builder.build(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index 7e812f9846..17518e2ba3 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -59,7 +59,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, null); awaitObserveReadAll(0, device.getId().getId().toString()); device.setFirmwareId(createFirmware().getId()); @@ -84,7 +84,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5, null); awaitObserveReadAll(9, device.getId().getId().toString()); device.setFirmwareId(createFirmware().getId()); @@ -114,7 +114,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA9); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9, null); awaitObserveReadAll(9, device.getId().getId().toString()); device.setSoftwareId(createSoftware().getId()); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index 1c83bed8eb..3c5d536dcd 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -91,7 +91,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg private void initRpc () throws Exception { String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet(); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, true, endpoint); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, true, endpoint, null); expectedObjects = ConcurrentHashMap.newKeySet(); expectedObjectIdVers = ConcurrentHashMap.newKeySet(); expectedInstances = ConcurrentHashMap.newKeySet(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index f164cb7fe7..b360918a9f 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -196,7 +196,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M boolean isStartLw) throws Exception { createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); - createNewClient(security, securityBs, coapConfig, true, endpoint); + createNewClient(security, securityBs, coapConfig, true, endpoint, null); lwM2MTestClient.start(isStartLw); if (isAwaitObserveReadAll) { awaitObserveReadAll(0, device.getId().getId().toString()); @@ -244,7 +244,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); String deviceIdStr = device.getId().getId().toString(); - createNewClient(security, securityBs, coapConfig, true, endpoint); + createNewClient(security, securityBs, coapConfig, true, endpoint, null); lwM2MTestClient.start(true); awaitObserveReadAll(0, deviceIdStr); await(awaitAlias) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength0Test.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength0Test.java new file mode 100644 index 0000000000..126dc39197 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength0Test.java @@ -0,0 +1,38 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; + + +@TestPropertySource(properties = { + "transport.lwm2m.dtls.connection_id_length=0" +}) + +@DaoSqlTest +@Slf4j +public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLength0Test extends AbstractSecurityLwM2MIntegrationDtlsCidLengthTest { + + + protected void testNoSecDtlsCidLength(Integer dtlsCidLength) throws Exception { + testNoSecDtlsCidLength(dtlsCidLength, 0); + } + protected void testPskDtlsCidLength(Integer dtlsCidLength) throws Exception { + testPskDtlsCidLength(dtlsCidLength, 0); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength3Test.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength3Test.java new file mode 100644 index 0000000000..d3f6605e11 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLength3Test.java @@ -0,0 +1,37 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; + + +@TestPropertySource(properties = { + "transport.lwm2m.dtls.connection_id_length=3" +}) + +@DaoSqlTest +@Slf4j +public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLength3Test extends AbstractSecurityLwM2MIntegrationDtlsCidLengthTest { + + protected void testNoSecDtlsCidLength(Integer dtlsCidLength) throws Exception { + testNoSecDtlsCidLength(dtlsCidLength, 3); + } + protected void testPskDtlsCidLength(Integer dtlsCidLength) throws Exception { + testPskDtlsCidLength(dtlsCidLength, 3); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest.java new file mode 100644 index 0000000000..1a63159352 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest.java @@ -0,0 +1,38 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.test.context.TestPropertySource; +import org.thingsboard.server.dao.service.DaoSqlTest; + + +@TestPropertySource(properties = { + "transport.lwm2m.dtls.connection_id_length=" +}) + +@DaoSqlTest +@Slf4j +public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest extends AbstractSecurityLwM2MIntegrationDtlsCidLengthTest { + + + protected void testNoSecDtlsCidLength(Integer dtlsCidLength) throws Exception { + testNoSecDtlsCidLength(dtlsCidLength, null); + } + protected void testPskDtlsCidLength(Integer dtlsCidLength) throws Exception { + testPskDtlsCidLength(dtlsCidLength, null); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..c743308fcd --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java @@ -0,0 +1,133 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.lwm2m.security.cid; + +import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.elements.config.Configuration; +import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpoint; +import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpointsProvider; +import org.eclipse.leshan.client.object.Security; +import org.eclipse.leshan.core.util.Hex; +import org.junit.Assert; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.device.credentials.lwm2m.AbstractLwM2MClientSecurityCredential; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; +import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; +import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; +import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState; +import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; +import static org.eclipse.leshan.client.object.Security.psk; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_INIT; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_READ_CONNECTION_ID; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_WRITE_CONNECTION_ID; + +@DaoSqlTest +@Slf4j +public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationTest { + + protected AbstractLwM2MClientSecurityCredential clientCredentials; + protected Security security; + protected Lwm2mDeviceProfileTransportConfiguration transportConfiguration; + protected LwM2MDeviceCredentials deviceCredentials; + protected String clientEndpoint; + protected LwM2MSecurityMode lwM2MSecurityMode; + protected String awaitAlias; + protected final Random randomSuffix = new Random(); + + protected final Set expectedStatusesRegistrationLwm2mDtlsCidSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS, ON_READ_CONNECTION_ID, ON_WRITE_CONNECTION_ID)); + + + protected void testNoSecDtlsCidLength(Integer dtlsCidLength, Integer serverDtlsCidLength) throws Exception { + initDeviceCredentialsNoSek(); + basicTestConnectionDtlsCidLength(dtlsCidLength, serverDtlsCidLength); + } + protected void testPskDtlsCidLength(Integer dtlsCidLength, Integer serverDtlsCidLength) throws Exception { + initDeviceCredentialsPsk(); + basicTestConnectionDtlsCidLength(dtlsCidLength, serverDtlsCidLength); + } + + protected void initDeviceCredentialsNoSek() { + clientEndpoint = CLIENT_ENDPOINT_NO_SEC + "_" + randomSuffix.nextInt(100); + deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + } + + protected void initDeviceCredentialsPsk() { + int suf = randomSuffix.nextInt(10); + clientEndpoint = CLIENT_ENDPOINT_PSK + "_" + suf; + String identity = CLIENT_PSK_IDENTITY + "_" + suf; + clientCredentials = new PSKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + ((PSKClientCredential)clientCredentials).setIdentity(identity); + clientCredentials.setKey(CLIENT_PSK_KEY); + security = psk(SECURE_URI, + shortServerId, + identity.getBytes(StandardCharsets.UTF_8), + Hex.decodeHex(CLIENT_PSK_KEY.toCharArray())); + deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); + } + + protected void basicTestConnectionDtlsCidLength(Integer clientDtlsCidLength, + Integer serverDtlsCidLength) throws Exception { + createDeviceProfile(transportConfiguration); + final Device device = createDevice(deviceCredentials, clientEndpoint); + device.getId().getId().toString(); + createNewClient(security, null, COAP_CONFIG, true, clientEndpoint, clientDtlsCidLength); + lwM2MTestClient.start(true); + await(awaitAlias) + .atMost(40, TimeUnit.SECONDS) + .until(() -> lwM2MTestClient.getClientStates().contains(ON_UPDATE_SUCCESS)); + Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatusesRegistrationLwm2mSuccess)); + + Configuration clientCoapConfig = ((CaliforniumClientEndpoint)((CaliforniumClientEndpointsProvider)lwM2MTestClient + .getLeshanClient().getEndpointsProvider().toArray()[0]).getEndpoints().toArray()[0]).getCoapEndpoint().getConfig(); + Assert.assertEquals(clientDtlsCidLength, clientCoapConfig.get(DTLS_CONNECTION_ID_LENGTH)); + + if (security.equals(SECURITY_NO_SEC)) { + Assert.assertTrue(lwM2MTestClient.getClientDtlsCid().isEmpty()); + } else { + Assert.assertEquals(2L, lwM2MTestClient.getClientDtlsCid().size()); + Assert.assertTrue(lwM2MTestClient.getClientDtlsCid().keySet().contains(ON_READ_CONNECTION_ID)); + Assert.assertTrue(lwM2MTestClient.getClientDtlsCid().keySet().contains(ON_WRITE_CONNECTION_ID)); + if (serverDtlsCidLength == null) { + Assert.assertNull(lwM2MTestClient.getClientDtlsCid().get(ON_WRITE_CONNECTION_ID)); + Assert.assertNull(lwM2MTestClient.getClientDtlsCid().get(ON_READ_CONNECTION_ID)); + } else { + Assert.assertEquals(clientDtlsCidLength, lwM2MTestClient.getClientDtlsCid().get(ON_READ_CONNECTION_ID)); + if (clientDtlsCidLength == null) { + Assert.assertNull(lwM2MTestClient.getClientDtlsCid().get(ON_READ_CONNECTION_ID)); + } else { + Assert.assertEquals(Integer.valueOf(serverDtlsCidLength), lwM2MTestClient.getClientDtlsCid().get(ON_WRITE_CONNECTION_ID)); + } + } + } + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..f43ae3af0c --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_0; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength0Test; + +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class NoSecLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength0Test { + + @Before + public void setUpNoSecDtlsCidLength() { + security = SECURITY_NO_SEC; + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); + awaitAlias = "await on client state (NoSec_Lwm2m) DtlsCidLength = 0"; + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testNoSecDtlsCidLength(null); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testNoSecDtlsCidLength(0); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testNoSecDtlsCidLength(2); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..38010111fa --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_0; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength0Test; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class PskLwm2mIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength0Test { + + @Before + public void createProfileRpc() { + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(lwM2MSecurityMode, NONE)); + awaitAlias = "await on client state (Psk_Lwm2m) DtlsCidLength = 0"; + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testPskDtlsCidLength(null); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testPskDtlsCidLength(0); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testPskDtlsCidLength(2); + } +} + diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..377ccf420a --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_3; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength3Test; + +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class NoSecLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength3Test { + + @Before + public void setUpNoSecDtlsCidLength() { + security = SECURITY_NO_SEC; + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); + awaitAlias = "await on client state (NoSec_Lwm2m) DtlsCidLength = 3"; + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testNoSecDtlsCidLength(null); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testNoSecDtlsCidLength(0); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testNoSecDtlsCidLength(2); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..afe436cdbc --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_3; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength3Test; + +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class PskLwm2mIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength3Test { + + @Before + public void createProfileRpc() { + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(lwM2MSecurityMode, NONE)); + awaitAlias = "await on client state (Psk_Lwm2m) DtlsCidLength = 3"; + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testPskDtlsCidLength(null); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testPskDtlsCidLength(0); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testPskDtlsCidLength(2); + } +} + diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..d5531f6354 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_null; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest; + +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class NoSecLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest { + + @Before + public void setUpNoSecDtlsCidLength() { + security = SECURITY_NO_SEC; + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); + awaitAlias = "await on client state (NoSec_Lwm2m) DtlsCidLength = Null"; + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testNoSecDtlsCidLength(null); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testNoSecDtlsCidLength(0); + } + + @Test + public void testWithNoSecConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testNoSecDtlsCidLength(2); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java new file mode 100644 index 0000000000..5c712f78d6 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_null; + +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest; + +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class PskLwm2mIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest { + + @Before + public void createProfileRpc() { + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(lwM2MSecurityMode, NONE)); + awaitAlias = "await on client state (Psk_Lwm2m) DtlsCidLength = Null"; + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_Null() throws Exception { + testPskDtlsCidLength(null); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_0() throws Exception { + testPskDtlsCidLength(0); + } + + @Test + public void testWithPskConnectLwm2mSuccessClientDtlsCidLength_2() throws Exception { + testPskDtlsCidLength(2); + } +} + diff --git a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java index e9296f70c5..f27131b7ab 100644 --- a/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java +++ b/common/coap-server/src/main/java/org/thingsboard/server/coapserver/TbCoapDtlsSettings.java @@ -41,6 +41,8 @@ import java.util.Collections; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.eclipse.californium.elements.config.CertificateAuthenticationMode.WANTED; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CLIENT_AUTHENTICATION_MODE; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_NODE_ID; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMISSION_TIMEOUT; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_ROLE; import static org.eclipse.californium.scandium.config.DtlsConfig.DtlsRole.SERVER_ONLY; @@ -59,6 +61,9 @@ public class TbCoapDtlsSettings { @Value("${transport.coap.dtls.retransmission_timeout:9000}") private int dtlsRetransmissionTimeout; + @Value("${transport.coap.dtls.connection_id_length}") + private Integer cIdLength; + @Bean @ConfigurationProperties(prefix = "transport.coap.dtls.credentials") public SslCredentialsConfig coapDtlsCredentials() { @@ -93,6 +98,14 @@ public class TbCoapDtlsSettings { configBuilder.set(DTLS_CLIENT_AUTHENTICATION_MODE, WANTED); configBuilder.set(DTLS_RETRANSMISSION_TIMEOUT, dtlsRetransmissionTimeout, MILLISECONDS); configBuilder.set(DTLS_ROLE, SERVER_ONLY); + configBuilder.set(DTLS_CONNECTION_ID_LENGTH, cIdLength); + if (cIdLength != null) { + if (cIdLength > 4) { + configBuilder.set(DTLS_CONNECTION_ID_NODE_ID, 0); + } else { + configBuilder.set(DTLS_CONNECTION_ID_NODE_ID, null); + } + } configBuilder.setAdvancedCertificateVerifier( new TbCoapDtlsCertificateVerifier( transportService, diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java index d6839ae394..c8e8baa30a 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/LwM2MTransportBootstrapService.java @@ -49,6 +49,7 @@ import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_RETRANSMIS import static org.thingsboard.server.transport.lwm2m.server.DefaultLwM2mTransportService.PSK_CIPHER_SUITES; import static org.thingsboard.server.transport.lwm2m.server.DefaultLwM2mTransportService.RPK_OR_X509_CIPHER_SUITES; import static org.thingsboard.server.transport.lwm2m.server.LwM2MNetworkConfig.getCoapConfig; +import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.setDtlsConnectorConfigCidLength; @Slf4j @Component @@ -113,15 +114,15 @@ public class LwM2MTransportBootstrapService { serverCoapConfig.setTransient(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY); serverCoapConfig.set(DtlsConfig.DTLS_RECOMMENDED_CIPHER_SUITES_ONLY, serverConfig.isRecommendedCiphers()); serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH); - serverCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, 6); serverCoapConfig.set(DTLS_RECOMMENDED_CURVES_ONLY, serverConfig.isRecommendedSupportedGroups()); serverCoapConfig.setTransient(DTLS_RETRANSMISSION_TIMEOUT); serverCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, serverConfig.getDtlsRetransmissionTimeout(), MILLISECONDS); - + if (serverConfig.getDtlsCidLength() != null) { + setDtlsConnectorConfigCidLength( serverCoapConfig, serverConfig.getDtlsCidLength()); + } /* Create DTLS Config */ - this.setServerWithCredentials(builder); // Set Californium Configuration diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java index 4b9ea2e4ac..03c4730313 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/config/LwM2MTransportServerConfig.java @@ -42,6 +42,10 @@ public class LwM2MTransportServerConfig implements LwM2MSecureServerConfig { @Value("${transport.lwm2m.dtls.retransmission_timeout:9000}") private int dtlsRetransmissionTimeout; + @Getter + @Value("${transport.lwm2m.dtls.connection_id_length:}") + private Integer dtlsCidLength; + @Getter @Value("${transport.lwm2m.timeout:}") private Long timeout; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java index 27bf6251a9..4bf9859b16 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/DefaultLwM2mTransportService.java @@ -58,6 +58,7 @@ import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_W import static org.eclipse.californium.scandium.dtls.cipher.CipherSuite.TLS_PSK_WITH_AES_128_CCM_8; import static org.thingsboard.server.transport.lwm2m.server.LwM2MNetworkConfig.getCoapConfig; import static org.thingsboard.server.transport.lwm2m.server.ota.DefaultLwM2MOtaUpdateService.FIRMWARE_UPDATE_COAP_RESOURCE; +import static org.thingsboard.server.transport.lwm2m.utils.LwM2MTransportUtil.setDtlsConnectorConfigCidLength; @Slf4j @Component @@ -165,21 +166,10 @@ public class DefaultLwM2mTransportService implements LwM2MTransportService { serverCoapConfig.set(DTLS_RETRANSMISSION_TIMEOUT, config.getDtlsRetransmissionTimeout(), MILLISECONDS); serverCoapConfig.set(DTLS_ROLE, SERVER_ONLY); serverCoapConfig.setTransient(DtlsConfig.DTLS_CONNECTION_ID_LENGTH); - /** - * "Control usage of DTLS connection ID.", - * If DTLS_CONNECTION_ID_LENGTH enables the use of a connection id, this node id could be used - * to configure the generation of connection ids specific for node in a multi-node deployment (cluster). - * The value is used as first byte in generated connection ids. - * DTLS connection ID length. disabled, - * 0 enables support without active use of CID.", defaultValue == null, minimumValue == 0); - * "- 'on' to activate Connection ID support ", - * " (same as -cid 6)", - * "- 'off' to deactivate it", - * "- Positive value define the size in byte of CID generated.", - * "- 0 value means we accept to use CID but will not generated one for foreign peer.", - */ - serverCoapConfig.set(DtlsConfig.DTLS_CONNECTION_ID_LENGTH, 6); + if (config.getDtlsCidLength() != null) { + setDtlsConnectorConfigCidLength( serverCoapConfig, config.getDtlsCidLength()); + } /* Create DTLS Config */ this.setServerWithCredentials(builder); diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java index b74a668b6a..db8398cd57 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2MTransportUtil.java @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.utils; import com.google.gson.JsonElement; import lombok.extern.slf4j.Slf4j; +import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.core.model.LwM2mModel; import org.eclipse.leshan.core.model.ObjectLoader; import org.eclipse.leshan.core.model.ObjectModel; @@ -55,6 +56,8 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; +import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_NODE_ID; import static org.eclipse.leshan.core.model.ResourceModel.Type.BOOLEAN; import static org.eclipse.leshan.core.model.ResourceModel.Type.FLOAT; import static org.eclipse.leshan.core.model.ResourceModel.Type.INTEGER; @@ -425,4 +428,15 @@ public class LwM2MTransportUtil { } return newValueStr.equals(oldValueStr); } + + public static void setDtlsConnectorConfigCidLength(Configuration serverCoapConfig, Integer cIdLength) { + serverCoapConfig.setTransient(DTLS_CONNECTION_ID_LENGTH); + serverCoapConfig.setTransient(DTLS_CONNECTION_ID_NODE_ID); + serverCoapConfig.set(DTLS_CONNECTION_ID_LENGTH, cIdLength); + if ( cIdLength > 4) { + serverCoapConfig.set(DTLS_CONNECTION_ID_NODE_ID, 0); + } else { + serverCoapConfig.set(DTLS_CONNECTION_ID_NODE_ID, null); + } + } } From a71f723e5e99e882a775984dfee6b35359804366 Mon Sep 17 00:00:00 2001 From: nick Date: Mon, 12 Feb 2024 15:49:59 +0200 Subject: [PATCH 203/397] lwm2m_coap: DTLS Cid Length - thongsboard3 --- application/src/main/resources/thingsboard.yml | 2 +- .../coap/src/main/resources/tb-coap-transport.yml | 11 +++++++++++ .../lwm2m/src/main/resources/tb-lwm2m-transport.yml | 10 ++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 0dc52a58f9..64af95857a 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1018,7 +1018,7 @@ transport: bind_address: "${COAP_DTLS_BIND_ADDRESS:0.0.0.0}" # CoAP DTLS bind port bind_port: "${COAP_DTLS_BIND_PORT:5684}" - # Server DTLS credentials + # Server DTLS credentials # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 # Default: off # Control usage of DTLS connection ID length (CID). diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index 7a3bd01fef..08ff4111c7 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -155,6 +155,17 @@ transport: # CoAP DTLS bind port bind_port: "${COAP_DTLS_BIND_PORT:5684}" # Server DTLS credentials + # Server DTLS credentials + # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # - A value that are > 4: MultiNodeConnectionIdGenerator is used + connection_id_length: "${COAP_DTLS_CONNECTION_ID_LENGTH:}" credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) type: "${COAP_DTLS_CREDENTIALS_TYPE:PEM}" diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index 4f0d4fce4c..01008d8d13 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -166,6 +166,16 @@ transport: dtls: # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}" + # CoAP DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # - A value that are > 4: MultiNodeConnectionIdGenerator is used + connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:}" server: # LwM2M Server ID id: "${LWM2M_SERVER_ID:123}" From 4b42139ae845a343c7aaddeccffa235801fca367 Mon Sep 17 00:00:00 2001 From: nick Date: Mon, 12 Feb 2024 16:13:40 +0200 Subject: [PATCH 204/397] lwm2m_coap: DTLS Cid Length - yml format --- .../src/main/resources/thingsboard.yml | 38 +++++++++---------- .../src/main/resources/tb-coap-transport.yml | 18 ++++----- .../src/main/resources/tb-lwm2m-transport.yml | 18 ++++----- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 64af95857a..a066cd7109 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1018,16 +1018,16 @@ transport: bind_address: "${COAP_DTLS_BIND_ADDRESS:0.0.0.0}" # CoAP DTLS bind port bind_port: "${COAP_DTLS_BIND_PORT:5684}" - # Server DTLS credentials - # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 - # Default: off - # Control usage of DTLS connection ID length (CID). - # - 'off' to deactivate it. - # - 'on' to activate Connection ID support (same as CID 0 or more 0). - # - A positive value defines generated CID size in bytes. - # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). - # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used - # - A value that are > 4: MultiNodeConnectionIdGenerator is used + # Server DTLS credentials + # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # - A value that are > 4: MultiNodeConnectionIdGenerator is used connection_id_length: "${COAP_DTLS_CONNECTION_ID_LENGTH:}" credentials: # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) @@ -1066,15 +1066,15 @@ transport: dtls: # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}" - # CoAP DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 - # Default: off - # Control usage of DTLS connection ID length (CID). - # - 'off' to deactivate it. - # - 'on' to activate Connection ID support (same as CID 0 or more 0). - # - A positive value defines generated CID size in bytes. - # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). - # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used - # - A value that are > 4: MultiNodeConnectionIdGenerator is used + # CoAP DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # - A value that are > 4: MultiNodeConnectionIdGenerator is used connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:}" server: # LwM2M Server ID diff --git a/transport/coap/src/main/resources/tb-coap-transport.yml b/transport/coap/src/main/resources/tb-coap-transport.yml index 08ff4111c7..86ed3a269b 100644 --- a/transport/coap/src/main/resources/tb-coap-transport.yml +++ b/transport/coap/src/main/resources/tb-coap-transport.yml @@ -155,15 +155,15 @@ transport: # CoAP DTLS bind port bind_port: "${COAP_DTLS_BIND_PORT:5684}" # Server DTLS credentials - # Server DTLS credentials - # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 - # Default: off - # Control usage of DTLS connection ID length (CID). - # - 'off' to deactivate it. - # - 'on' to activate Connection ID support (same as CID 0 or more 0). - # - A positive value defines generated CID size in bytes. - # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). - # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # Server DTLS credentials + # CoAP DTLS connection ID length. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used # - A value that are > 4: MultiNodeConnectionIdGenerator is used connection_id_length: "${COAP_DTLS_CONNECTION_ID_LENGTH:}" credentials: diff --git a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml index 01008d8d13..1070f17746 100644 --- a/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml +++ b/transport/lwm2m/src/main/resources/tb-lwm2m-transport.yml @@ -166,15 +166,15 @@ transport: dtls: # RFC7925_RETRANSMISSION_TIMEOUT_IN_MILLISECONDS = 9000 retransmission_timeout: "${LWM2M_DTLS_RETRANSMISSION_TIMEOUT_MS:9000}" - # CoAP DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 - # Default: off - # Control usage of DTLS connection ID length (CID). - # - 'off' to deactivate it. - # - 'on' to activate Connection ID support (same as CID 0 or more 0). - # - A positive value defines generated CID size in bytes. - # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). - # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used - # - A value that are > 4: MultiNodeConnectionIdGenerator is used + # CoAP DTLS connection ID length for LWM2M. RFC 9146, Connection Identifier for DTLS 1.2 + # Default: off + # Control usage of DTLS connection ID length (CID). + # - 'off' to deactivate it. + # - 'on' to activate Connection ID support (same as CID 0 or more 0). + # - A positive value defines generated CID size in bytes. + # - A value of 0 means we accept using CID but will not generate one for foreign peer (enables support but not for incoming traffic). + # - A value between 0 and <= 4: SingleNodeConnectionIdGenerator is used + # - A value that are > 4: MultiNodeConnectionIdGenerator is used connection_id_length: "${LWM2M_DTLS_CONNECTION_ID_LENGTH:}" server: # LwM2M Server ID From 492dc5916e8a273ff56f4505210cd80071076a2b Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 13 Feb 2024 11:07:34 +0200 Subject: [PATCH 205/397] Improvements for tenant actors init with dedicated rule engines --- .../server/actors/app/AppActor.java | 3 +- .../RuleChainActorMessageProcessor.java | 1 + .../ruleChain/RuleChainManagerActor.java | 4 ++ .../RuleNodeActorMessageProcessor.java | 9 +++- .../server/actors/tenant/TenantActor.java | 46 ++++++++++++------ .../DefaultTbRuleEngineConsumerService.java | 37 ++++++++------- .../discovery/HashPartitionServiceTest.java | 6 +-- .../DefaultTbServiceInfoProvider.java | 2 +- .../queue/discovery/HashPartitionService.java | 47 ++++++++++++------- .../queue/discovery/TenantRoutingInfo.java | 2 +- 10 files changed, 101 insertions(+), 56 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/app/AppActor.java b/application/src/main/java/org/thingsboard/server/actors/app/AppActor.java index 563f381380..4ab54c0ad8 100644 --- a/application/src/main/java/org/thingsboard/server/actors/app/AppActor.java +++ b/application/src/main/java/org/thingsboard/server/actors/app/AppActor.java @@ -202,8 +202,7 @@ public class AppActor extends ContextAwareActor { return Optional.ofNullable(ctx.getOrCreateChildActor(new TbEntityActorId(tenantId), () -> DefaultActorService.TENANT_DISPATCHER_NAME, () -> new TenantActor.ActorCreator(systemContext, tenantId), - () -> systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE) || - systemContext.getPartitionService().isManagedByCurrentService(tenantId))); + () -> true)); } private void onToEdgeSessionMsg(EdgeSessionMsg msg) { diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java index e14ed8203b..4021bdf8ea 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainActorMessageProcessor.java @@ -161,6 +161,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor actorRef.tellWithHighPriority(msg)); } diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainManagerActor.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainManagerActor.java index 468da57e96..6f920bc9ab 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainManagerActor.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleChainManagerActor.java @@ -50,6 +50,8 @@ public abstract class RuleChainManagerActor extends ContextAwareActor { @Getter protected TbActorRef rootChainActor; + protected boolean ruleChainsInitialized; + public RuleChainManagerActor(ActorSystemContext systemContext, TenantId tenantId) { super(systemContext); this.tenantId = tenantId; @@ -57,6 +59,7 @@ public abstract class RuleChainManagerActor extends ContextAwareActor { } protected void initRuleChains() { + ruleChainsInitialized = true; for (RuleChain ruleChain : new PageDataIterable<>(link -> ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, link), ContextAwareActor.ENTITY_PACK_LIMIT)) { RuleChainId ruleChainId = ruleChain.getId(); log.debug("[{}|{}] Creating rule chain actor", ruleChainId.getEntityType(), ruleChain.getId()); @@ -70,6 +73,7 @@ public abstract class RuleChainManagerActor extends ContextAwareActor { for (RuleChain ruleChain : new PageDataIterable<>(link -> ruleChainService.findTenantRuleChainsByType(tenantId, RuleChainType.CORE, link), ContextAwareActor.ENTITY_PACK_LIMIT)) { ctx.stop(new TbEntityActorId(ruleChain.getId())); } + ruleChainsInitialized = false; } protected void visit(RuleChain entity, TbActorRef actorRef) { diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java index 47de6bcdf1..df08c5a5c7 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.actors.ruleChain; +import lombok.extern.slf4j.Slf4j; import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.server.actors.ActorSystemContext; @@ -39,6 +40,7 @@ import org.thingsboard.server.gen.transport.TransportProtos; /** * @author Andrew Shvayka */ +@Slf4j public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor { private final String ruleChainName; @@ -61,6 +63,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor deviceActorIds = ctx.filterChildren(new TbEntityTypeActorIdPredicate(EntityType.DEVICE) { - @Override - protected boolean testEntityId(EntityId entityId) { - return super.testEntityId(entityId) && !isMyPartition(entityId); - } - }); - deviceActorIds.forEach(id -> ctx.stop(id)); - } + onPartitionChangeMsg((PartitionChangeMsg) msg); break; case COMPONENT_LIFE_CYCLE_MSG: onComponentLifecycleMsg((ComponentLifecycleMsg) msg); @@ -239,6 +228,35 @@ public class TenantActor extends RuleChainManagerActor { } } + private void onPartitionChangeMsg(PartitionChangeMsg msg) { + ServiceType serviceType = msg.getServiceType(); + if (ServiceType.TB_RULE_ENGINE.equals(serviceType)) { + if (systemContext.getPartitionService().isManagedByCurrentService(tenantId)) { + if (!ruleChainsInitialized) { + log.info("Tenant {} is already managed by this service, initializing rule chains", tenantId); + initRuleChains(); + } + } else { + if (ruleChainsInitialized) { + log.info("Tenant {} is no longer managed by this service, stopping rule chains", tenantId); + destroyRuleChains(); + } + return; + } + + //To Rule Chain Actors + broadcast(msg); + } else if (ServiceType.TB_CORE.equals(serviceType)) { + List deviceActorIds = ctx.filterChildren(new TbEntityTypeActorIdPredicate(EntityType.DEVICE) { + @Override + protected boolean testEntityId(EntityId entityId) { + return super.testEntityId(entityId) && !isMyPartition(entityId); + } + }); + deviceActorIds.forEach(id -> ctx.stop(id)); + } + } + private void onComponentLifecycleMsg(ComponentLifecycleMsg msg) { if (msg.getEntityId().getEntityType().equals(EntityType.API_USAGE_STATE)) { ApiUsageState old = getApiUsageState(); diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java index ce989c711d..3bc0af787d 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java @@ -99,25 +99,28 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< List queues = queueService.findAllQueues(); for (Queue configuration : queues) { if (partitionService.isManagedByCurrentService(configuration.getTenantId())) { - initConsumer(configuration); + QueueKey queueKey = new QueueKey(ServiceType.TB_RULE_ENGINE, configuration); + getOrCreateConsumer(queueKey).init(configuration); } } } - private void initConsumer(Queue configuration) { - getOrCreateConsumer(new QueueKey(ServiceType.TB_RULE_ENGINE, configuration)).init(configuration); - } - @Override protected void onTbApplicationEvent(PartitionChangeEvent event) { event.getPartitionsMap().forEach((queueKey, partitions) -> { - var consumer = consumers.get(queueKey); - if (consumer != null) { - consumer.update(partitions); - } else { - log.warn("Received invalid partition change event for {} that is not managed by this service", queueKey); + if (partitionService.isManagedByCurrentService(queueKey.getTenantId())) { + getOrCreateConsumer(queueKey).update(partitions); } }); + consumers.keySet().stream() + .collect(Collectors.groupingBy(QueueKey::getTenantId)) + .forEach((tenantId, queueKeys) -> { + if (!partitionService.isManagedByCurrentService(tenantId)) { + queueKeys.forEach(queueKey -> { + removeConsumer(queueKey).ifPresent(TbRuleEngineQueueConsumerManager::stop); + }); + } + }); } @AfterStartUp(order = AfterStartUp.REGULAR_SERVICE) @@ -211,10 +214,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< log.info("Received queue delete msg: [{}]", queueDeleteMsg); TenantId tenantId = new TenantId(new UUID(queueDeleteMsg.getTenantIdMSB(), queueDeleteMsg.getTenantIdLSB())); QueueKey queueKey = new QueueKey(ServiceType.TB_RULE_ENGINE, queueDeleteMsg.getQueueName(), tenantId); - var consumerManager = consumers.remove(queueKey); - if (consumerManager != null) { - consumerManager.delete(true); - } + removeConsumer(queueKey).ifPresent(consumer -> consumer.delete(true)); } partitionService.removeQueues(queueDeleteMsgs); @@ -229,10 +229,7 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< .filter(queueKey -> queueKey.getTenantId().equals(event.getTenantId())) .collect(Collectors.toList()); toRemove.forEach(queueKey -> { - var consumerManager = consumers.remove(queueKey); - if (consumerManager != null) { - consumerManager.delete(false); - } + removeConsumer(queueKey).ifPresent(consumer -> consumer.delete(false)); }); } } @@ -242,6 +239,10 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< return consumers.computeIfAbsent(queueKey, key -> new TbRuleEngineQueueConsumerManager(ctx, key)); } + private Optional removeConsumer(QueueKey queueKey) { + return Optional.ofNullable(consumers.remove(queueKey)); + } + @Scheduled(fixedDelayString = "${queue.rule-engine.stats.print-interval-ms}") public void printStats() { if (ctx.isStatsEnabled()) { diff --git a/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java b/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java index 7f8515f50b..e67bbb9506 100644 --- a/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java @@ -156,7 +156,7 @@ public class HashPartitionServiceTest { for (int queueIndex = 0; queueIndex < queueCount; queueIndex++) { QueueKey queueKey = new QueueKey(ServiceType.TB_RULE_ENGINE, "queue" + queueIndex, tenantId); for (int partition = 0; partition < partitionCount; partition++) { - ServiceInfo serviceInfo = clusterRoutingService.resolveByPartitionIdx(services, queueKey, partition); + ServiceInfo serviceInfo = clusterRoutingService.resolveByPartitionIdx(services, queueKey, partition, Collections.emptyMap()); String serviceId = serviceInfo.getServiceId(); map.put(serviceId, map.get(serviceId) + 1); } @@ -389,9 +389,9 @@ public class HashPartitionServiceTest { .limit(100).collect(Collectors.toList()); for (int partition = 0; partition < 10; partition++) { - ServiceInfo expectedAssignedRuleEngine = clusterRoutingService.resolveByPartitionIdx(ruleEngines, new QueueKey(ServiceType.TB_RULE_ENGINE, tenantId), partition); + ServiceInfo expectedAssignedRuleEngine = clusterRoutingService.resolveByPartitionIdx(ruleEngines, new QueueKey(ServiceType.TB_RULE_ENGINE, tenantId), partition, Collections.emptyMap()); for (QueueKey queueKey : queues) { - ServiceInfo assignedRuleEngine = clusterRoutingService.resolveByPartitionIdx(ruleEngines, queueKey, partition); + ServiceInfo assignedRuleEngine = clusterRoutingService.resolveByPartitionIdx(ruleEngines, queueKey, partition, Collections.emptyMap()); assertThat(assignedRuleEngine).as(queueKey + "[" + partition + "] should be assigned to " + expectedAssignedRuleEngine.getServiceId()) .isEqualTo(expectedAssignedRuleEngine); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java index e60b5f7cc5..2dce7517bb 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/DefaultTbServiceInfoProvider.java @@ -81,7 +81,7 @@ public class DefaultTbServiceInfoProvider implements TbServiceInfoProvider { } log.info("Current Service ID: {}", serviceId); if (serviceType.equalsIgnoreCase("monolith")) { - serviceTypes = Collections.unmodifiableList(Arrays.asList(ServiceType.values())); + serviceTypes = List.of(ServiceType.values()); } else { serviceTypes = Collections.singletonList(ServiceType.of(serviceType)); } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java index 4630dc4bf8..72f7826c27 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java @@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.exception.TenantNotFoundException; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; +import org.thingsboard.server.common.data.util.CollectionsUtil; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.gen.transport.TransportProtos; @@ -81,7 +82,7 @@ public class HashPartitionService implements PartitionService { private List currentOtherServices; private final Map> tbTransportServicesByType = new HashMap<>(); - private final Map> responsibleServices = new HashMap<>(); + private volatile Map> responsibleServices = Collections.emptyMap(); private HashFunction hashFunction; @@ -218,16 +219,26 @@ public class HashPartitionService implements PartitionService { @Override public boolean isManagedByCurrentService(TenantId tenantId) { - Set assignedTenantProfiles = serviceInfoProvider.getAssignedTenantProfiles(); - if (assignedTenantProfiles.isEmpty()) { - // TODO: refactor this for common servers + if (serviceInfoProvider.isService(ServiceType.TB_CORE) || !serviceInfoProvider.isService(ServiceType.TB_RULE_ENGINE)) { return true; + } + + Set assignedTenantProfiles = serviceInfoProvider.getAssignedTenantProfiles(); + if (assignedTenantProfiles.isEmpty()) { // if this is regular rule engine + if (tenantId.isSysTenantId()) { + return true; + } + TenantRoutingInfo routingInfo = getRoutingInfo(tenantId); + if (routingInfo.isIsolated()) { + return CollectionsUtil.isEmpty(responsibleServices.get(routingInfo.getProfileId())); + } else { + return true; + } } else { if (tenantId.isSysTenantId()) { return false; } - TenantProfileId profileId = tenantRoutingInfoService.getRoutingInfo(tenantId).getProfileId(); - return assignedTenantProfiles.contains(profileId.getId()); + return assignedTenantProfiles.contains(getRoutingInfo(tenantId).getProfileId().getId()); } } @@ -283,14 +294,14 @@ public class HashPartitionService implements PartitionService { public synchronized void recalculatePartitions(ServiceInfo currentService, List otherServices) { log.info("Recalculating partitions"); tbTransportServicesByType.clear(); - responsibleServices.clear(); logServiceInfo(currentService); otherServices.forEach(this::logServiceInfo); Map> queueServicesMap = new HashMap<>(); - addNode(queueServicesMap, currentService); + Map> responsibleServices = new HashMap<>(); + addNode(currentService, queueServicesMap, responsibleServices); for (ServiceInfo other : otherServices) { - addNode(queueServicesMap, other); + addNode(other, queueServicesMap, responsibleServices); } queueServicesMap.values().forEach(list -> list.sort(Comparator.comparing(ServiceInfo::getServiceId))); responsibleServices.values().forEach(list -> list.sort(Comparator.comparing(ServiceInfo::getServiceId))); @@ -299,7 +310,7 @@ public class HashPartitionService implements PartitionService { partitionSizesMap.forEach((queueKey, size) -> { for (int i = 0; i < size; i++) { try { - ServiceInfo serviceInfo = resolveByPartitionIdx(queueServicesMap.get(queueKey), queueKey, i); + ServiceInfo serviceInfo = resolveByPartitionIdx(queueServicesMap.get(queueKey), queueKey, i, responsibleServices); log.trace("Server responsible for {}[{}] - {}", queueKey, i, serviceInfo != null ? serviceInfo.getServiceId() : "none"); if (currentService.equals(serviceInfo)) { newPartitions.computeIfAbsent(queueKey, key -> new ArrayList<>()).add(i); @@ -309,6 +320,7 @@ public class HashPartitionService implements PartitionService { } } }); + this.responsibleServices = responsibleServices; final ConcurrentMap> oldPartitions = myPartitions; myPartitions = newPartitions; @@ -474,20 +486,22 @@ public class HashPartitionService implements PartitionService { if (TenantId.SYS_TENANT_ID.equals(tenantId)) { return false; } - TenantRoutingInfo routingInfo = tenantRoutingInfoMap.computeIfAbsent(tenantId, k -> { - return tenantRoutingInfoService.getRoutingInfo(tenantId); - }); + TenantRoutingInfo routingInfo = getRoutingInfo(tenantId); if (routingInfo == null) { throw new TenantNotFoundException(tenantId); } switch (serviceType) { case TB_RULE_ENGINE: - return routingInfo.isIsolatedTbRuleEngine(); + return routingInfo.isIsolated(); default: return false; } } + private TenantRoutingInfo getRoutingInfo(TenantId tenantId) { + return tenantRoutingInfoMap.computeIfAbsent(tenantId, tenantRoutingInfoService::getRoutingInfo); + } + private TenantId getIsolatedOrSystemTenantId(ServiceType serviceType, TenantId tenantId) { return isIsolated(serviceType, tenantId) ? tenantId : TenantId.SYS_TENANT_ID; } @@ -496,7 +510,7 @@ public class HashPartitionService implements PartitionService { log.info("[{}] Found common server: {}", server.getServiceId(), server.getServiceTypesList()); } - private void addNode(Map> queueServiceList, ServiceInfo instance) { + private void addNode(ServiceInfo instance, Map> queueServiceList, Map> responsibleServices) { for (String serviceTypeStr : instance.getServiceTypesList()) { ServiceType serviceType = ServiceType.of(serviceTypeStr); if (ServiceType.TB_RULE_ENGINE.equals(serviceType)) { @@ -528,7 +542,8 @@ public class HashPartitionService implements PartitionService { } } - protected ServiceInfo resolveByPartitionIdx(List servers, QueueKey queueKey, int partition) { + protected ServiceInfo resolveByPartitionIdx(List servers, QueueKey queueKey, int partition, + Map> responsibleServices) { if (servers == null || servers.isEmpty()) { return null; } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TenantRoutingInfo.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TenantRoutingInfo.java index c221572bfe..caf4e823fd 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TenantRoutingInfo.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/TenantRoutingInfo.java @@ -23,5 +23,5 @@ import org.thingsboard.server.common.data.id.TenantProfileId; public class TenantRoutingInfo { private final TenantId tenantId; private final TenantProfileId profileId; - private final boolean isolatedTbRuleEngine; + private final boolean isolated; } From e806c1c86e82a1ff3bae7625ba7c0fae4f87d438 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 13 Feb 2024 13:49:14 +0200 Subject: [PATCH 206/397] Fix Rule Engine consumers init when tenant becomes managed --- .../RuleNodeActorMessageProcessor.java | 4 ++- .../server/actors/tenant/TenantActor.java | 6 ++--- .../DefaultTbRuleEngineConsumerService.java | 25 +++++++++++++------ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java index df08c5a5c7..e7b0113dbe 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java @@ -193,7 +193,9 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor { if (partitionService.isManagedByCurrentService(queueKey.getTenantId())) { - getOrCreateConsumer(queueKey).update(partitions); + var consumer = getConsumer(queueKey).orElseGet(() -> { + Queue config = queueService.findQueueByTenantIdAndName(queueKey.getTenantId(), queueKey.getQueueName()); + return createConsumer(queueKey, config); + }); + consumer.update(partitions); } }); consumers.keySet().stream() @@ -190,9 +194,9 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< QueueKey queueKey = new QueueKey(ServiceType.TB_RULE_ENGINE, queueName, tenantId); Queue queue = queueService.findQueueById(tenantId, queueId); - TbRuleEngineQueueConsumerManager consumerManager = getOrCreateConsumer(queueKey); - Queue oldQueue = consumerManager.getQueue(); - consumerManager.update(queue); + var consumer = getConsumer(queueKey).orElseGet(() -> createConsumer(queueKey, queue)); + Queue oldQueue = consumer.getQueue(); + consumer.update(queue); if (oldQueue == null || queue.getPartitions() != oldQueue.getPartitions()) { partitionsChanged = true; @@ -235,8 +239,15 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< } } - private TbRuleEngineQueueConsumerManager getOrCreateConsumer(QueueKey queueKey) { - return consumers.computeIfAbsent(queueKey, key -> new TbRuleEngineQueueConsumerManager(ctx, key)); + private Optional getConsumer(QueueKey queueKey) { + return Optional.ofNullable(consumers.get(queueKey)); + } + + private TbRuleEngineQueueConsumerManager createConsumer(QueueKey queueKey, Queue queue) { + var consumer = new TbRuleEngineQueueConsumerManager(ctx, queueKey); + consumers.put(queueKey, consumer); + consumer.init(queue); + return consumer; } private Optional removeConsumer(QueueKey queueKey) { From 91d6cf6dee22905b99e34cc505ab65aae14af22a Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 13 Feb 2024 13:50:41 +0200 Subject: [PATCH 207/397] Non-isolated tenant is not managed even if assignedTenantProfiles contains his profile --- .../queue/discovery/HashPartitionService.java | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java index 72f7826c27..e7034143fe 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java @@ -223,23 +223,33 @@ public class HashPartitionService implements PartitionService { return true; } + boolean isManaged; Set assignedTenantProfiles = serviceInfoProvider.getAssignedTenantProfiles(); if (assignedTenantProfiles.isEmpty()) { // if this is regular rule engine if (tenantId.isSysTenantId()) { - return true; - } - TenantRoutingInfo routingInfo = getRoutingInfo(tenantId); - if (routingInfo.isIsolated()) { - return CollectionsUtil.isEmpty(responsibleServices.get(routingInfo.getProfileId())); + isManaged = true; } else { - return true; + TenantRoutingInfo routingInfo = getRoutingInfo(tenantId); + if (routingInfo.isIsolated()) { + isManaged = CollectionsUtil.isEmpty(responsibleServices.get(routingInfo.getProfileId())); + } else { + isManaged = true; + } } } else { if (tenantId.isSysTenantId()) { - return false; + isManaged = false; + } else { + TenantRoutingInfo routingInfo = getRoutingInfo(tenantId); + if (routingInfo.isIsolated()) { + isManaged = assignedTenantProfiles.contains(routingInfo.getProfileId().getId()); + } else { + isManaged = false; + } } - return assignedTenantProfiles.contains(getRoutingInfo(tenantId).getProfileId().getId()); } + log.trace("[{}] Tenant {} managed by this service", tenantId, isManaged ? "is" : "is not"); + return isManaged; } @Override From 937124fa61a023f79763091c28115ec387d16cd5 Mon Sep 17 00:00:00 2001 From: Dmitriymush Date: Tue, 13 Feb 2024 14:09:38 +0200 Subject: [PATCH 208/397] UI: added workaround for matChipInputAddOnBlur selection bug in tb-entity-subtype-list input --- .../components/entity/entity-subtype-list.component.html | 3 ++- .../components/entity/entity-subtype-list.component.ts | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.html b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.html index 89c9b2ace8..26fb757c42 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.html +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.html @@ -31,9 +31,10 @@ style="max-width: 200px;" #entitySubtypeInput (focusin)="onFocus()" + (blur)="addOnBlur($event)" formControlName="entitySubtype" matAutocompleteOrigin - matChipInputAddOnBlur + matChipInputAddOnBlur="false" #origin="matAutocompleteOrigin" [matAutocompleteConnectedTo]="origin" [matAutocomplete]="entitySubtypeAutocomplete" diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts index 9b49241d50..bc3cde24f5 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts @@ -262,6 +262,15 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, this.clear(''); } } + + addOnBlur(event: FocusEvent) { + if (!event.relatedTarget) { + return; + } + const value = this.entitySubtypeInput.nativeElement.value; + this.chipAdd({value} as MatChipInputEvent); + } + remove(entitySubtype: string) { const index = this.entitySubtypeList.indexOf(entitySubtype); if (index >= 0) { From cb674048e7ddef34442513fadeab76f056a15281 Mon Sep 17 00:00:00 2001 From: nick Date: Tue, 13 Feb 2024 14:27:18 +0200 Subject: [PATCH 209/397] lwm2m: client queue Mode --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 18 +++++++++++++++--- .../lwm2m/client/LwM2MTestClient.java | 7 +++---- .../lwm2m/ota/sql/OtaLwM2MIntegrationTest.java | 6 +++--- .../rpc/AbstractRpcLwM2MIntegrationTest.java | 2 +- .../AbstractSecurityLwM2MIntegrationTest.java | 4 ++-- .../sql/NoSecLwM2MIntegrationTest.java | 8 +++++++- .../server/client/LwM2mClientContextImpl.java | 12 ++++++++---- 7 files changed, 39 insertions(+), 18 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 3d21a191a9..7b989a1997 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -219,7 +219,8 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte public void basicTestConnectionObserveTelemetry(Security security, LwM2MDeviceCredentials deviceCredentials, Configuration coapConfig, - String endpoint) throws Exception { + String endpoint, + boolean queueMode) throws Exception { Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS, getBootstrapServerCredentialsNoSec(NONE)); createDeviceProfile(transportConfiguration); Device device = createDevice(deviceCredentials, endpoint); @@ -236,7 +237,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte getWsClient().waitForReply(); getWsClient().registerWaitForUpdate(); - createNewClient(security, null, coapConfig, false, endpoint, null); + createNewClient(security, null, coapConfig, false, endpoint, null, queueMode); deviceId = device.getId().getId().toString(); awaitObserveReadAll(0, deviceId); String msg = getWsClient().waitForUpdate(); @@ -304,15 +305,26 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte this.resources = resources; } + public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, + String endpoint) throws Exception { + this.createNewClient(security, securityBs, coapConfig, isRpc, endpoint, null, false); + } + public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, String endpoint, Integer clientDtlsCidLength) throws Exception { + this.createNewClient(security, securityBs, coapConfig, isRpc, endpoint, clientDtlsCidLength, false); + } + + public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, + String endpoint, Integer clientDtlsCidLength, boolean queueMode) throws Exception { this.clientDestroy(); lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); try (ServerSocket socket = new ServerSocket(0)) { int clientPort = socket.getLocalPort(); lwM2MTestClient.init(security, securityBs, coapConfig, clientPort, isRpc, - this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, isWriteAttribute, clientDtlsCidLength); + this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, isWriteAttribute + , clientDtlsCidLength, queueMode); } } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index c3c1f5ff33..4363bca41c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -129,7 +129,7 @@ public class LwM2MTestClient { public void init(Security security, Security securityBs,Configuration coapConfig, int port, boolean isRpc, LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler, - LwM2mClientContext clientContext, boolean isWriteAttribute, Integer cIdLength) throws InvalidDDFFileException, IOException { + LwM2mClientContext clientContext, boolean isWriteAttribute, Integer cIdLength, boolean queueMode) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", leshanClient); this.defaultLwM2mUplinkMsgHandlerTest = defaultLwM2mUplinkMsgHandler; this.clientContext = clientContext; @@ -263,11 +263,10 @@ public class LwM2MTestClient { boolean reconnectOnUpdate = false; engineFactory.setReconnectOnUpdate(reconnectOnUpdate); engineFactory.setResumeOnConnect(true); - // new + /** - * Client use queue mode (not fully implemented). + * Client use queue mode. */ - boolean queueMode = false; engineFactory.setQueueMode(queueMode); // Create client diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index 17518e2ba3..7e812f9846 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -59,7 +59,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO, null); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); awaitObserveReadAll(0, device.getId().getId().toString()); device.setFirmwareId(createFirmware().getId()); @@ -84,7 +84,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5, null); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5); awaitObserveReadAll(9, device.getId().getId().toString()); device.setFirmwareId(createFirmware().getId()); @@ -114,7 +114,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA9); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9, null); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9); awaitObserveReadAll(9, device.getId().getId().toString()); device.setSoftwareId(createSoftware().getId()); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index 3c5d536dcd..1c83bed8eb 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -91,7 +91,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg private void initRpc () throws Exception { String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet(); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, true, endpoint, null); + createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, true, endpoint); expectedObjects = ConcurrentHashMap.newKeySet(); expectedObjectIdVers = ConcurrentHashMap.newKeySet(); expectedInstances = ConcurrentHashMap.newKeySet(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index b360918a9f..f164cb7fe7 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -196,7 +196,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M boolean isStartLw) throws Exception { createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); - createNewClient(security, securityBs, coapConfig, true, endpoint, null); + createNewClient(security, securityBs, coapConfig, true, endpoint); lwM2MTestClient.start(isStartLw); if (isAwaitObserveReadAll) { awaitObserveReadAll(0, device.getId().getId().toString()); @@ -244,7 +244,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); String deviceIdStr = device.getId().getId().toString(); - createNewClient(security, securityBs, coapConfig, true, endpoint, null); + createNewClient(security, securityBs, coapConfig, true, endpoint); lwM2MTestClient.start(true); awaitObserveReadAll(0, deviceIdStr); await(awaitAlias) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java index 7389f5db27..7a34ec4283 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java @@ -32,7 +32,13 @@ public class NoSecLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationT public void testWithNoSecConnectLwm2mSuccessAndObserveTelemetry() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC; LwM2MDeviceCredentials clientCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); - super.basicTestConnectionObserveTelemetry(SECURITY_NO_SEC, clientCredentials, COAP_CONFIG, clientEndpoint); + super.basicTestConnectionObserveTelemetry(SECURITY_NO_SEC, clientCredentials, COAP_CONFIG, clientEndpoint, false); + } + @Test + public void testWithNoSecQueueModeConnectLwm2mSuccessAndObserveTelemetry() throws Exception { + String clientEndpoint = CLIENT_ENDPOINT_NO_SEC + "_QueueMode"; + LwM2MDeviceCredentials clientCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + super.basicTestConnectionObserveTelemetry(SECURITY_NO_SEC, clientCredentials, COAP_CONFIG, clientEndpoint, true); } // Bootstrap + Lwm2m diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java index 03449aaaef..fa3063befb 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java @@ -461,11 +461,15 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { PowerMode powerMode = client.getPowerMode(); OtherConfiguration profileSettings = null; if (powerMode == null) { - var clientProfile = getProfile(client.getProfileId()); - profileSettings = clientProfile.getClientLwM2mSettings(); - powerMode = profileSettings.getPowerMode(); - if (powerMode == null) { + if (client.getProfileId() == null) { powerMode = PowerMode.DRX; + } else { + var clientProfile = getProfile(client.getProfileId()); + profileSettings = clientProfile.getClientLwM2mSettings(); + powerMode = profileSettings.getPowerMode(); + if (powerMode == null) { + powerMode = PowerMode.DRX; + } } } if (PowerMode.DRX.equals(powerMode)) { From 4319024eed5c47c08bad02a1d64e4212f08660ed Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 13 Feb 2024 14:28:19 +0200 Subject: [PATCH 210/397] Ignore ComponentLifecycleMsg for non-managed tenants --- .../java/org/thingsboard/server/actors/tenant/TenantActor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java b/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java index 4a283bfcfa..1565af1695 100644 --- a/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java +++ b/application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java @@ -284,7 +284,7 @@ public class TenantActor extends RuleChainManagerActor { onToDeviceActorMsg(new DeviceDeleteMsg(tenantId, deviceId), true); deletedDevices.add(deviceId); } - if (isRuleEngine) { + if (isRuleEngine && ruleChainsInitialized) { TbActorRef target = getEntityActorRef(msg.getEntityId()); if (target != null) { if (msg.getEntityId().getEntityType() == EntityType.RULE_CHAIN) { From 12af0cd757821915de4a2969698bd354976f40a5 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 13 Feb 2024 15:01:15 +0200 Subject: [PATCH 211/397] Always recalculate partitions after queue updates --- .../DefaultTbRuleEngineConsumerService.java | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java index b92ed34639..afdd150a59 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbRuleEngineConsumerService.java @@ -184,7 +184,6 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< } private void updateQueues(List queueUpdateMsgs) { - boolean partitionsChanged = false; for (QueueUpdateMsg queueUpdateMsg : queueUpdateMsgs) { log.info("Received queue update msg: [{}]", queueUpdateMsg); TenantId tenantId = new TenantId(new UUID(queueUpdateMsg.getTenantIdMSB(), queueUpdateMsg.getTenantIdLSB())); @@ -194,23 +193,14 @@ public class DefaultTbRuleEngineConsumerService extends AbstractConsumerService< QueueKey queueKey = new QueueKey(ServiceType.TB_RULE_ENGINE, queueName, tenantId); Queue queue = queueService.findQueueById(tenantId, queueId); - var consumer = getConsumer(queueKey).orElseGet(() -> createConsumer(queueKey, queue)); - Queue oldQueue = consumer.getQueue(); - consumer.update(queue); - - if (oldQueue == null || queue.getPartitions() != oldQueue.getPartitions()) { - partitionsChanged = true; - } - } else { - partitionsChanged = true; + getConsumer(queueKey).ifPresentOrElse(consumer -> consumer.update(queue), + () -> createConsumer(queueKey, queue)); } } - if (partitionsChanged) { - partitionService.updateQueues(queueUpdateMsgs); - partitionService.recalculatePartitions(ctx.getServiceInfoProvider().getServiceInfo(), - new ArrayList<>(partitionService.getOtherServices(ServiceType.TB_RULE_ENGINE))); - } + partitionService.updateQueues(queueUpdateMsgs); + partitionService.recalculatePartitions(ctx.getServiceInfoProvider().getServiceInfo(), + new ArrayList<>(partitionService.getOtherServices(ServiceType.TB_RULE_ENGINE))); } private void deleteQueues(List queueDeleteMsgs) { From 9cdcad8775562ada44d887ca9b3190bb33e9584d Mon Sep 17 00:00:00 2001 From: nick Date: Tue, 13 Feb 2024 15:13:26 +0200 Subject: [PATCH 212/397] lwm2m/coap: client queue Mode --- .../coap/client/DefaultCoapClientContext.java | 16 ++++++------- .../server/client/LwM2mClientContextImpl.java | 24 ++++++------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java index 7177542c3d..8dafc18a88 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java @@ -18,7 +18,6 @@ package org.thingsboard.server.transport.coap.client; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.coap.CoAP; -import org.eclipse.californium.core.coap.CoAP.ResponseCode; import org.eclipse.californium.core.coap.Response; import org.eclipse.californium.core.observe.ObserveRelation; import org.eclipse.californium.core.server.resources.CoapExchange; @@ -222,7 +221,7 @@ public class DefaultCoapClientContext implements CoapClientContext { private void onUplink(TbCoapClientState client, boolean notifyOtherServers, long uplinkTs) { PowerMode powerMode = client.getPowerMode(); PowerSavingConfiguration profileSettings = null; - if (powerMode == null) { + if (powerMode == null && client.getProfileId() != null) { var clientProfile = getProfile(client.getProfileId()); if (clientProfile.isPresent()) { profileSettings = clientProfile.get().getClientSettings(); @@ -736,7 +735,7 @@ public class DefaultCoapClientContext implements CoapClientContext { private boolean isDownlinkAllowed(TbCoapClientState client) { PowerMode powerMode = client.getPowerMode(); PowerSavingConfiguration profileSettings = null; - if (powerMode == null) { + if (powerMode == null && client.getProfileId() != null) { var clientProfile = getProfile(client.getProfileId()); if (clientProfile.isPresent()) { profileSettings = clientProfile.get().getClientSettings(); @@ -785,11 +784,12 @@ public class DefaultCoapClientContext implements CoapClientContext { private PowerMode getPowerMode(TbCoapClientState client) { PowerMode powerMode = client.getPowerMode(); if (powerMode == null) { - Optional deviceProfile = getProfile(client.getProfileId()); - if (deviceProfile.isPresent()) { - powerMode = deviceProfile.get().getClientSettings().getPowerMode(); - } else { - powerMode = PowerMode.PSM; + powerMode = PowerMode.PSM; + if (client.getProfileId() != null) { + Optional deviceProfile = getProfile(client.getProfileId()); + if (deviceProfile.isPresent()) { + powerMode = deviceProfile.get().getClientSettings().getPowerMode(); + } } } return powerMode; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java index fa3063befb..4f35489250 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java @@ -411,15 +411,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { public boolean isDownlinkAllowed(LwM2mClient client) { PowerMode powerMode = client.getPowerMode(); OtherConfiguration profileSettings = null; - if (powerMode == null) { + if (powerMode == null && client.getProfileId() != null) { var clientProfile = getProfile(client.getProfileId()); profileSettings = clientProfile.getClientLwM2mSettings(); powerMode = profileSettings.getPowerMode(); - if (powerMode == null) { - powerMode = PowerMode.DRX; - } } - if (PowerMode.DRX.equals(powerMode) || otaUpdateService.isOtaDownloading(client)) { + if (powerMode == null || PowerMode.DRX.equals(powerMode) || otaUpdateService.isOtaDownloading(client)) { return true; } client.lock(); @@ -460,19 +457,12 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { public void onUplink(LwM2mClient client) { PowerMode powerMode = client.getPowerMode(); OtherConfiguration profileSettings = null; - if (powerMode == null) { - if (client.getProfileId() == null) { - powerMode = PowerMode.DRX; - } else { - var clientProfile = getProfile(client.getProfileId()); - profileSettings = clientProfile.getClientLwM2mSettings(); - powerMode = profileSettings.getPowerMode(); - if (powerMode == null) { - powerMode = PowerMode.DRX; - } - } + if (powerMode == null && client.getProfileId() != null) { + var clientProfile = getProfile(client.getProfileId()); + profileSettings = clientProfile.getClientLwM2mSettings(); + powerMode = profileSettings.getPowerMode(); } - if (PowerMode.DRX.equals(powerMode)) { + if (powerMode == null || PowerMode.DRX.equals(powerMode)) { client.updateLastUplinkTime(); return; } From b6b67bb3d5752cdf05be980f6856c90c1c59d6e9 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 13 Feb 2024 16:26:30 +0200 Subject: [PATCH 213/397] added alarm state handling for IN, NOT_IN types of operation --- .../rule/engine/profile/AlarmRuleState.java | 5 + .../engine/profile/AlarmRuleStateTest.java | 98 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmRuleStateTest.java diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java index b3322c049c..da63c72750 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java @@ -46,6 +46,7 @@ import org.thingsboard.server.common.adaptor.JsonConverter; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -467,6 +468,10 @@ class AlarmRuleState { return !val.equals(predicateValue); case NOT_CONTAINS: return !val.contains(predicateValue); + case IN: + return predicateValue.contains(val); + case NOT_IN: + return !predicateValue.contains(val); default: throw new RuntimeException("Operation not supported: " + predicate.getOperation()); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmRuleStateTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmRuleStateTest.java new file mode 100644 index 0000000000..a46517b682 --- /dev/null +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmRuleStateTest.java @@ -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. + */ +package org.thingsboard.rule.engine.profile; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.thingsboard.rule.engine.math.TbRuleNodeMathFunctionType; +import org.thingsboard.server.common.data.device.profile.AlarmCondition; +import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter; +import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey; +import org.thingsboard.server.common.data.device.profile.AlarmConditionKeyType; +import org.thingsboard.server.common.data.device.profile.AlarmRule; +import org.thingsboard.server.common.data.device.profile.SimpleAlarmConditionSpec; +import org.thingsboard.server.common.data.query.EntityKeyValueType; +import org.thingsboard.server.common.data.query.FilterPredicateValue; +import org.thingsboard.server.common.data.query.StringFilterPredicate; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; + +public class AlarmRuleStateTest { + + private static Stream testEvalCondition() { + return Stream.of( + Arguments.of(StringFilterPredicate.StringOperation.IN, "test value", "test", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.IN, "test value", "teeeeest", AlarmEvalResult.FALSE), + Arguments.of(StringFilterPredicate.StringOperation.NOT_IN, "test value", "test", AlarmEvalResult.FALSE), + Arguments.of(StringFilterPredicate.StringOperation.NOT_IN, "test value", "teeeeest", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.CONTAINS, "test value", "test value", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.CONTAINS, "test value", "test", AlarmEvalResult.FALSE), + Arguments.of(StringFilterPredicate.StringOperation.NOT_CONTAINS, "test value", "test", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.NOT_CONTAINS, "test value", "test value", AlarmEvalResult.FALSE), + Arguments.of(StringFilterPredicate.StringOperation.EQUAL, "test value", "test value", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.EQUAL, "test value", "test", AlarmEvalResult.FALSE), + Arguments.of(StringFilterPredicate.StringOperation.NOT_EQUAL, "test value", "test", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.NOT_EQUAL, "test value", "test value", AlarmEvalResult.FALSE), + Arguments.of(StringFilterPredicate.StringOperation.ENDS_WITH, "test value", "some test value", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.ENDS_WITH, "test value", "some test value2", AlarmEvalResult.FALSE), + Arguments.of(StringFilterPredicate.StringOperation.STARTS_WITH, "test value", "test value attribute", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.STARTS_WITH, "test value", "test", AlarmEvalResult.FALSE) + ); + } + + @ParameterizedTest + @MethodSource + public void testEvalCondition(StringFilterPredicate.StringOperation operation, String predicateValue, String attributeValue, AlarmEvalResult evalResult) { + AlarmConditionFilterKey alarmConditionFilterKey = new AlarmConditionFilterKey(AlarmConditionKeyType.ATTRIBUTE, "stringKey"); + + StringFilterPredicate predicate = new StringFilterPredicate(); + predicate.setOperation(operation); + predicate.setValue(new FilterPredicateValue<>(predicateValue)); + + AlarmConditionFilter alarmConditionFilter = new AlarmConditionFilter(); + alarmConditionFilter.setKey(alarmConditionFilterKey); + alarmConditionFilter.setPredicate(predicate); + alarmConditionFilter.setValueType(EntityKeyValueType.STRING); + + List condition = new ArrayList<>(); + condition.add(alarmConditionFilter); + + AlarmCondition alarmCondition = new AlarmCondition(); + alarmCondition.setSpec(new SimpleAlarmConditionSpec()); + alarmCondition.setCondition(condition); + + AlarmRule alarmRule = new AlarmRule(); + alarmRule.setCondition(alarmCondition); + + AlarmRuleState alarmRuleState = new AlarmRuleState(null, alarmRule, null, null, null); + + Set entityKeys = new HashSet<>(List.of(alarmConditionFilterKey)); + DataSnapshot result = new DataSnapshot(entityKeys); + result.putValue(alarmConditionFilterKey, System.currentTimeMillis(), EntityKeyValue.fromString(attributeValue)); + Assertions.assertEquals(evalResult, alarmRuleState.eval(result)); + } +} From 1749a35f048dfefe6b17e4160927faf24feff599 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Tue, 13 Feb 2024 17:14:36 +0200 Subject: [PATCH 214/397] handling predicate value as coma separated string --- .../server/common/data/StringUtils.java | 25 +++++++++++++++++ .../dao/sql/query/EntityKeyMapping.java | 27 +++---------------- .../dao/sql/query/EntityKeyMappingTest.java | 26 +++++++++--------- .../rule/engine/profile/AlarmRuleState.java | 8 +++--- .../engine/profile/AlarmRuleStateTest.java | 14 +++------- 5 files changed, 51 insertions(+), 49 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java index 3bd8cbcd20..5e7566ea5f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java @@ -19,7 +19,9 @@ import com.google.common.base.Splitter; import org.apache.commons.lang3.RandomStringUtils; import java.security.SecureRandom; +import java.util.ArrayList; import java.util.Base64; +import java.util.List; import java.util.function.Function; import static org.apache.commons.lang3.StringUtils.repeat; @@ -245,4 +247,27 @@ public class StringUtils { return string.substring(0, maxLength) + truncationMarkerFunc.apply(truncatedSymbols); } + public static List getListValuesWithoutQuote(String value) { + List splitValues = List.of(value.trim().split("\\s*,\\s*")); + List result = new ArrayList<>(); + char lastWayInputValue = '#'; + for (String str : splitValues) { + char startWith = str.charAt(0); + char endWith = str.charAt(str.length() - 1); + + // if first value is not quote, so we return values after split + if (startWith != '\'' && startWith != '"') return splitValues; + + // if value is not in quote, so we return values after split + if (startWith != endWith) return splitValues; + + // if different way values, so don't replace quote and return values after split + if (lastWayInputValue != '#' && startWith != lastWayInputValue) return splitValues; + + result.add(str.substring(1, str.length() - 1)); + lastWayInputValue = startWith; + } + return result; + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index f5874cbd08..595f8ae3e8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -47,6 +47,8 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.thingsboard.server.common.data.StringUtils.getListValuesWithoutQuote; + @Data public class EntityKeyMapping { @@ -582,30 +584,7 @@ public class EntityKeyMapping { return String.format("((%s is not null and %s)", field, stringOperationQuery); } - protected List getListValuesWithoutQuote(String value) { - List splitValues = List.of(value.trim().split("\\s*,\\s*")); - List result = new ArrayList<>(); - char lastWayInputValue = '#'; - for (String str : splitValues) { - char startWith = str.charAt(0); - char endWith = str.charAt(str.length() - 1); - - // if first value is not quote, so we return values after split - if (startWith != '\'' && startWith != '"') return splitValues; - - // if value is not in quote, so we return values after split - if (startWith != endWith) return splitValues; - - // if different way values, so don't replace quote and return values after split - if (lastWayInputValue != '#' && startWith != lastWayInputValue) return splitValues; - - result.add(str.substring(1, str.length() - 1)); - lastWayInputValue = startWith; - } - return result; - } - - private String buildNumericPredicateQuery(QueryContext ctx, String field, NumericFilterPredicate numericFilterPredicate) { + private String buildNumericPredicateQuery(QueryContext ctx, String field, NumericFilterPredicate numericFilterPredicate) { String paramName = getNextParameterName(field); ctx.addDoubleParameter(paramName, numericFilterPredicate.getValue().getValue()); String numericOperationQuery = ""; diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityKeyMappingTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityKeyMappingTest.java index b9baffef1c..7d6d23f248 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityKeyMappingTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityKeyMappingTest.java @@ -24,6 +24,8 @@ import org.springframework.test.context.junit4.SpringRunner; import java.util.List; +import static org.thingsboard.server.common.data.StringUtils.getListValuesWithoutQuote; + @RunWith(SpringRunner.class ) @SpringBootTest(classes = EntityKeyMapping.class) public class EntityKeyMappingTest { @@ -36,39 +38,39 @@ public class EntityKeyMappingTest { @Test public void testSplitToList() { String value = "device1, device2, device3"; - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); } @Test public void testReplaceSingleQuote() { String value = "'device1', 'device2', 'device3'"; - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); } @Test public void testReplaceDoubleQuote() { String value = "\"device1\", \"device2\", \"device3\""; - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); } @Test public void testSplitWithoutSpace() { String value = "\"device1\" , \"device2\" , \"device3\""; - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); } @Test public void testSaveSpacesBetweenString() { String value = "device 1 , device 2 , device 3"; List result = List.of("device 1", "device 2", "device 3"); - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); } @Test public void testSaveQuoteInString() { String value = "device ''1 , device \"\"2 , device \"'3"; List result = List.of("device ''1", "device \"\"2", "device \"'3"); - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); } @Test @@ -76,28 +78,28 @@ public class EntityKeyMappingTest { String value = "\"device1\", 'device2', \"device3\""; List result = List.of("\"device1\"", "'device2'", "\"device3\""); - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); value = "'device1', \"device2\", \"device3\""; result = List.of("'device1'", "\"device2\"", "\"device3\""); - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); value = "device1, 'device2', \"device3\""; result = List.of("device1", "'device2'", "\"device3\""); - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); value = "'device1', device2, \"device3\""; result = List.of("'device1'", "device2", "\"device3\""); - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); value = "device1, \"device2\", \"device3\""; result = List.of("device1", "\"device2\"", "\"device3\""); - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); value = "\"device1\", device2, \"device3\""; result = List.of("\"device1\"", "device2", "\"device3\""); - Assert.assertEquals(entityKeyMapping.getListValuesWithoutQuote(value), result); + Assert.assertEquals(getListValuesWithoutQuote(value), result); } } \ No newline at end of file diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java index da63c72750..028afa25ce 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java @@ -46,11 +46,13 @@ import org.thingsboard.server.common.adaptor.JsonConverter; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; -import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import static org.thingsboard.server.common.data.StringUtils.equalsAny; +import static org.thingsboard.server.common.data.StringUtils.getListValuesWithoutQuote; + @Data @Slf4j class AlarmRuleState { @@ -469,9 +471,9 @@ class AlarmRuleState { case NOT_CONTAINS: return !val.contains(predicateValue); case IN: - return predicateValue.contains(val); + return equalsAny(val, getListValuesWithoutQuote(predicateValue).toArray(new String[0])); case NOT_IN: - return !predicateValue.contains(val); + return !equalsAny(val, getListValuesWithoutQuote(predicateValue).toArray(new String[0])); default: throw new RuntimeException("Operation not supported: " + predicate.getOperation()); } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmRuleStateTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmRuleStateTest.java index a46517b682..e4b2856dc3 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmRuleStateTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/AlarmRuleStateTest.java @@ -15,14 +15,10 @@ */ package org.thingsboard.rule.engine.profile; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.thingsboard.rule.engine.math.TbRuleNodeMathFunctionType; import org.thingsboard.server.common.data.device.profile.AlarmCondition; import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter; import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey; @@ -39,16 +35,14 @@ import java.util.List; import java.util.Set; import java.util.stream.Stream; -import static org.junit.Assert.assertEquals; - public class AlarmRuleStateTest { private static Stream testEvalCondition() { return Stream.of( - Arguments.of(StringFilterPredicate.StringOperation.IN, "test value", "test", AlarmEvalResult.TRUE), - Arguments.of(StringFilterPredicate.StringOperation.IN, "test value", "teeeeest", AlarmEvalResult.FALSE), - Arguments.of(StringFilterPredicate.StringOperation.NOT_IN, "test value", "test", AlarmEvalResult.FALSE), - Arguments.of(StringFilterPredicate.StringOperation.NOT_IN, "test value", "teeeeest", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.IN, "test,value", "test", AlarmEvalResult.TRUE), + Arguments.of(StringFilterPredicate.StringOperation.IN, "test,value", "teeeeest", AlarmEvalResult.FALSE), + Arguments.of(StringFilterPredicate.StringOperation.NOT_IN, "test,value", "test", AlarmEvalResult.FALSE), + Arguments.of(StringFilterPredicate.StringOperation.NOT_IN, "test,value", "teeeeest", AlarmEvalResult.TRUE), Arguments.of(StringFilterPredicate.StringOperation.CONTAINS, "test value", "test value", AlarmEvalResult.TRUE), Arguments.of(StringFilterPredicate.StringOperation.CONTAINS, "test value", "test", AlarmEvalResult.FALSE), Arguments.of(StringFilterPredicate.StringOperation.NOT_CONTAINS, "test value", "test", AlarmEvalResult.TRUE), From 7a747f101efd6b7846a677d0bf6dcdfe3d14a186 Mon Sep 17 00:00:00 2001 From: rusikv Date: Tue, 13 Feb 2024 18:16:27 +0200 Subject: [PATCH 215/397] UI: added 'Default coma separetad values' hint to alarm rule condition string filter predicate value input in case of 'in' and 'not in' operations --- .../filter/filter-predicate-value.component.html | 2 +- .../filter/filter-predicate-value.component.ts | 14 +++++++++++++- .../filter/string-filter-predicate.component.html | 1 + .../src/assets/locale/locale.constant-en_US.json | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html index 4e7a499895..c6ae39f295 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html @@ -41,7 +41,7 @@
    -
    filter.default-value
    +
    {{ hintText | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts index 30260b26ea..473e01801f 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts @@ -32,7 +32,8 @@ import { EntityKeyValueType, FilterPredicateValue, getDynamicSourcesForAllowUser, - inheritModeForDynamicValueSourceType + inheritModeForDynamicValueSourceType, + StringOperation } from '@shared/models/query/query.models'; @Component({ @@ -81,6 +82,15 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, Vali return this.onlyUserDynamicSourceValue; } + @Input() + set operation(operation: StringOperation) { + if (operation && (operation === StringOperation.IN || operation === StringOperation.NOT_IN)) { + this.hintText = 'filter.default-coma-separated-values'; + } else { + this.hintText = 'filter.default-value'; + } + } + @Input() valueType: EntityKeyValueType; @@ -98,6 +108,8 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, Vali inheritMode = false; + hintText = 'filter.default-value'; + private propagateChange = null; private propagateChangePending = false; diff --git a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html index 2ce80373e8..c2888fa06f 100644 --- a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html @@ -31,6 +31,7 @@ [onlyUserDynamicSource]="onlyUserDynamicSource" fxFlex="70" [valueType]="valueTypeEnum.STRING" + [operation]="stringFilterPredicateFormGroup.get('operation').value" formControlName="value">
    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 19981797f8..cb77262623 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -2667,6 +2667,7 @@ "current-user": "Current user", "current-device": "Current device", "default-value": "Default value", + "default-coma-separated-values": "Default coma separated values", "dynamic-source-type": "Dynamic source type", "dynamic-value": "Dynamic value", "no-dynamic-value": "No dynamic value", From eae3d9cdb94b42b3814b2055330f50a36e0e5c4b Mon Sep 17 00:00:00 2001 From: Dmitriymush Date: Tue, 13 Feb 2024 21:12:14 +0200 Subject: [PATCH 216/397] UI: fixed onDashboardStateInputFocus --- .../lib/settings/common/action/widget-action.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts index 6c2cd3fb8f..3fa353623f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts @@ -186,7 +186,7 @@ export class WidgetActionComponent implements ControlValueAccessor, OnInit, Vali } onDashboardStateInputFocus(): void { - this.actionTypeFormGroup.get('targetDashboardStateId').updateValueAndValidity({onlySelf: true, emitEvent: true}); + this.actionTypeFormGroup.get('targetDashboardId').updateValueAndValidity({onlySelf: true, emitEvent: true}); } stateDisplayTypeName(displayType: stateDisplayType): string { From 48875174196f04bf02f5cbab5e46db5e841811b1 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Wed, 14 Feb 2024 11:33:13 +0200 Subject: [PATCH 217/397] refactoring: renamed StringUtils method --- .../server/common/data/StringUtils.java | 7 ++++- .../dao/sql/query/EntityKeyMapping.java | 4 +-- .../dao/sql/query/EntityKeyMappingTest.java | 26 +++++++++---------- .../rule/engine/profile/AlarmRuleState.java | 6 ++--- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java index 5e7566ea5f..232473348e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java @@ -20,6 +20,7 @@ import org.apache.commons.lang3.RandomStringUtils; import java.security.SecureRandom; import java.util.ArrayList; +import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.function.Function; @@ -158,6 +159,10 @@ public class StringUtils { } public static boolean equalsAny(String string, String... otherStrings) { + return equalsAny(string, Arrays.asList(otherStrings)); + } + + public static boolean equalsAny(String string, List otherStrings) { for (String otherString : otherStrings) { if (equals(string, otherString)) { return true; @@ -247,7 +252,7 @@ public class StringUtils { return string.substring(0, maxLength) + truncationMarkerFunc.apply(truncatedSymbols); } - public static List getListValuesWithoutQuote(String value) { + public static List splitByCommaWithoutQuotes(String value) { List splitValues = List.of(value.trim().split("\\s*,\\s*")); List result = new ArrayList<>(); char lastWayInputValue = '#'; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index 595f8ae3e8..b928e8790e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -47,7 +47,7 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.thingsboard.server.common.data.StringUtils.getListValuesWithoutQuote; +import static org.thingsboard.server.common.data.StringUtils.splitByCommaWithoutQuotes; @Data public class EntityKeyMapping { @@ -576,7 +576,7 @@ public class EntityKeyMapping { switch (stringFilterPredicate.getOperation()) { case IN: case NOT_IN: - ctx.addStringListParameter(paramName, getListValuesWithoutQuote(value)); + ctx.addStringListParameter(paramName, splitByCommaWithoutQuotes(value)); break; default: ctx.addStringParameter(paramName, value); diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityKeyMappingTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityKeyMappingTest.java index 7d6d23f248..2ccab3cf29 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityKeyMappingTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/query/EntityKeyMappingTest.java @@ -24,7 +24,7 @@ import org.springframework.test.context.junit4.SpringRunner; import java.util.List; -import static org.thingsboard.server.common.data.StringUtils.getListValuesWithoutQuote; +import static org.thingsboard.server.common.data.StringUtils.splitByCommaWithoutQuotes; @RunWith(SpringRunner.class ) @SpringBootTest(classes = EntityKeyMapping.class) @@ -38,39 +38,39 @@ public class EntityKeyMappingTest { @Test public void testSplitToList() { String value = "device1, device2, device3"; - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); } @Test public void testReplaceSingleQuote() { String value = "'device1', 'device2', 'device3'"; - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); } @Test public void testReplaceDoubleQuote() { String value = "\"device1\", \"device2\", \"device3\""; - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); } @Test public void testSplitWithoutSpace() { String value = "\"device1\" , \"device2\" , \"device3\""; - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); } @Test public void testSaveSpacesBetweenString() { String value = "device 1 , device 2 , device 3"; List result = List.of("device 1", "device 2", "device 3"); - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); } @Test public void testSaveQuoteInString() { String value = "device ''1 , device \"\"2 , device \"'3"; List result = List.of("device ''1", "device \"\"2", "device \"'3"); - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); } @Test @@ -78,28 +78,28 @@ public class EntityKeyMappingTest { String value = "\"device1\", 'device2', \"device3\""; List result = List.of("\"device1\"", "'device2'", "\"device3\""); - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); value = "'device1', \"device2\", \"device3\""; result = List.of("'device1'", "\"device2\"", "\"device3\""); - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); value = "device1, 'device2', \"device3\""; result = List.of("device1", "'device2'", "\"device3\""); - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); value = "'device1', device2, \"device3\""; result = List.of("'device1'", "device2", "\"device3\""); - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); value = "device1, \"device2\", \"device3\""; result = List.of("device1", "\"device2\"", "\"device3\""); - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); value = "\"device1\", device2, \"device3\""; result = List.of("\"device1\"", "device2", "\"device3\""); - Assert.assertEquals(getListValuesWithoutQuote(value), result); + Assert.assertEquals(splitByCommaWithoutQuotes(value), result); } } \ No newline at end of file diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java index 028afa25ce..ada54ad26e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmRuleState.java @@ -51,7 +51,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.Function; import static org.thingsboard.server.common.data.StringUtils.equalsAny; -import static org.thingsboard.server.common.data.StringUtils.getListValuesWithoutQuote; +import static org.thingsboard.server.common.data.StringUtils.splitByCommaWithoutQuotes; @Data @Slf4j @@ -471,9 +471,9 @@ class AlarmRuleState { case NOT_CONTAINS: return !val.contains(predicateValue); case IN: - return equalsAny(val, getListValuesWithoutQuote(predicateValue).toArray(new String[0])); + return equalsAny(val, splitByCommaWithoutQuotes(predicateValue)); case NOT_IN: - return !equalsAny(val, getListValuesWithoutQuote(predicateValue).toArray(new String[0])); + return !equalsAny(val, splitByCommaWithoutQuotes(predicateValue)); default: throw new RuntimeException("Operation not supported: " + predicate.getOperation()); } From f878df58a9027d9f47f0eec1ede2c867465e2882 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 14 Feb 2024 12:17:19 +0200 Subject: [PATCH 218/397] Fix NPE in transport rate limit service on tenant update --- .../limits/DefaultTransportRateLimitService.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java index 58f94b0b00..473ecc39af 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/limits/DefaultTransportRateLimitService.java @@ -93,7 +93,7 @@ public class DefaultTransportRateLimitService implements TransportRateLimitServi EntityTransportRateLimits deviceRateLimitPrototype = createRateLimits(update.getProfile(), false); for (TenantId tenantId : update.getAffectedTenants()) { mergeLimits(tenantId, tenantRateLimitPrototype, perTenantLimits::get, perTenantLimits::put); - tenantDevices.get(tenantId).forEach(deviceId -> { + getTenantDevices(tenantId).forEach(deviceId -> { mergeLimits(deviceId, deviceRateLimitPrototype, perDeviceLimits::get, perDeviceLimits::put); }); } @@ -104,7 +104,7 @@ public class DefaultTransportRateLimitService implements TransportRateLimitServi EntityTransportRateLimits tenantRateLimitPrototype = createRateLimits(tenantProfileCache.get(tenantId), true); EntityTransportRateLimits deviceRateLimitPrototype = createRateLimits(tenantProfileCache.get(tenantId), false); mergeLimits(tenantId, tenantRateLimitPrototype, perTenantLimits::get, perTenantLimits::put); - tenantDevices.get(tenantId).forEach(deviceId -> { + getTenantDevices(tenantId).forEach(deviceId -> { mergeLimits(deviceId, deviceRateLimitPrototype, perDeviceLimits::get, perDeviceLimits::put); }); } @@ -259,8 +259,13 @@ public class DefaultTransportRateLimitService implements TransportRateLimitServi private EntityTransportRateLimits getDeviceRateLimits(TenantId tenantId, DeviceId deviceId) { return perDeviceLimits.computeIfAbsent(deviceId, k -> { EntityTransportRateLimits limits = createRateLimits(tenantProfileCache.get(tenantId), false); - tenantDevices.computeIfAbsent(tenantId, id -> ConcurrentHashMap.newKeySet()).add(deviceId); + getTenantDevices(tenantId).add(deviceId); return limits; }); } + + private Set getTenantDevices(TenantId tenantId) { + return tenantDevices.computeIfAbsent(tenantId, id -> ConcurrentHashMap.newKeySet()); + } + } From 724e95975a7fb505864278b1086283b18e773938 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 14 Feb 2024 12:41:19 +0200 Subject: [PATCH 219/397] Test isManagedByCurrentService --- .../discovery/HashPartitionServiceTest.java | 75 +++++++++---------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java b/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java index e67bbb9506..4d389b4210 100644 --- a/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/queue/discovery/HashPartitionServiceTest.java @@ -63,7 +63,6 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -73,9 +72,9 @@ public class HashPartitionServiceTest { public static final int ITERATIONS = 1000000; public static final int SERVER_COUNT = 3; - private HashPartitionService clusterRoutingService; + private HashPartitionService partitionService; - private TbServiceInfoProvider discoveryService; + private TbServiceInfoProvider serviceInfoProvider; private TenantRoutingInfoService routingInfoService; private ApplicationEventPublisher applicationEventPublisher; private QueueRoutingInfoService queueRoutingInfoService; @@ -85,19 +84,17 @@ public class HashPartitionServiceTest { @Before public void setup() throws Exception { - discoveryService = mock(TbServiceInfoProvider.class); + serviceInfoProvider = mock(TbServiceInfoProvider.class); applicationEventPublisher = mock(ApplicationEventPublisher.class); routingInfoService = mock(TenantRoutingInfoService.class); queueRoutingInfoService = mock(QueueRoutingInfoService.class); topicService = mock(TopicService.class); when(topicService.buildTopicName(Mockito.any())).thenAnswer(i -> i.getArguments()[0]); - clusterRoutingService = createPartitionService(); + partitionService = createPartitionService(); ServiceInfo currentServer = ServiceInfo.newBuilder() .setServiceId("tb-core-0") .addAllServiceTypes(Collections.singletonList(ServiceType.TB_CORE.name())) .build(); -// when(queueService.resolve(Mockito.any(), Mockito.anyString())).thenAnswer(i -> i.getArguments()[1]); -// when(discoveryService.getServiceInfo()).thenReturn(currentServer); List otherServers = new ArrayList<>(); for (int i = 1; i < SERVER_COUNT; i++) { otherServers.add(ServiceInfo.newBuilder() @@ -106,7 +103,7 @@ public class HashPartitionServiceTest { .build()); } - clusterRoutingService.recalculatePartitions(currentServer, otherServers); + partitionService.recalculatePartitions(currentServer, otherServers); } @Test @@ -122,7 +119,7 @@ public class HashPartitionServiceTest { long start = System.currentTimeMillis(); Map map = new HashMap<>(); for (DeviceId deviceId : devices) { - TopicPartitionInfo address = clusterRoutingService.resolve(ServiceType.TB_CORE, TenantId.SYS_TENANT_ID, deviceId); + TopicPartitionInfo address = partitionService.resolve(ServiceType.TB_CORE, TenantId.SYS_TENANT_ID, deviceId); Integer partition = address.getPartition().get(); map.put(partition, map.getOrDefault(partition, 0) + 1); } @@ -156,7 +153,7 @@ public class HashPartitionServiceTest { for (int queueIndex = 0; queueIndex < queueCount; queueIndex++) { QueueKey queueKey = new QueueKey(ServiceType.TB_RULE_ENGINE, "queue" + queueIndex, tenantId); for (int partition = 0; partition < partitionCount; partition++) { - ServiceInfo serviceInfo = clusterRoutingService.resolveByPartitionIdx(services, queueKey, partition, Collections.emptyMap()); + ServiceInfo serviceInfo = partitionService.resolveByPartitionIdx(services, queueKey, partition, Collections.emptyMap()); String serviceId = serviceInfo.getServiceId(); map.put(serviceId, map.get(serviceId) + 1); } @@ -233,15 +230,34 @@ public class HashPartitionServiceTest { } Map>> serversPartitions = new HashMap<>(); - clusterRoutingService.init(); + when(serviceInfoProvider.isService(eq(ServiceType.TB_RULE_ENGINE))).thenReturn(true); + partitionService.init(); for (ServiceInfo ruleEngine : ruleEngines) { List other = new ArrayList<>(ruleEngines); other.removeIf(serviceInfo -> serviceInfo.getServiceId().equals(ruleEngine.getServiceId())); - clusterRoutingService.recalculatePartitions(ruleEngine, other); - clusterRoutingService.myPartitions.forEach((queueKey, partitions) -> { + partitionService.recalculatePartitions(ruleEngine, other); + partitionService.myPartitions.forEach((queueKey, partitions) -> { serversPartitions.computeIfAbsent(queueKey, k -> new HashMap<>()).put(ruleEngine, partitions); }); + + Set assignedTenantProfiles = ruleEngine.getAssignedTenantProfilesList().stream().map(UUID::fromString).collect(Collectors.toSet()); + when(serviceInfoProvider.getAssignedTenantProfiles()).thenReturn(assignedTenantProfiles); + if (assignedTenantProfiles.isEmpty()) { + assertThat(partitionService.isManagedByCurrentService(TenantId.SYS_TENANT_ID)).isTrue(); + tenants.forEach((tenantId, tenantProfileId) -> { + assertThat(partitionService.isManagedByCurrentService(tenantId)).isFalse(); + }); + } else { + assertThat(partitionService.isManagedByCurrentService(TenantId.SYS_TENANT_ID)).isFalse(); + tenants.forEach((tenantId, tenantProfileId) -> { + if (assignedTenantProfiles.contains(tenantProfileId.getId())) { + assertThat(partitionService.isManagedByCurrentService(tenantId)).isTrue(); + } else { + assertThat(partitionService.isManagedByCurrentService(tenantId)).isFalse(); + } + }); + } } assertThat(serversPartitions.keySet()).containsAll(queues.stream().map(queue -> new QueueKey(ServiceType.TB_RULE_ENGINE, queue)).collect(Collectors.toList())); @@ -286,7 +302,7 @@ public class HashPartitionServiceTest { mockRoutingInfo(tenantId, tenantProfileId, false); // not isolated yet mockQueues(queues); - when(discoveryService.isService(eq(ServiceType.TB_RULE_ENGINE))).thenReturn(true); + when(serviceInfoProvider.isService(eq(ServiceType.TB_RULE_ENGINE))).thenReturn(true); Mockito.reset(applicationEventPublisher); HashPartitionService partitionService_common = createPartitionService(); partitionService_common.recalculatePartitions(commonRuleEngine, List.of(dedicatedRuleEngine)); @@ -349,27 +365,6 @@ public class HashPartitionServiceTest { }); } - @Test - public void testIsManagedByCurrentServiceCheck() { - TenantProfileId isolatedProfileId = new TenantProfileId(UUID.randomUUID()); - when(discoveryService.getAssignedTenantProfiles()).thenReturn(Set.of(isolatedProfileId.getId())); // dedicated server - TenantProfileId regularProfileId = new TenantProfileId(UUID.randomUUID()); - - TenantId isolatedTenantId = new TenantId(UUID.randomUUID()); - mockRoutingInfo(isolatedTenantId, isolatedProfileId, true); - TenantId regularTenantId = new TenantId(UUID.randomUUID()); - mockRoutingInfo(regularTenantId, regularProfileId, false); - - assertThat(clusterRoutingService.isManagedByCurrentService(isolatedTenantId)).isTrue(); - assertThat(clusterRoutingService.isManagedByCurrentService(regularTenantId)).isFalse(); - - - when(discoveryService.getAssignedTenantProfiles()).thenReturn(Collections.emptySet()); // common server - - assertThat(clusterRoutingService.isManagedByCurrentService(isolatedTenantId)).isTrue(); - assertThat(clusterRoutingService.isManagedByCurrentService(regularTenantId)).isTrue(); - } - @Test public void testPartitionsDistribution_sameTenantDifferentQueues() { List ruleEngines = new ArrayList<>(); @@ -389,9 +384,9 @@ public class HashPartitionServiceTest { .limit(100).collect(Collectors.toList()); for (int partition = 0; partition < 10; partition++) { - ServiceInfo expectedAssignedRuleEngine = clusterRoutingService.resolveByPartitionIdx(ruleEngines, new QueueKey(ServiceType.TB_RULE_ENGINE, tenantId), partition, Collections.emptyMap()); + ServiceInfo expectedAssignedRuleEngine = partitionService.resolveByPartitionIdx(ruleEngines, new QueueKey(ServiceType.TB_RULE_ENGINE, tenantId), partition, Collections.emptyMap()); for (QueueKey queueKey : queues) { - ServiceInfo assignedRuleEngine = clusterRoutingService.resolveByPartitionIdx(ruleEngines, queueKey, partition, Collections.emptyMap()); + ServiceInfo assignedRuleEngine = partitionService.resolveByPartitionIdx(ruleEngines, queueKey, partition, Collections.emptyMap()); assertThat(assignedRuleEngine).as(queueKey + "[" + partition + "] should be assigned to " + expectedAssignedRuleEngine.getServiceId()) .isEqualTo(expectedAssignedRuleEngine); } @@ -403,9 +398,9 @@ public class HashPartitionServiceTest { verify(applicationEventPublisher).publishEvent(argThat(event -> event instanceof PartitionChangeEvent && predicate.test((PartitionChangeEvent) event))); } - private void mockRoutingInfo(TenantId tenantId, TenantProfileId tenantProfileId, boolean isolatedTbRuleEngine) { + private void mockRoutingInfo(TenantId tenantId, TenantProfileId tenantProfileId, boolean isolated) { when(routingInfoService.getRoutingInfo(eq(tenantId))) - .thenReturn(new TenantRoutingInfo(tenantId, tenantProfileId, isolatedTbRuleEngine)); + .thenReturn(new TenantRoutingInfo(tenantId, tenantProfileId, isolated)); } private void mockQueues(List queues) { @@ -424,7 +419,7 @@ public class HashPartitionServiceTest { } private HashPartitionService createPartitionService() { - HashPartitionService partitionService = new HashPartitionService(discoveryService, + HashPartitionService partitionService = new HashPartitionService(serviceInfoProvider, routingInfoService, applicationEventPublisher, queueRoutingInfoService, From 0bfdd9b27c176768d65a6521be2250a265493f59 Mon Sep 17 00:00:00 2001 From: okolesnyk Date: Tue, 16 May 2023 12:26:10 +0300 Subject: [PATCH 220/397] UI. Device profile > Alarm rules (captions)(PROD-3051) --- .../profile/alarm/device-profile-alarm.component.html | 1 - ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 +- ui-ngx/src/assets/locale/locale.constant-ko_KR.json | 2 +- ui-ngx/src/assets/locale/locale.constant-sl_SI.json | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html index 96494faecd..502d80fb31 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html @@ -73,7 +73,6 @@ close Date: Wed, 14 Feb 2024 13:17:16 +0200 Subject: [PATCH 221/397] fixed spelling mistake --- .../home/components/filter/filter-predicate-value.component.ts | 2 +- ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts index 473e01801f..2f3d29df91 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts @@ -85,7 +85,7 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, Vali @Input() set operation(operation: StringOperation) { if (operation && (operation === StringOperation.IN || operation === StringOperation.NOT_IN)) { - this.hintText = 'filter.default-coma-separated-values'; + this.hintText = 'filter.default-comma-separated-values'; } else { this.hintText = 'filter.default-value'; } 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 cb77262623..b12e97c856 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -2667,7 +2667,7 @@ "current-user": "Current user", "current-device": "Current device", "default-value": "Default value", - "default-coma-separated-values": "Default coma separated values", + "default-comma-separated-values": "Default comma-separated values", "dynamic-source-type": "Dynamic source type", "dynamic-value": "Dynamic value", "no-dynamic-value": "No dynamic value", From 005d555bc5c8c3cc1e508062e51f3e51f925d1df Mon Sep 17 00:00:00 2001 From: Alexander Keidel Date: Fri, 9 Feb 2024 12:37:48 +0100 Subject: [PATCH 222/397] Global Queue Prefix is now correctly respected by js-executor, rule-node and tb-rule-engine-notifications-node- consumer groups --- .../server/queue/provider/KafkaMonolithQueueFactory.java | 2 +- .../server/queue/provider/KafkaTbCoreQueueFactory.java | 2 +- .../server/queue/provider/KafkaTbRuleEngineQueueFactory.java | 4 ++-- msa/js-executor/queue/kafkaTemplate.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java index 662d29af5b..3459096e08 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java @@ -269,7 +269,7 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi responseBuilder.settings(kafkaSettings); responseBuilder.topic(jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId()); responseBuilder.clientId("js-" + serviceInfoProvider.getServiceId()); - responseBuilder.groupId("rule-engine-node-" + serviceInfoProvider.getServiceId()); + responseBuilder.groupId(topicService.buildTopicName("rule-engine-node-") + serviceInfoProvider.getServiceId()); responseBuilder.decoder(msg -> { JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java index db6ee52181..1852693304 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbCoreQueueFactory.java @@ -226,7 +226,7 @@ public class KafkaTbCoreQueueFactory implements TbCoreQueueFactory { responseBuilder.settings(kafkaSettings); responseBuilder.topic(jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId()); responseBuilder.clientId("js-" + serviceInfoProvider.getServiceId()); - responseBuilder.groupId("rule-engine-node-" + serviceInfoProvider.getServiceId()); + responseBuilder.groupId(topicService.buildTopicName("rule-engine-node-") + serviceInfoProvider.getServiceId()); responseBuilder.decoder(msg -> { JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java index 2b20afac84..63798f95a1 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java @@ -179,7 +179,7 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { consumerBuilder.settings(kafkaSettings); consumerBuilder.topic(topicService.getNotificationsTopic(ServiceType.TB_RULE_ENGINE, serviceInfoProvider.getServiceId()).getFullTopicName()); consumerBuilder.clientId("tb-rule-engine-notifications-consumer-" + serviceInfoProvider.getServiceId()); - consumerBuilder.groupId("tb-rule-engine-notifications-node-" + serviceInfoProvider.getServiceId()); + consumerBuilder.groupId(topicService.buildTopicName("tb-rule-engine-notifications-node-") + serviceInfoProvider.getServiceId()); consumerBuilder.decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), ToRuleEngineNotificationMsg.parseFrom(msg.getData()), msg.getHeaders())); consumerBuilder.admin(notificationAdmin); consumerBuilder.statsService(consumerStatsService); @@ -199,7 +199,7 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { responseBuilder.settings(kafkaSettings); responseBuilder.topic(jsInvokeSettings.getResponseTopic() + "." + serviceInfoProvider.getServiceId()); responseBuilder.clientId("js-" + serviceInfoProvider.getServiceId()); - responseBuilder.groupId("rule-engine-node-" + serviceInfoProvider.getServiceId()); + responseBuilder.groupId(topicService.buildTopicName("rule-engine-node-") + serviceInfoProvider.getServiceId()); responseBuilder.decoder(msg -> { JsInvokeProtos.RemoteJsResponse.Builder builder = JsInvokeProtos.RemoteJsResponse.newBuilder(); JsonFormat.parser().ignoringUnknownFields().merge(new String(msg.getData(), StandardCharsets.UTF_8), builder); diff --git a/msa/js-executor/queue/kafkaTemplate.ts b/msa/js-executor/queue/kafkaTemplate.ts index 07290d0d4c..4ba3a1aee1 100644 --- a/msa/js-executor/queue/kafkaTemplate.ts +++ b/msa/js-executor/queue/kafkaTemplate.ts @@ -64,7 +64,7 @@ export class KafkaTemplate implements IQueue { const queuePrefix: string = config.get('queue_prefix'); const requestTopic: string = queuePrefix ? queuePrefix + "." + config.get('request_topic') : config.get('request_topic'); const useConfluent = config.get('kafka.use_confluent_cloud'); - + const groupId:string = queuePrefix ? queuePrefix + ".js-executor-group" : "js-executor-group"; this.logger.info('Kafka Bootstrap Servers: %s', kafkaBootstrapServers); this.logger.info('Kafka Requests Topic: %s', requestTopic); @@ -119,7 +119,7 @@ export class KafkaTemplate implements IQueue { } } - this.consumer = this.kafkaClient.consumer({groupId: 'js-executor-group'}); + this.consumer = this.kafkaClient.consumer({groupId: groupId}); this.producer = this.kafkaClient.producer({createPartitioner: Partitioners.DefaultPartitioner}); const {CRASH} = this.consumer.events; From 094cff6174039febbf3fc3a4b64bc99085f79942 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 14 Feb 2024 14:01:20 +0200 Subject: [PATCH 223/397] Tell failure if originator is not a device --- .../thingsboard/rule/engine/action/TbDeviceStateNode.java | 7 +++++-- .../rule/engine/action/TbDeviceStateNodeTest.java | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) 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 9d6901ea01..b0f426d905 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 @@ -98,8 +98,11 @@ public class TbDeviceStateNode implements TbNode { return; } - if (!EntityType.DEVICE.equals(msg.getOriginator().getEntityType())) { - ctx.tellSuccess(msg); + EntityType originatorEntityType = msg.getOriginator().getEntityType(); + if (!EntityType.DEVICE.equals(originatorEntityType)) { + ctx.tellFailure(msg, new IllegalArgumentException( + "Unsupported originator entity type: [" + originatorEntityType + "]. Only DEVICE entity type is supported." + )); return; } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java index d66babea9a..19cb3c55bd 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java @@ -263,7 +263,12 @@ public class TbDeviceStateNodeTest { node.onMsg(ctxMock, msg); // THEN - then(ctxMock).should().tellSuccess(msg); + var exceptionCaptor = ArgumentCaptor.forClass(Exception.class); + then(ctxMock).should().tellFailure(eq(msg), exceptionCaptor.capture()); + assertThat(exceptionCaptor.getValue()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Unsupported originator entity type: [" + unsupportedType + "]. Only DEVICE entity type is supported."); + then(ctxMock).shouldHaveNoMoreInteractions(); } From 85f441c7c040ccc52b5da0f34350d57aaf95d589 Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 14 Feb 2024 14:49:30 +0200 Subject: [PATCH 224/397] lwm2m: if client after registration change port: update registration - ok --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 5 +- .../AbstractSecurityLwM2MIntegrationTest.java | 33 +++++++ ...rityLwM2MIntegrationDtlsCidLengthTest.java | 48 --------- ...oSecLwM2MIntegrationDtlsCidLengthTest.java | 1 - .../PskLwm2mIntegrationDtlsCidLengthTest.java | 4 +- ...oSecLwM2MIntegrationDtlsCidLengthTest.java | 1 - .../PskLwm2mIntegrationDtlsCidLengthTest.java | 3 +- ...oSecLwM2MIntegrationDtlsCidLengthTest.java | 1 - .../PskLwm2mIntegrationDtlsCidLengthTest.java | 3 +- .../AbstractLwM2MIntegrationDiffPortTest.java | 99 +++++++++++++++++++ .../LwM2MIntegrationDiffPortTest.java | 45 +++++++++ .../store/TbInMemoryRegistrationStore.java | 13 ++- 12 files changed, 193 insertions(+), 63 deletions(-) create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java create mode 100644 application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/LwM2MIntegrationDiffPortTest.java diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 7b989a1997..1eedd74608 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -97,6 +97,8 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClient import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_INIT; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; @@ -172,9 +174,8 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte " \"pagingTransmissionWindow\": null,\n" + " \"clientOnlyObserveAfterConnect\": 1\n" + " }"; - - protected final Set expectedStatusesBsSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS)); protected final Set expectedStatusesRegistrationLwm2mSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); + protected final Set expectedStatusesRegistrationLwm2mSuccessUpdate = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS, ON_UPDATE_STARTED, ON_UPDATE_SUCCESS)); protected final Set expectedStatusesRegistrationBsSuccess = new HashSet<>(Arrays.asList(ON_BOOTSTRAP_STARTED, ON_BOOTSTRAP_SUCCESS, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS)); protected DeviceProfile deviceProfile; protected ScheduledExecutorService executor; diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index f164cb7fe7..f66d4ef4b8 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -26,6 +26,7 @@ import org.junit.Assert; import org.springframework.test.web.servlet.MvcResult; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.device.credentials.lwm2m.AbstractLwM2MClientSecurityCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MBootstrapClientCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredential; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; @@ -50,6 +51,7 @@ import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootst import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; @@ -59,13 +61,16 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Random; import java.util.Set; import java.util.concurrent.TimeUnit; import static org.awaitility.Awaitility.await; import static org.eclipse.leshan.client.object.Security.noSecBootstrap; +import static org.eclipse.leshan.client.object.Security.psk; import static org.junit.Assert.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_STARTED; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_DEREGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; @@ -118,6 +123,13 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M private final LwM2MBootstrapClientCredentials defaultBootstrapCredentials; + protected AbstractLwM2MClientSecurityCredential clientCredentials; + protected Security security; + protected Lwm2mDeviceProfileTransportConfiguration transportConfiguration; + protected LwM2MDeviceCredentials deviceCredentials; + protected String clientEndpoint; + protected final Random randomSuffix = new Random(); + public AbstractSecurityLwM2MIntegrationTest() { // create client credentials @@ -381,6 +393,27 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M return bootstrapCredentials; } + + protected void initDeviceCredentialsNoSek() { + clientEndpoint = CLIENT_ENDPOINT_NO_SEC + "_" + randomSuffix.nextInt(100); + security = SECURITY_NO_SEC; + deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); + } + protected void initDeviceCredentialsPsk() { + int suf = randomSuffix.nextInt(10); + clientEndpoint = CLIENT_ENDPOINT_PSK + "_" + suf; + String identity = CLIENT_PSK_IDENTITY + "_" + suf; + clientCredentials = new PSKClientCredential(); + clientCredentials.setEndpoint(clientEndpoint); + ((PSKClientCredential)clientCredentials).setIdentity(identity); + clientCredentials.setKey(CLIENT_PSK_KEY); + security = psk(SECURE_URI, + shortServerId, + identity.getBytes(StandardCharsets.UTF_8), + Hex.decodeHex(CLIENT_PSK_KEY.toCharArray())); + deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); + } + private LwM2MBootstrapClientCredentials getBootstrapClientCredentialsRpk(X509Certificate certificate, PrivateKey privateKey, boolean privateKeyIsBad) { LwM2MBootstrapClientCredentials bootstrapCredentials = new LwM2MBootstrapClientCredentials(); RPKBootstrapClientCredential serverCredentials = new RPKBootstrapClientCredential(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java index c743308fcd..f44a2b1874 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java @@ -19,34 +19,16 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpoint; import org.eclipse.leshan.client.californium.endpoint.CaliforniumClientEndpointsProvider; -import org.eclipse.leshan.client.object.Security; -import org.eclipse.leshan.core.util.Hex; import org.junit.Assert; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.device.credentials.lwm2m.AbstractLwM2MClientSecurityCredential; -import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; -import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; -import org.thingsboard.server.common.data.device.credentials.lwm2m.PSKClientCredential; -import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.dao.service.DaoSqlTest; -import org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Random; -import java.util.Set; import java.util.concurrent.TimeUnit; import static org.awaitility.Awaitility.await; import static org.eclipse.californium.scandium.config.DtlsConfig.DTLS_CONNECTION_ID_LENGTH; -import static org.eclipse.leshan.client.object.Security.psk; -import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_INIT; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_READ_CONNECTION_ID; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; -import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_SUCCESS; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_WRITE_CONNECTION_ID; @@ -54,17 +36,7 @@ import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClient @Slf4j public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationTest { - protected AbstractLwM2MClientSecurityCredential clientCredentials; - protected Security security; - protected Lwm2mDeviceProfileTransportConfiguration transportConfiguration; - protected LwM2MDeviceCredentials deviceCredentials; - protected String clientEndpoint; - protected LwM2MSecurityMode lwM2MSecurityMode; protected String awaitAlias; - protected final Random randomSuffix = new Random(); - - protected final Set expectedStatusesRegistrationLwm2mDtlsCidSuccess = new HashSet<>(Arrays.asList(ON_INIT, ON_REGISTRATION_STARTED, ON_REGISTRATION_SUCCESS, ON_READ_CONNECTION_ID, ON_WRITE_CONNECTION_ID)); - protected void testNoSecDtlsCidLength(Integer dtlsCidLength, Integer serverDtlsCidLength) throws Exception { initDeviceCredentialsNoSek(); @@ -75,26 +47,6 @@ public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLengthTest extends basicTestConnectionDtlsCidLength(dtlsCidLength, serverDtlsCidLength); } - protected void initDeviceCredentialsNoSek() { - clientEndpoint = CLIENT_ENDPOINT_NO_SEC + "_" + randomSuffix.nextInt(100); - deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); - } - - protected void initDeviceCredentialsPsk() { - int suf = randomSuffix.nextInt(10); - clientEndpoint = CLIENT_ENDPOINT_PSK + "_" + suf; - String identity = CLIENT_PSK_IDENTITY + "_" + suf; - clientCredentials = new PSKClientCredential(); - clientCredentials.setEndpoint(clientEndpoint); - ((PSKClientCredential)clientCredentials).setIdentity(identity); - clientCredentials.setKey(CLIENT_PSK_KEY); - security = psk(SECURE_URI, - shortServerId, - identity.getBytes(StandardCharsets.UTF_8), - Hex.decodeHex(CLIENT_PSK_KEY.toCharArray())); - deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); - } - protected void basicTestConnectionDtlsCidLength(Integer clientDtlsCidLength, Integer serverDtlsCidLength) throws Exception { createDeviceProfile(transportConfiguration); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java index f43ae3af0c..8ce9053e5e 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/NoSecLwM2MIntegrationDtlsCidLengthTest.java @@ -26,7 +26,6 @@ public class NoSecLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2 @Before public void setUpNoSecDtlsCidLength() { - security = SECURITY_NO_SEC; transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); awaitAlias = "await on client state (NoSec_Lwm2m) DtlsCidLength = 0"; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java index 38010111fa..1d73025edc 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_0/PskLwm2mIntegrationDtlsCidLengthTest.java @@ -18,13 +18,15 @@ package org.thingsboard.server.transport.lwm2m.security.cid.serverDtlsCidLength_ import org.junit.Before; import org.junit.Test; import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength0Test; + +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; public class PskLwm2mIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength0Test { @Before public void createProfileRpc() { - transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(lwM2MSecurityMode, NONE)); + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, NONE)); awaitAlias = "await on client state (Psk_Lwm2m) DtlsCidLength = 0"; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java index 377ccf420a..932632a359 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/NoSecLwM2MIntegrationDtlsCidLengthTest.java @@ -26,7 +26,6 @@ public class NoSecLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2 @Before public void setUpNoSecDtlsCidLength() { - security = SECURITY_NO_SEC; transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); awaitAlias = "await on client state (NoSec_Lwm2m) DtlsCidLength = 3"; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java index afe436cdbc..6049b57f77 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_3/PskLwm2mIntegrationDtlsCidLengthTest.java @@ -19,13 +19,14 @@ import org.junit.Before; import org.junit.Test; import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLength3Test; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; public class PskLwm2mIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLength3Test { @Before public void createProfileRpc() { - transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(lwM2MSecurityMode, NONE)); + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, NONE)); awaitAlias = "await on client state (Psk_Lwm2m) DtlsCidLength = 3"; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java index d5531f6354..d8c7c67b2b 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/NoSecLwM2MIntegrationDtlsCidLengthTest.java @@ -26,7 +26,6 @@ public class NoSecLwM2MIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2 @Before public void setUpNoSecDtlsCidLength() { - security = SECURITY_NO_SEC; transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); awaitAlias = "await on client state (NoSec_Lwm2m) DtlsCidLength = Null"; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java index 5c712f78d6..6fefaf7622 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/serverDtlsCidLength_null/PskLwm2mIntegrationDtlsCidLengthTest.java @@ -19,13 +19,14 @@ import org.junit.Before; import org.junit.Test; import org.thingsboard.server.transport.lwm2m.security.cid.AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; public class PskLwm2mIntegrationDtlsCidLengthTest extends AbstractSecurityLwM2MIntegrationDtlsCidLengthNullTest { @Before public void createProfileRpc() { - transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(lwM2MSecurityMode, NONE)); + transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, NONE)); awaitAlias = "await on client state (Psk_Lwm2m) DtlsCidLength = Null"; } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java new file mode 100644 index 0000000000..89ff598bc2 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.security.diffPort; + +import lombok.extern.slf4j.Slf4j; +import org.eclipse.leshan.core.peer.IpPeer; +import org.eclipse.leshan.core.peer.LwM2mPeer; +import org.eclipse.leshan.core.peer.SocketIdentity; +import org.eclipse.leshan.server.registration.RegistrationStore; +import org.eclipse.leshan.server.registration.RegistrationUpdate; +import org.junit.Assert; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; +import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_STARTED; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_REGISTRATION_SUCCESS; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MClientState.ON_UPDATE_SUCCESS; + +@DaoSqlTest +@Slf4j +public abstract class AbstractLwM2MIntegrationDiffPortTest extends AbstractSecurityLwM2MIntegrationTest { + + @SpyBean + private RegistrationStore registrationStoreTest; + + protected void basicTestConnectionDifferentPort(Lwm2mDeviceProfileTransportConfiguration transportConfiguration, + String awaitAlias) throws Exception { + + createDeviceProfile(transportConfiguration); + createDevice(deviceCredentials, clientEndpoint); + createNewClient(security, null, COAP_CONFIG, true, clientEndpoint); + lwM2MTestClient.start(true); + await(awaitAlias) + .atMost(40, TimeUnit.SECONDS) + .until(() -> lwM2MTestClient.getClientStates().contains(ON_REGISTRATION_SUCCESS) || lwM2MTestClient.getClientStates().contains(ON_REGISTRATION_STARTED)); + Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatusesRegistrationLwm2mSuccess)); + + await(awaitAlias) + .atMost(40, TimeUnit.SECONDS) + .until(() -> { + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + Object[] arguments = invocation.getArguments(); + if (arguments.length > 0 && arguments[0] instanceof RegistrationUpdate) { + int portOld = ((RegistrationUpdate) arguments[0]).getPort(); + int portValueChange = 5; + arguments[0] = registrationUpdateNewPort((RegistrationUpdate) arguments[0], portValueChange); + int portNew = ((RegistrationUpdate) arguments[0]).getPort(); + Assert.assertEquals((portNew - portOld), portValueChange); + } + return invocation.callRealMethod(); + } + }).when(registrationStoreTest).updateRegistration(any(RegistrationUpdate.class)); + return lwM2MTestClient.getClientStates().contains(ON_UPDATE_SUCCESS); + }); + Assert.assertTrue(lwM2MTestClient.getClientStates().containsAll(expectedStatusesRegistrationLwm2mSuccessUpdate)); + } + + private RegistrationUpdate registrationUpdateNewPort (RegistrationUpdate update, int portValueChange) { + Integer portOld = update.getPort(); + Integer portNew = portOld + portValueChange; + log.warn("portOld: [{}], portNew: [{}]", portOld, portNew); + InetAddress addressOld = update.getAddress(); + InetSocketAddress socketAddressUpdate = new InetSocketAddress(addressOld, portNew); + SocketIdentity socketIdentity = new SocketIdentity(socketAddressUpdate); + LwM2mPeer sender = new IpPeer(new InetSocketAddress(addressOld, portNew), socketIdentity); + return new RegistrationUpdate(update.getRegistrationId(), sender, + update.getLifeTimeInSec(), update.getSmsNumber(), update.getBindingMode(), + update.getObjectLinks(), update.getAlternatePath(), + update.getSupportedContentFormats(), update.getSupportedObjects(), + update.getAvailableInstances(), update.getAdditionalAttributes(), + update.getApplicationData()); + } +} diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/LwM2MIntegrationDiffPortTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/LwM2MIntegrationDiffPortTest.java new file mode 100644 index 0000000000..204bc70b5f --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/LwM2MIntegrationDiffPortTest.java @@ -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. + */ +package org.thingsboard.server.transport.lwm2m.security.diffPort; + +import org.junit.Test; +import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; + +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.NO_SEC; +import static org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode.PSK; +import static org.thingsboard.server.transport.lwm2m.Lwm2mTestHelper.LwM2MProfileBootstrapConfigType.NONE; + +public class LwM2MIntegrationDiffPortTest extends AbstractLwM2MIntegrationDiffPortTest { + + @Test + public void testWithNoSecConnectLwm2mSuccess_AfterRegistration_UpdateRegistrationFromDifferentPort_Ok() throws Exception { + String awaitAlias = "await on client state (NoSec different port)"; + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(NO_SEC, NONE)); + initDeviceCredentialsNoSek(); + basicTestConnectionDifferentPort( + transportConfiguration, + awaitAlias); + } + @Test + public void testWithPskConnectLwm2mSuccess_AfterRegistration_UpdateRegistrationFromDifferentPort_Ok() throws Exception { + String awaitAlias = "await on client state (Psk different port)"; + Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(PSK, NONE)); + initDeviceCredentialsPsk(); + basicTestConnectionDifferentPort( + transportConfiguration, + awaitAlias); + } +} diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbInMemoryRegistrationStore.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbInMemoryRegistrationStore.java index a9f65ff0bf..60afd76ffb 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbInMemoryRegistrationStore.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/store/TbInMemoryRegistrationStore.java @@ -17,6 +17,7 @@ package org.thingsboard.server.transport.lwm2m.server.store; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.coap.Token; import org.eclipse.californium.core.network.RandomTokenGenerator; import org.eclipse.californium.core.network.TokenGenerator; @@ -40,8 +41,6 @@ import org.eclipse.leshan.server.registration.Registration; import org.eclipse.leshan.server.registration.RegistrationStore; import org.eclipse.leshan.server.registration.RegistrationUpdate; import org.eclipse.leshan.server.registration.UpdatedRegistration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; import org.thingsboard.server.transport.lwm2m.server.LwM2mVersionedModelProvider; @@ -68,8 +67,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import static org.eclipse.leshan.core.californium.ObserveUtil.CTX_CF_OBERSATION; import static org.eclipse.leshan.core.californium.ObserveUtil.extractSerializedObservation; +@Slf4j public class TbInMemoryRegistrationStore implements RegistrationStore, Startable, Stoppable, Destroyable { - private final Logger LOG = LoggerFactory.getLogger(TbInMemoryRegistrationStore.class); // Data structure private final Map regsByEp = new HashMap<>(); @@ -339,10 +338,10 @@ public class TbInMemoryRegistrationStore implements RegistrationStore, Startable if (addIfAbsent && previousObservation != null) { if (!existingObservation.getPath().equals(observation.getPath())) { removed.add(previousObservation); - LOG.warn("Token collision ? observation [{}] will be replaced by observation [{}], that this observation includes input observation [{}]!", + log.warn("Token collision ? observation [{}] will be replaced by observation [{}], that this observation includes input observation [{}]!", previousObservation, observation, observation); } else { - LOG.warn("Token collision ? existing observation [{}] includes input observation [{}]", + log.warn("Token collision ? existing observation [{}] includes input observation [{}]", existingObservation, observation); } } @@ -576,7 +575,7 @@ public class TbInMemoryRegistrationStore implements RegistrationStore, Startable try { schedExecutor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { - LOG.warn("Destroying InMemoryRegistrationStore was interrupted.", e); + log.warn("Destroying InMemoryRegistrationStore was interrupted.", e); } } @@ -602,7 +601,7 @@ public class TbInMemoryRegistrationStore implements RegistrationStore, Startable } } } catch (Exception e) { - LOG.warn("Unexpected Exception while registration cleaning", e); + log.warn("Unexpected Exception while registration cleaning", e); } } } From 541f6a3314099fd8614d06a97a0418ec939dbb77 Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 14 Feb 2024 15:50:31 +0200 Subject: [PATCH 225/397] lwm2m/coap: client queue Mode --- .../coap/client/DefaultCoapClientContext.java | 15 ++++++++------- .../server/client/LwM2mClientContextImpl.java | 8 ++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java index 735ec1d524..eaf105ee48 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/client/DefaultCoapClientContext.java @@ -220,7 +220,7 @@ public class DefaultCoapClientContext implements CoapClientContext { private void onUplink(TbCoapClientState client, boolean notifyOtherServers, long uplinkTs) { PowerMode powerMode = client.getPowerMode(); PowerSavingConfiguration profileSettings = null; - if (powerMode == null) { + if (powerMode == null && client.getProfileId() != null) { var clientProfile = getProfile(client.getProfileId()); if (clientProfile.isPresent()) { profileSettings = clientProfile.get().getClientSettings(); @@ -726,7 +726,7 @@ public class DefaultCoapClientContext implements CoapClientContext { private boolean isDownlinkAllowed(TbCoapClientState client) { PowerMode powerMode = client.getPowerMode(); PowerSavingConfiguration profileSettings = null; - if (powerMode == null) { + if (powerMode == null && client.getProfileId() != null) { var clientProfile = getProfile(client.getProfileId()); if (clientProfile.isPresent()) { profileSettings = clientProfile.get().getClientSettings(); @@ -775,11 +775,12 @@ public class DefaultCoapClientContext implements CoapClientContext { private PowerMode getPowerMode(TbCoapClientState client) { PowerMode powerMode = client.getPowerMode(); if (powerMode == null) { - Optional deviceProfile = getProfile(client.getProfileId()); - if (deviceProfile.isPresent()) { - powerMode = deviceProfile.get().getClientSettings().getPowerMode(); - } else { - powerMode = PowerMode.PSM; + powerMode = PowerMode.PSM; + if (client.getProfileId() != null) { + Optional deviceProfile = getProfile(client.getProfileId()); + if (deviceProfile.isPresent()) { + powerMode = deviceProfile.get().getClientSettings().getPowerMode(); + } } } return powerMode; diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java index 03449aaaef..18e27ba568 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/client/LwM2mClientContextImpl.java @@ -411,7 +411,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { public boolean isDownlinkAllowed(LwM2mClient client) { PowerMode powerMode = client.getPowerMode(); OtherConfiguration profileSettings = null; - if (powerMode == null) { + if (powerMode == null && client.getProfileId() != null) { var clientProfile = getProfile(client.getProfileId()); profileSettings = clientProfile.getClientLwM2mSettings(); powerMode = profileSettings.getPowerMode(); @@ -419,7 +419,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { powerMode = PowerMode.DRX; } } - if (PowerMode.DRX.equals(powerMode) || otaUpdateService.isOtaDownloading(client)) { + if (powerMode == null || PowerMode.DRX.equals(powerMode) || otaUpdateService.isOtaDownloading(client)) { return true; } client.lock(); @@ -460,7 +460,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { public void onUplink(LwM2mClient client) { PowerMode powerMode = client.getPowerMode(); OtherConfiguration profileSettings = null; - if (powerMode == null) { + if (powerMode == null && client.getProfileId() != null) { var clientProfile = getProfile(client.getProfileId()); profileSettings = clientProfile.getClientLwM2mSettings(); powerMode = profileSettings.getPowerMode(); @@ -468,7 +468,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { powerMode = PowerMode.DRX; } } - if (PowerMode.DRX.equals(powerMode)) { + if (powerMode == null || PowerMode.DRX.equals(powerMode)) { client.updateLastUplinkTime(); return; } From fcf5921b7e43185e2dc39843069b6d1b5369aa71 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 14 Feb 2024 15:59:41 +0200 Subject: [PATCH 226/397] UI: Clear style code in notification component --- .../sent-notification-dialog.component.html | 108 ++++++++--------- .../sent-notification-dialog.component.scss | 53 ++------ .../sent/sent-notification-dialog.componet.ts | 2 +- ...tion-template-configuration.component.html | 114 +++++++++--------- ...tion-template-configuration.component.scss | 10 +- ...emplate-notification-dialog.component.html | 4 +- ...emplate-notification-dialog.component.scss | 18 +-- .../app/shared/models/notification.models.ts | 4 +- 8 files changed, 132 insertions(+), 181 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html index 71daee5343..8f5d41de34 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html @@ -39,18 +39,10 @@ {{ 'notification.compose' | translate }}
    - - + + {{ 'notification.start-from-scratch' | translate }} + {{ 'notification.use-template' | translate }} +
    -
    notification.at-least-one-should-be-selected
    +
    notification.at-least-one-should-be-selected
    \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n\n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gt extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.alarmSeverities=Object.keys(b),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[ge,ye,xe],this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==x.TBEL||this.tbelEnabled||(r=x.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===x.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===x.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",gt),gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),gt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gt,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class yt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["entityType"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==F.DEVICE&&t!==F.ASSET?this.createRelationConfigForm.get("entityTypePattern").setValidators([]):this.createRelationConfigForm.get("entityTypePattern").setValidators([O.required,O.pattern(/.*\S.*/)]),this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",yt),yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yt,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bt extends f{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,O.required],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart,O.required]})}}e("DeviceProfileConfigComponent",bt),bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n',dependencies:[{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ht extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}var vt;e("GeneratorConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(vt||(vt={}));const Ct=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer"],[vt.TENANT,"tb.rulenode.originator-tenant"],[vt.RELATED,"tb.rulenode.originator-related"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[vt.ENTITY,"tb.rulenode.originator-entity"]]),Ft=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer-desc"],[vt.TENANT,"tb.rulenode.originator-tenant-desc"],[vt.RELATED,"tb.rulenode.originator-related-entity-desc"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[vt.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),kt=[k.createdTime,k.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},k.firstName,k.lastName,k.email,k.title,k.country,k.state,k.city,k.address,k.address2,k.zip,k.phone,k.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],Lt=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 Tt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Tt||(Tt={}));const It=new Map([[Tt.CIRCLE,"tb.rulenode.perimeter-circle"],[Tt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Nt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Nt||(Nt={}));const St=new Map([[Nt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Nt.SECONDS,"tb.rulenode.time-unit-seconds"],[Nt.MINUTES,"tb.rulenode.time-unit-minutes"],[Nt.HOURS,"tb.rulenode.time-unit-hours"],[Nt.DAYS,"tb.rulenode.time-unit-days"]]);var qt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(qt||(qt={}));const At=new Map([[qt.METER,"tb.rulenode.range-unit-meter"],[qt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[qt.FOOT,"tb.rulenode.range-unit-foot"],[qt.MILE,"tb.rulenode.range-unit-mile"],[qt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Mt;!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"}(Mt||(Mt={}));const Et=new Map([[Mt.ID,"tb.rulenode.entity-details-id"],[Mt.TITLE,"tb.rulenode.entity-details-title"],[Mt.COUNTRY,"tb.rulenode.entity-details-country"],[Mt.STATE,"tb.rulenode.entity-details-state"],[Mt.CITY,"tb.rulenode.entity-details-city"],[Mt.ZIP,"tb.rulenode.entity-details-zip"],[Mt.ADDRESS,"tb.rulenode.entity-details-address"],[Mt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Mt.PHONE,"tb.rulenode.entity-details-phone"],[Mt.EMAIL,"tb.rulenode.entity-details-email"],[Mt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Gt;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Gt||(Gt={}));const Dt=new Map([[Gt.FIRST,"tb.rulenode.first"],[Gt.LAST,"tb.rulenode.last"],[Gt.ALL,"tb.rulenode.all"]]),wt=new Map([[Gt.FIRST,"tb.rulenode.first-mode-hint"],[Gt.LAST,"tb.rulenode.last-mode-hint"],[Gt.ALL,"tb.rulenode.all-mode-hint"]]);var Vt,Pt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Vt||(Vt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(Pt||(Pt={}));const Rt=new Map([[Pt.ATTRIBUTES,"tb.rulenode.attributes"],[Pt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[Pt.FIELDS,"tb.rulenode.fields"]]),Ot=new Map([[Pt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[Pt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[Pt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),_t=new Map([[Vt.ASC,"tb.rulenode.ascending"],[Vt.DESC,"tb.rulenode.descending"]]);var Bt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Bt||(Bt={}));const Kt=new Map([[Bt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Bt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),zt=["anonymous","basic","cert.PEM"],Ut=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Ht=["sas","cert.PEM"],jt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var $t;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}($t||($t={}));const Qt=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],Jt=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 Yt;!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"}(Yt||(Yt={}));const Wt=new Map([[Yt.CUSTOM,{value:Yt.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[Yt.ADD,{value:Yt.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[Yt.SUB,{value:Yt.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[Yt.MULT,{value:Yt.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[Yt.DIV,{value:Yt.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[Yt.SIN,{value:Yt.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.SINH,{value:Yt.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[Yt.COS,{value:Yt.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.COSH,{value:Yt.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[Yt.TAN,{value:Yt.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[Yt.TANH,{value:Yt.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ACOS,{value:Yt.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[Yt.ASIN,{value:Yt.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN,{value:Yt.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN2,{value:Yt.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}],[Yt.EXP,{value:Yt.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[Yt.EXPM1,{value:Yt.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[Yt.SQRT,{value:Yt.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[Yt.CBRT,{value:Yt.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[Yt.GET_EXP,{value:Yt.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[Yt.HYPOT,{value:Yt.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[Yt.LOG,{value:Yt.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG10,{value:Yt.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG1P,{value:Yt.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[Yt.CEIL,{value:Yt.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR,{value:Yt.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR_DIV,{value:Yt.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[Yt.FLOOR_MOD,{value:Yt.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[Yt.ABS,{value:Yt.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[Yt.MIN,{value:Yt.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[Yt.MAX,{value:Yt.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[Yt.POW,{value:Yt.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}],[Yt.SIGNUM,{value:Yt.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[Yt.RAD,{value:Yt.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[Yt.DEG,{value:Yt.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var Zt,Xt,en;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(Zt||(Zt={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(Xt||(Xt={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(en||(en={}));const tn=new Map([[en.DATA,"tb.rulenode.message-to-metadata"],[en.METADATA,"tb.rulenode.metadata-to-message"]]),nn=(new Map([[en.DATA,"tb.rulenode.from-message"],[en.METADATA,"tb.rulenode.from-metadata"]]),new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.metadata"]])),rn=new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.message-metadata"]]),on=new Map([[Zt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[Zt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[Zt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[Zt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[Zt.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),an=new Map([[Xt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[Xt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[Xt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[Xt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),ln=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var sn,mn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(sn||(sn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(mn||(mn={}));const pn=new Map([[sn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[sn.SERVER_SCOPE,"tb.rulenode.server-scope"],[sn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);class dn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.keys(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.keys(qt),this.rangeUnitTranslationMap=At,this.timeUnits=Object.keys(Nt),this.timeUnitsTranslationMap=St}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([])):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required])),t||n!==Tt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",dn),dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.latitude-key-name\n \n \n {{ \'tb.rulenode.latitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.longitude-key-name\n \n \n {{ \'tb.rulenode.longitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.perimeter-type\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n \n tb.rulenode.perimeter-key-name\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.circle-center-latitude\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n tb.rulenode.circle-center-longitude\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.range\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n tb.rulenode.range-units\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
    \n \n tb.rulenode.latitude-key-name\n \n \n {{ \'tb.rulenode.latitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.longitude-key-name\n \n \n {{ \'tb.rulenode.longitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.perimeter-type\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n \n tb.rulenode.perimeter-key-name\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.circle-center-latitude\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n tb.rulenode.circle-center-longitude\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.range\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n tb.rulenode.range-units\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class un extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",un),un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:un,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:un,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:un,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",cn),cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",fn),fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",gn),gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",yn),yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",xn),xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xn,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",bn),bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bn,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:a((()=>hn)),multi:!0},{provide:K,useExisting:a((()=>hn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Te.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ie.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:a((()=>hn)),multi:!0},{provide:K,useExisting:a((()=>hn)),multi:!0}],template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],required:[{type:i}]}});class vn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:o,args:["attributeChipList"]}]}});class Ln extends L{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=Wt,this.ArgumentType=Zt,this.attributeScopeMap=pn,this.argumentTypeMap=on,this.arguments=Object.values(Zt),this.attributeScope=Object.values(sn),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===Yt.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===Zt.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==Zt.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(ln[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:a((()=>Ln)),multi:!0},{provide:K,useExisting:a((()=>Ln)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ne.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:Ne.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Se.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Se.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Se.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ie.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:a((()=>Ln)),multi:!0},{provide:K,useExisting:a((()=>Ln)),multi:!0}],template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],function:[{type:i}]}});class Tn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(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=[...Wt.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(qe((e=>{let t;t="string"==typeof e&&Yt[e]?Yt[e]:null,this.updateView(t)})),Ae((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=Wt.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Tn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Ve.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Ve.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Pe.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:a((()=>Tn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:i}],disabled:[{type:i}],operationInput:[{type:o,args:["operationInput",{static:!0}]}]}});class In extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=Yt,this.ArgumentTypeResult=Xt,this.argumentTypeResultMap=an,this.attributeScopeMap=pn,this.argumentsResult=Object.values(Xt),this.attributeScopeResult=Object.values(mn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===Yt.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===Xt.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ln,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:Tn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nn{constructor(){this.textAlign="left"}}e("ExampleHintComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:He.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:i}],popupHelpLink:[{type:i}],textAlign:[{type:i}]}});class Sn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new _e,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ae(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(Be(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>Sn)),multi:!0},{provide:K,useExisting:a((()=>Sn)),multi:!0}],ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Oe([T()],Sn.prototype,"disabled",void 0),Oe([T()],Sn.prototype,"uniqueKeyValuePairValidator",void 0),Oe([T()],Sn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:a((()=>Sn)),multi:!0},{provide:K,useExisting:a((()=>Sn)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class qn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.entityType=F,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>qn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:je.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:$e.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:a((()=>qn)),multi:!0}],template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class An extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>An)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Qe.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:a((()=>An)),multi:!0}],template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Mn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(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=[ge,ye,xe],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(I))this.messageTypesList.push({name:N.get(I[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Me(""),Ae((e=>e||"")),Ee((e=>this.fetchMessageTypes(e))),Ge())}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 Ke(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return Ke(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ve.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Ve.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:Ve.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Pe.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],label:[{type:i}],placeholder:[{type:i}],disabled:[{type:i}],chipList:[{type:o,args:["chipList",{static:!1}]}],matAutocomplete:[{type:o,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:o,args:["messageTypeInput",{static:!1}]}]}});class En extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=zt,this.credentialsTypeTranslationsMap=Ut,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){ie(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:a((()=>En)),multi:!0},{provide:K,useExisting:a((()=>En)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Je.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:Je.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:Je.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:Je.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:Je.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ye.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:a((()=>En)),multi:!0},{provide:K,useExisting:a((()=>En)),multi:!0}],template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],disableCertPemCredentials:[{type:i}],passwordFieldRequired:[{type:i}]}});const Gn=new l("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class Dn{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new _e,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Dn,deps:[{token:t.NgZone},{token:j},{token:Gn,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),Dn.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Dn,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Dn,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:m,args:[j]}]},{type:void 0,decorators:[{type:p},{type:m,args:[Gn]}]}]}});class wn{constructor(e,t,n,o){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=o,this.cbOnSuccess=new r,this.cbOnError=new r,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:wn,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:Dn}],target:t.ɵɵFactoryTarget.Directive}),wn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:wn,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:wn,decorators:[{type:d,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:Dn}]},propDecorators:{targetElm:[{type:i,args:["ngxClipboard"]}],container:[{type:i}],cbContent:[{type:i}],cbSuccessMsg:[{type:i}],cbOnSuccess:[{type:u}],cbOnError:[{type:u}]}});class Vn{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Vn,deps:[{token:Dn},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),Vn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:Vn,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Vn,decorators:[{type:d,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:Dn},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class Pn{}Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Pn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,declarations:[wn,Vn],imports:[$],exports:[wn,Vn]}),Pn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,decorators:[{type:c,args:[{imports:[$],declarations:[wn,Vn],exports:[wn,Vn]}]}]});class Rn{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 _e,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(Be(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(Be(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Rn),Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Rn)),multi:!0},{provide:K,useExisting:a((()=>Rn)),multi:!0}],ngImport:t,template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:wn,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Oe([T()],Rn.prototype,"disabled",void 0),Oe([T()],Rn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:a((()=>Rn)),multi:!0},{provide:K,useExisting:a((()=>Rn)),multi:!0}],template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:i}],disabled:[{type:i}],required:[{type:i}]}});class On{constructor(e,t){this.fb=e,this.translate=t,this.translation=nn,this.propagateChange=()=>{},this.destroy$=new _e,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(De(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",On),On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),On.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:On,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:a((()=>On)),multi:!0}],ngImport:t,template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:a((()=>On)),multi:!0}],template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:i}],translation:[{type:i}]}});class _n extends L{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new _e,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ae(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(De(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)ie(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(De(this.destroy$)).subscribe((t=>{const n=Lt.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>_n)),multi:!0},{provide:K,useExisting:a((()=>_n)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Ie.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Oe([T()],_n.prototype,"disabled",void 0),Oe([T()],_n.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:a((()=>_n)),multi:!0},{provide:K,useExisting:a((()=>_n)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:i}],disabled:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],targetKeyPrefix:[{type:i}],selectText:[{type:i}],selectRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class Bn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Qe.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0}],template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Kn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new _e,this.separatorKeysCodes=[ge,ye,xe],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(De(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||ie(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0},{provide:K,useExisting:Kn,multi:!0}],ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0},{provide:K,useExisting:Kn,multi:!0}],template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:i}]}});class zn extends L{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new _e,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(De(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0}],template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Un{}e("RulenodeCoreConfigCommonModule",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Un.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Un,declarations:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn],imports:[$,M,Re],exports:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn]}),Un.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,imports:[$,M,Re]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:c,args:[{declarations:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn],imports:[$,M,Re],exports:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn]}]}]});class Hn{}e("RuleNodeCoreConfigActionModule",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Hn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Hn,declarations:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In],imports:[$,M,Re,Un],exports:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In]}),Hn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,imports:[$,M,Re,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:c,args:[{declarations:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In],imports:[$,M,Re,Un],exports:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In]}]}]});class jn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]]})}prepareInputConfig(e){return{inputValueKey:ie(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:ie(e?.outputValueKey)?e.outputValueKey:null,useCache:!ie(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!ie(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:ie(e?.periodValueKey)?e.periodValueKey:null,round:ie(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!ie(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative}}prepareOutputConfig(e){return le(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class $n extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.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,le(e)}prepareInputConfig(e){let t,n;return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Qn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return se(e)&&(e.attributesControl={clientAttributeNames:ie(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ie(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ie(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ie(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:ie(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!ie(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Qn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:qn,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Kn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Jn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Mt))this.predefinedValues.push({value:Mt[e],name:this.translate.instant(Et.get(Mt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=ie(e?.addToMetadata)?e.addToMetadata?en.METADATA:en.DATA:e?.fetchTo?e.fetchTo:en.DATA,{detailsList:ie(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Yn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Gt,this.samplingOrders=Object.values(Vt),this.samplingOrdersTranslate=_t,this.timeUnits=Object.values(Nt),this.timeUnitsTranslationMap=St,this.deduplicationStrategiesHintTranslations=wt,this.headerOptions=[],this.timeUnitMap={[Nt.MILLISECONDS]:1,[Nt.SECONDS]:1e3,[Nt.MINUTES]:6e4,[Nt.HOURS]:36e5,[Nt.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 Dt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Dt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,le(e)}prepareInputConfig(e){return se(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:ie(e?.aggregation)?e.aggregation:E.NONE,fetchMode:ie(e?.fetchMode)?e.fetchMode:Gt.FIRST,orderBy:ie(e?.orderBy)?e.orderBy:Vt.ASC,limit:ie(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!ie(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:ie(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:ie(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Nt.MINUTES,endInterval:ie(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:ie(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Nt.MINUTES},startIntervalPattern:ie(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:ie(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Gt.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Gt.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:He.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Wn extends f{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 se(e)&&(e.attributesControl={clientAttributeNames:ie(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ie(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ie(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ie(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA,tellFailureIfAbsent:!!ie(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:ie(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Kn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Zn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of kt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return le(e)}prepareInputConfig(e){return{dataMapping:ie(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:ie(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:_n,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Xn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=Pt,this.msgMetadataLabelTranslations=Ot,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(kt))this.originatorFields.push({value:kt[e].value,name:this.translate.instant(kt[e].name)});for(const e of Rt.keys())this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===Pt.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,le(e)}prepareInputConfig(e){let t,n,r={[k.name.value]:`relatedEntity${this.translate.instant(k.name.name)}`},o={serialNumber:"sn"};return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,t===Pt.FIELDS?r=n:o=n,{relationsQuery:ie(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:An,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:_n,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class er extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class tr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class nr{}e("RulenodeCoreConfigEnrichmentModule",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),nr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:nr,declarations:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr],imports:[$,M,Un],exports:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr]}),nr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:c,args:[{declarations:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr],imports:[$,M,Un],exports:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr]}]}]});class rr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Ht,this.azureIotHubCredentialsTypeTranslationsMap=jt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Je.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:Je.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:Je.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:Je.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:Je.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ye.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class or extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=Qt,this.ToByteStandartCharsetTypeTranslationMap=Jt}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ar extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&me(e.clientId))},[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){me(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:En,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ir extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=D,this.entityType=F}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ir,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
    \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ye.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys($t)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],useRedisQueueForMsgPersistence:[!!e&&e.useRedisQueueForMsgPersistence,[]],trimQueue:[!!e&&e.trimQueue,[]],maxQueueSize:[e?e.maxQueueSize:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","useRedisQueueForMsgPersistence","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("useRedisQueueForMsgPersistence").value,r=this.restApiCallConfigForm.get("enableProxy").value,o=this.restApiCallConfigForm.get("useSystemProxyProperties").value;r&&!o?(this.restApiCallConfigForm.get("proxyHost").setValidators(r?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(r?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),n?this.restApiCallConfigForm.get("maxQueueSize").setValidators([O.min(0)]):this.restApiCallConfigForm.get("maxQueueSize").setValidators([]),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("maxQueueSize").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:En,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class dr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(w),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Bt,this.sqsQueueTypes=Object.keys(Bt),this.sqsQueueTypeTranslationsMap=Kt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr{}e("RulenodeCoreConfigExternalModule",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),gr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:gr,declarations:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur],imports:[$,M,Re,Un],exports:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur]}),gr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,imports:[$,M,Re,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:c,args:[{declarations:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur],imports:[$,M,Re,Un],exports:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur]}]}]});class yr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ie(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:zn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class xr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ie(e?.messageNames)?e.messageNames:[],metadataNames:ie(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!ie(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:ie(e?.messageNames)?e.messageNames:[],metadataNames:ie(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class br extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=C}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ie(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ie(e?.direction)?e.direction:null,entityType:ie(e?.entityType)?e.entityType:null,entityId:ie(e?.entityId)?e.entityId:null,relationType:ie(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:$e.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.values(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.values(qt),this.rangeUnitTranslationMap=At,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ie(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ie(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ie(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ie(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ie(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ie(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ie(e?.centerLongitude)?e.centerLongitude:null,range:ie(e?.range)?e.range:null,rangeUnit:ie(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ie(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class vr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ie(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Mn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.TENANT,F.CUSTOMER,F.USER,F.DASHBOARD,F.RULE_CHAIN,F.RULE_NODE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ie(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ie(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ie(e?.jsScript)?e.jsScript:null,tbelScript:ie(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class kr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ie(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ie(e?.jsScript)?e.jsScript:null,tbelScript:ie(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Lr{}e("RuleNodeCoreConfigFilterModule",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Lr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Lr,declarations:[xr,br,hr,vr,Cr,Fr,kr,yr],imports:[$,M,Un],exports:[xr,br,hr,vr,Cr,Fr,kr,yr]}),Lr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:c,args:[{declarations:[xr,br,hr,vr,Cr,Fr,kr,yr],imports:[$,M,Un],exports:[xr,br,hr,vr,Cr,Fr,kr,yr]}]}]});class Tr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=vt,this.originatorSources=Object.keys(vt),this.originatorSourceTranslationMap=Ct,this.originatorSourceDescTranslationMap=Ft,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.USER,F.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===vt.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===vt.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Ne.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Ne.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Ir extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.FormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - const Nr=mt({passive:!0});class Sr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return ze;const t=ke(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new _e,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Nr),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Nr)}}),r}stopMonitoring(e){const t=ke(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Sr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Sr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Sr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Sr,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class qr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new r}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:qr,deps:[{token:t.ElementRef},{token:Sr}],target:t.ɵɵFactoryTarget.Directive}),qr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:qr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:qr,decorators:[{type:d,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Sr}]},propDecorators:{cdkAutofill:[{type:u}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Ar{get minRows(){return this._minRows}set minRows(e){this._minRows=Le(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=Le(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Fe(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new _e,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();Ue(e,"resize").pipe(we(16),De(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Ar,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Ar.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Ar,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Ar,decorators:[{type:d,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:p},{type:m,args:[j]}]}]},propDecorators:{minRows:[{type:i,args:["cdkAutosizeMinRows"]}],maxRows:[{type:i,args:["cdkAutosizeMaxRows"]}],enabled:[{type:i,args:["cdkTextareaAutosize"]}],placeholder:[{type:i}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Mr{}Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Mr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,declarations:[qr,Ar],exports:[qr,Ar]}),Mr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,decorators:[{type:c,args:[{declarations:[qr,Ar],exports:[qr,Ar]}]}]});class Er extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:ie(e?.fromTemplate)?e.fromTemplate:null,toTemplate:ie(e?.toTemplate)?e.toTemplate:null,ccTemplate:ie(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:ie(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:ie(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:ie(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:ie(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:ie(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Er),Er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Er,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:He.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Ar,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Ne.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Ne.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Gr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=tn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.copyFrom?en.METADATA:en.DATA:ie(e?.copyFrom)?e.copyFrom:en.DATA,{keys:ie(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Gr),Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Dr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=rn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ie(e?.renameIn)?e?.renameIn:en.DATA,{renameKeysMapping:ie(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Dr),Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dr,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dr,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class wr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",wr),wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),wr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wr,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Vr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=nn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ie(e?.deleteFrom)?e?.deleteFrom:en.DATA,{keys:ie(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Vr),Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vr,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Gt,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Dt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[ie(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[ie(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[ie(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[ie(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[ie(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Je.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:Je.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:Je.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Rn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Rr{}e("RulenodeCoreConfigTransformModule",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Rr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Rr,declarations:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr],imports:[$,M,Un],exports:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr]}),Rr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:c,args:[{declarations:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr],imports:[$,M,Un],exports:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr]}]}]});class Or extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=F}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class _r extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Br{}e("RuleNodeCoreConfigFlowModule",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Br,declarations:[Or,_r],imports:[$,M,Un],exports:[Or,_r]}),Br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:c,args:[{declarations:[Or,_r],imports:[$,M,Un],exports:[Or,_r]}]}]});class Kr{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 not exists","create-entity-if-not-exists-hint":"Create a new entity set above if it does not exist.","entity-name-pattern":"Name pattern","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 name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","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","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":"Timeseries keys","timeseries-keys-required":"At least one timeseries key should be selected.","add-timeseries-key":"Add timeseries key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-to-specific-entity":"Delete relation to specific entity","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"use-redis-queue":"Use redis queue for message persistence","ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","trim-redis-queue":"Trim redis queue","redis-queue-max-size":"Redis queue max size","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.","persist-alarm-rules":"Persist state of alarm rules","fetch-alarm-rules":"Fetch state of alarm rules","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","use-server-ts":"Use server ts","use-server-ts-hint":"Enable this setting to use the timestamp of the 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.","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.","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":"timeseries 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 timeseries from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch timeseries 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 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."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),Kr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Kr,declarations:[dt],imports:[$,M],exports:[Hn,Lr,nr,gr,Rr,Br,dt]}),Kr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,imports:[$,M,Hn,Lr,nr,gr,Rr,Br]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:c,args:[{declarations:[dt],imports:[$,M],exports:[Hn,Lr,nr,gr,Rr,Br,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map +System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/checkbox","@angular/material/input","@angular/material/form-field","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/select","@angular/material/core","@angular/material/slide-toggle","@shared/components/hint-tooltip-icon.component","@core/public-api","@shared/components/js-func.component","@angular/material/button","@angular/material/icon","@angular/material/tooltip","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/chips","@shared/pipe/safe.pipe","@shared/components/entity/entity-type-select.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","rxjs","@shared/components/help-popup.component","@shared/components/entity/entity-subtype-list.component","@shared/components/relation/relation-type-autocomplete.component","@home/components/relation/relation-filters.component","@angular/material/expansion","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,f,g,y,x,b,h,v,C,F,k,L,T,I,N,S,q,A,M,E,G,D,w,V,P,R,O,_,B,K,z,U,H,j,$,Q,J,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,fe,ge,ye,xe,be,he,ve,Ce,Fe,ke,Le,Te,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,De,we,Ve,Pe,Re,Oe,_e,Be,Ke,ze,Ue,He,je,$e,Qe,Je,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.EventEmitter,o=e.ViewChild,a=e.forwardRef,i=e.Input,l=e.InjectionToken,s=e.Injectable,m=e.Inject,p=e.Optional,d=e.Directive,u=e.Output,c=e.NgModule},function(e){f=e.RuleNodeConfigurationComponent,g=e.AttributeScope,y=e.telemetryTypeTranslations,x=e.ScriptLanguage,b=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.entitySearchDirectionTranslations,F=e.EntityType,k=e.entityFields,L=e.PageComponent,T=e.coerceBoolean,I=e.MessageType,N=e.messageTypeNames,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,D=e.NotificationType,w=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,U=e.FormGroup},function(e){H=e,j=e.DOCUMENT,$=e.CommonModule},function(e){Q=e},function(e){J=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e.getCurrentAuthState,oe=e,ae=e.isEqual,ie=e.isDefinedAndNotNull,le=e.deepTrim,se=e.isObject,me=e.isNotEmptyStr},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e},function(e){fe=e},function(e){ge=e.ENTER,ye=e.COMMA,xe=e.SEMICOLON},function(e){be=e},function(e){he=e},function(e){ve=e},function(e){Ce=e},function(e){Fe=e},function(e){ke=e},function(e){Le=e.coerceBooleanProperty,Te=e.coerceElement,Ie=e.coerceNumberProperty},function(e){Ne=e},function(e){Se=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e.tap,Ee=e.map,Ge=e.startWith,De=e.mergeMap,we=e.share,Ve=e.takeUntil,Pe=e.auditTime},function(e){Re=e},function(e){Oe=e},function(e){_e=e.HomeComponentsModule},function(e){Be=e.__decorate},function(e){Ke=e.Subject,ze=e.takeUntil,Ue=e.of,He=e.EMPTY,je=e.fromEvent},function(e){$e=e},function(e){Qe=e},function(e){Je=e},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
    ",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
    "}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ct extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===g.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ct),ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ct,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ft extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===x.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===x.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",ft),ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ft,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gt extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.alarmSeverities=Object.keys(b),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[ge,ye,xe],this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==x.TBEL||this.tbelEnabled||(r=x.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===x.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===x.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",gt),gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),gt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gt,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class yt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["entityType"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==F.DEVICE&&t!==F.ASSET?this.createRelationConfigForm.get("entityTypePattern").setValidators([]):this.createRelationConfigForm.get("entityTypePattern").setValidators([O.required,O.pattern(/.*\S.*/)]),this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",yt),yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yt,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bt extends f{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,O.required],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart,O.required]})}}e("DeviceProfileConfigComponent",bt),bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n',dependencies:[{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ht extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}var vt;e("GeneratorConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(vt||(vt={}));const Ct=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer"],[vt.TENANT,"tb.rulenode.originator-tenant"],[vt.RELATED,"tb.rulenode.originator-related"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[vt.ENTITY,"tb.rulenode.originator-entity"]]),Ft=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer-desc"],[vt.TENANT,"tb.rulenode.originator-tenant-desc"],[vt.RELATED,"tb.rulenode.originator-related-entity-desc"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[vt.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),kt=[k.createdTime,k.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},k.firstName,k.lastName,k.email,k.title,k.country,k.state,k.city,k.address,k.address2,k.zip,k.phone,k.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],Lt=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 Tt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Tt||(Tt={}));const It=new Map([[Tt.CIRCLE,"tb.rulenode.perimeter-circle"],[Tt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Nt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Nt||(Nt={}));const St=new Map([[Nt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Nt.SECONDS,"tb.rulenode.time-unit-seconds"],[Nt.MINUTES,"tb.rulenode.time-unit-minutes"],[Nt.HOURS,"tb.rulenode.time-unit-hours"],[Nt.DAYS,"tb.rulenode.time-unit-days"]]);var qt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(qt||(qt={}));const At=new Map([[qt.METER,"tb.rulenode.range-unit-meter"],[qt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[qt.FOOT,"tb.rulenode.range-unit-foot"],[qt.MILE,"tb.rulenode.range-unit-mile"],[qt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Mt;!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"}(Mt||(Mt={}));const Et=new Map([[Mt.ID,"tb.rulenode.entity-details-id"],[Mt.TITLE,"tb.rulenode.entity-details-title"],[Mt.COUNTRY,"tb.rulenode.entity-details-country"],[Mt.STATE,"tb.rulenode.entity-details-state"],[Mt.CITY,"tb.rulenode.entity-details-city"],[Mt.ZIP,"tb.rulenode.entity-details-zip"],[Mt.ADDRESS,"tb.rulenode.entity-details-address"],[Mt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Mt.PHONE,"tb.rulenode.entity-details-phone"],[Mt.EMAIL,"tb.rulenode.entity-details-email"],[Mt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Gt;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Gt||(Gt={}));const Dt=new Map([[Gt.FIRST,"tb.rulenode.first"],[Gt.LAST,"tb.rulenode.last"],[Gt.ALL,"tb.rulenode.all"]]),wt=new Map([[Gt.FIRST,"tb.rulenode.first-mode-hint"],[Gt.LAST,"tb.rulenode.last-mode-hint"],[Gt.ALL,"tb.rulenode.all-mode-hint"]]);var Vt,Pt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Vt||(Vt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(Pt||(Pt={}));const Rt=new Map([[Pt.ATTRIBUTES,"tb.rulenode.attributes"],[Pt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[Pt.FIELDS,"tb.rulenode.fields"]]),Ot=new Map([[Pt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[Pt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[Pt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),_t=new Map([[Vt.ASC,"tb.rulenode.ascending"],[Vt.DESC,"tb.rulenode.descending"]]);var Bt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Bt||(Bt={}));const Kt=new Map([[Bt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Bt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),zt=["anonymous","basic","cert.PEM"],Ut=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Ht=["sas","cert.PEM"],jt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var $t;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}($t||($t={}));const Qt=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],Jt=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 Yt;!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"}(Yt||(Yt={}));const Wt=new Map([[Yt.CUSTOM,{value:Yt.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[Yt.ADD,{value:Yt.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[Yt.SUB,{value:Yt.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[Yt.MULT,{value:Yt.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[Yt.DIV,{value:Yt.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[Yt.SIN,{value:Yt.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.SINH,{value:Yt.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[Yt.COS,{value:Yt.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.COSH,{value:Yt.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[Yt.TAN,{value:Yt.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[Yt.TANH,{value:Yt.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ACOS,{value:Yt.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[Yt.ASIN,{value:Yt.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN,{value:Yt.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN2,{value:Yt.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}],[Yt.EXP,{value:Yt.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[Yt.EXPM1,{value:Yt.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[Yt.SQRT,{value:Yt.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[Yt.CBRT,{value:Yt.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[Yt.GET_EXP,{value:Yt.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[Yt.HYPOT,{value:Yt.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[Yt.LOG,{value:Yt.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG10,{value:Yt.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG1P,{value:Yt.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[Yt.CEIL,{value:Yt.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR,{value:Yt.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR_DIV,{value:Yt.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[Yt.FLOOR_MOD,{value:Yt.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[Yt.ABS,{value:Yt.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[Yt.MIN,{value:Yt.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[Yt.MAX,{value:Yt.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[Yt.POW,{value:Yt.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}],[Yt.SIGNUM,{value:Yt.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[Yt.RAD,{value:Yt.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[Yt.DEG,{value:Yt.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var Zt,Xt,en;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(Zt||(Zt={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(Xt||(Xt={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(en||(en={}));const tn=new Map([[en.DATA,"tb.rulenode.message-to-metadata"],[en.METADATA,"tb.rulenode.metadata-to-message"]]),nn=(new Map([[en.DATA,"tb.rulenode.from-message"],[en.METADATA,"tb.rulenode.from-metadata"]]),new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.metadata"]])),rn=new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.message-metadata"]]),on=new Map([[Zt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[Zt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[Zt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[Zt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[Zt.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),an=new Map([[Xt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[Xt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[Xt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[Xt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),ln=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var sn,mn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(sn||(sn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(mn||(mn={}));const pn=new Map([[sn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[sn.SERVER_SCOPE,"tb.rulenode.server-scope"],[sn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var dn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(dn||(dn={}));const un=new Map([[dn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[dn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.keys(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.keys(qt),this.rangeUnitTranslationMap=At,this.presenceMonitoringStrategies=un,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Nt),this.timeUnitsTranslationMap=St,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[O.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",cn),cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n
    \n
    \n
    {{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
    \n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
    \n
    {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
    \n
    \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n
    \n
    \n
    {{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
    \n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
    \n
    {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
    \n
    \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fn extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",fn),fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",gn),gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",yn),yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",xn),xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",bn),bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:a((()=>Cn)),multi:!0},{provide:K,useExisting:a((()=>Cn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Se.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:a((()=>Cn)),multi:!0},{provide:K,useExisting:a((()=>Cn)),multi:!0}],template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],required:[{type:i}]}});class Fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ln extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:o,args:["attributeChipList"]}]}});class In extends L{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=Wt,this.ArgumentType=Zt,this.attributeScopeMap=pn,this.argumentTypeMap=on,this.arguments=Object.values(Zt),this.attributeScope=Object.values(sn),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===Yt.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===Zt.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==Zt.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(ln[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:a((()=>In)),multi:!0},{provide:K,useExisting:a((()=>In)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:qe.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:qe.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Ae.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Ae.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Ae.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Se.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:a((()=>In)),multi:!0},{provide:K,useExisting:a((()=>In)),multi:!0}],template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],function:[{type:i}]}});class Nn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(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=[...Wt.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(Me((e=>{let t;t="string"==typeof e&&Yt[e]?Yt[e]:null,this.updateView(t)})),Ee((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=Wt.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Nn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Re.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Re.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Oe.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:a((()=>Nn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:i}],disabled:[{type:i}],operationInput:[{type:o,args:["operationInput",{static:!0}]}]}});class Sn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=Yt,this.ArgumentTypeResult=Xt,this.argumentTypeResultMap=an,this.attributeScopeMap=pn,this.argumentsResult=Object.values(Xt),this.attributeScopeResult=Object.values(mn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===Yt.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===Xt.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:In,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:Nn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class qn{constructor(){this.textAlign="left"}}e("ExampleHintComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:i}],popupHelpLink:[{type:i}],textAlign:[{type:i}]}});class An{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new Ke,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ae(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(ze(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>An)),multi:!0},{provide:K,useExisting:a((()=>An)),multi:!0}],ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:qn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([T()],An.prototype,"disabled",void 0),Be([T()],An.prototype,"uniqueKeyValuePairValidator",void 0),Be([T()],An.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:a((()=>An)),multi:!0},{provide:K,useExisting:a((()=>An)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class Mn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.entityType=F,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Qe.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:Je.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0}],template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class En extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>En)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Ye.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:a((()=>En)),multi:!0}],template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Gn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(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=[ge,ye,xe],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(I))this.messageTypesList.push({name:N.get(I[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Ge(""),Ee((e=>e||"")),De((e=>this.fetchMessageTypes(e))),we())}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 Ue(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return Ue(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Gn)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Re.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Re.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:Re.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Oe.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:a((()=>Gn)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],label:[{type:i}],placeholder:[{type:i}],disabled:[{type:i}],chipList:[{type:o,args:["chipList",{static:!1}]}],matAutocomplete:[{type:o,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:o,args:["messageTypeInput",{static:!1}]}]}});class Dn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=zt,this.credentialsTypeTranslationsMap=Ut,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){ie(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:a((()=>Dn)),multi:!0},{provide:K,useExisting:a((()=>Dn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:We.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:We.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:a((()=>Dn)),multi:!0},{provide:K,useExisting:a((()=>Dn)),multi:!0}],template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],disableCertPemCredentials:[{type:i}],passwordFieldRequired:[{type:i}]}});const wn=new l("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class Vn{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new Ke,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Vn,deps:[{token:t.NgZone},{token:j},{token:wn,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),Vn.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Vn,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Vn,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:m,args:[j]}]},{type:void 0,decorators:[{type:p},{type:m,args:[wn]}]}]}});class Pn{constructor(e,t,n,o){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=o,this.cbOnSuccess=new r,this.cbOnError=new r,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:Vn}],target:t.ɵɵFactoryTarget.Directive}),Pn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:Pn,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,decorators:[{type:d,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:Vn}]},propDecorators:{targetElm:[{type:i,args:["ngxClipboard"]}],container:[{type:i}],cbContent:[{type:i}],cbSuccessMsg:[{type:i}],cbOnSuccess:[{type:u}],cbOnError:[{type:u}]}});class Rn{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Rn,deps:[{token:Vn},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),Rn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:Rn,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Rn,decorators:[{type:d,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:Vn},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class On{}On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,deps:[],target:t.ɵɵFactoryTarget.NgModule}),On.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,declarations:[Pn,Rn],imports:[$],exports:[Pn,Rn]}),On.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,decorators:[{type:c,args:[{imports:[$],declarations:[Pn,Rn],exports:[Pn,Rn]}]}]});class _n{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 Ke,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(ze(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(ze(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>_n)),multi:!0},{provide:K,useExisting:a((()=>_n)),multi:!0}],ngImport:t,template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Pn,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([T()],_n.prototype,"disabled",void 0),Be([T()],_n.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:a((()=>_n)),multi:!0},{provide:K,useExisting:a((()=>_n)),multi:!0}],template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:i}],disabled:[{type:i}],required:[{type:i}]}});class Bn{constructor(e,t){this.fb=e,this.translate=t,this.translation=nn,this.propagateChange=()=>{},this.destroy$=new Ke,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0}],ngImport:t,template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0}],template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:i}],translation:[{type:i}]}});class Kn extends L{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new Ke,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ae(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(Ve(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)ie(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(Ve(this.destroy$)).subscribe((t=>{const n=Lt.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0},{provide:K,useExisting:a((()=>Kn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Se.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:qn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([T()],Kn.prototype,"disabled",void 0),Be([T()],Kn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0},{provide:K,useExisting:a((()=>Kn)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:i}],disabled:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],targetKeyPrefix:[{type:i}],selectText:[{type:i}],selectRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class zn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>zn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ye.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0}],template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Un{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new Ke,this.separatorKeysCodes=[ge,ye,xe],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||ie(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:a((()=>Un)),multi:!0},{provide:K,useExisting:Un,multi:!0}],ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:qn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:a((()=>Un)),multi:!0},{provide:K,useExisting:Un,multi:!0}],template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:i}]}});class Hn extends L{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new Ke,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>Hn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>Hn)),multi:!0}],template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class jn{}e("RulenodeCoreConfigCommonModule",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),jn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:jn,declarations:[An,Mn,En,Gn,Dn,In,Nn,_n,Cn,Bn,Kn,zn,Un,Hn,qn],imports:[$,M,_e],exports:[An,Mn,En,Gn,Dn,In,Nn,_n,Cn,Bn,Kn,zn,Un,Hn,qn]}),jn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,imports:[$,M,_e]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:c,args:[{declarations:[An,Mn,En,Gn,Dn,In,Nn,_n,Cn,Bn,Kn,zn,Un,Hn,qn],imports:[$,M,_e],exports:[An,Mn,En,Gn,Dn,In,Nn,_n,Cn,Bn,Kn,zn,Un,Hn,qn]}]}]});class $n{}e("RuleNodeCoreConfigActionModule",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[],target:t.ɵɵFactoryTarget.NgModule}),$n.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$n,declarations:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn],imports:[$,M,_e,jn],exports:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn]}),$n.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,imports:[$,M,_e,jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:c,args:[{declarations:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn],imports:[$,M,_e,jn],exports:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn]}]}]});class Qn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]]})}prepareInputConfig(e){return{inputValueKey:ie(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:ie(e?.outputValueKey)?e.outputValueKey:null,useCache:!ie(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!ie(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:ie(e?.periodValueKey)?e.periodValueKey:null,round:ie(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!ie(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative}}prepareOutputConfig(e){return le(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Qn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Jn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.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,le(e)}prepareInputConfig(e){let t,n;return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:An,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Yn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return se(e)&&(e.attributesControl={clientAttributeNames:ie(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ie(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ie(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ie(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:ie(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!ie(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Mn,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Un,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Wn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Mt))this.predefinedValues.push({value:Mt[e],name:this.translate.instant(Et.get(Mt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=ie(e?.addToMetadata)?e.addToMetadata?en.METADATA:en.DATA:e?.fetchTo?e.fetchTo:en.DATA,{detailsList:ie(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Zn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Gt,this.samplingOrders=Object.values(Vt),this.samplingOrdersTranslate=_t,this.timeUnits=Object.values(Nt),this.timeUnitsTranslationMap=St,this.deduplicationStrategiesHintTranslations=wt,this.headerOptions=[],this.timeUnitMap={[Nt.MILLISECONDS]:1,[Nt.SECONDS]:1e3,[Nt.MINUTES]:6e4,[Nt.HOURS]:36e5,[Nt.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 Dt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Dt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,le(e)}prepareInputConfig(e){return se(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:ie(e?.aggregation)?e.aggregation:E.NONE,fetchMode:ie(e?.fetchMode)?e.fetchMode:Gt.FIRST,orderBy:ie(e?.orderBy)?e.orderBy:Vt.ASC,limit:ie(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!ie(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:ie(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:ie(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Nt.MINUTES,endInterval:ie(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:ie(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Nt.MINUTES},startIntervalPattern:ie(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:ie(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Gt.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Gt.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:qn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Xn extends f{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 se(e)&&(e.attributesControl={clientAttributeNames:ie(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ie(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ie(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ie(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA,tellFailureIfAbsent:!!ie(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:ie(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Un,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class er extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of kt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return le(e)}prepareInputConfig(e){return{dataMapping:ie(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:ie(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Kn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class tr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=Pt,this.msgMetadataLabelTranslations=Ot,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(kt))this.originatorFields.push({value:kt[e].value,name:this.translate.instant(kt[e].name)});for(const e of Rt.keys())this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===Pt.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,le(e)}prepareInputConfig(e){let t,n,r={[k.name.value]:`relatedEntity${this.translate.instant(k.name.name)}`},o={serialNumber:"sn"};return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,t===Pt.FIELDS?r=n:o=n,{relationsQuery:ie(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:An,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:En,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Kn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class nr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:An,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class rr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class or{}e("RulenodeCoreConfigEnrichmentModule",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[],target:t.ɵɵFactoryTarget.NgModule}),or.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:or,declarations:[Jn,Wn,Yn,Xn,er,Zn,tr,nr,Qn,rr],imports:[$,M,jn],exports:[Jn,Wn,Yn,Xn,er,Zn,tr,nr,Qn,rr]}),or.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,imports:[$,M,jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:c,args:[{declarations:[Jn,Wn,Yn,Xn,er,Zn,tr,nr,Qn,rr],imports:[$,M,jn],exports:[Jn,Wn,Yn,Xn,er,Zn,tr,nr,Qn,rr]}]}]});class ar extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Ht,this.azureIotHubCredentialsTypeTranslationsMap=jt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:We.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:We.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ir extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=Qt,this.ToByteStandartCharsetTypeTranslationMap=Jt}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ir,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&me(e.clientId))},[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){me(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Dn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=D,this.entityType=F}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
    \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class mr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class dr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys($t)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],useRedisQueueForMsgPersistence:[!!e&&e.useRedisQueueForMsgPersistence,[]],trimQueue:[!!e&&e.trimQueue,[]],maxQueueSize:[e?e.maxQueueSize:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","useRedisQueueForMsgPersistence","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("useRedisQueueForMsgPersistence").value,r=this.restApiCallConfigForm.get("enableProxy").value,o=this.restApiCallConfigForm.get("useSystemProxyProperties").value;r&&!o?(this.restApiCallConfigForm.get("proxyHost").setValidators(r?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(r?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),n?this.restApiCallConfigForm.get("maxQueueSize").setValidators([O.min(0)]):this.restApiCallConfigForm.get("maxQueueSize").setValidators([]),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("maxQueueSize").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Dn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(w),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class gr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Bt,this.sqsQueueTypes=Object.keys(Bt),this.sqsQueueTypeTranslationsMap=Kt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xr{}e("RulenodeCoreConfigExternalModule",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),xr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:xr,declarations:[gr,yr,mr,ir,lr,sr,pr,dr,ur,ar,cr,fr],imports:[$,M,_e,jn],exports:[gr,yr,mr,ir,lr,sr,pr,dr,ur,ar,cr,fr]}),xr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,imports:[$,M,_e,jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:c,args:[{declarations:[gr,yr,mr,ir,lr,sr,pr,dr,ur,ar,cr,fr],imports:[$,M,_e,jn],exports:[gr,yr,mr,ir,lr,sr,pr,dr,ur,ar,cr,fr]}]}]});class br extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ie(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Hn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class hr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ie(e?.messageNames)?e.messageNames:[],metadataNames:ie(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!ie(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:ie(e?.messageNames)?e.messageNames:[],metadataNames:ie(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class vr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=C}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ie(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ie(e?.direction)?e.direction:null,entityType:ie(e?.entityType)?e.entityType:null,entityId:ie(e?.entityId)?e.entityId:null,relationType:ie(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Je.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.values(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.values(qt),this.rangeUnitTranslationMap=At,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ie(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ie(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ie(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ie(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ie(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ie(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ie(e?.centerLongitude)?e.centerLongitude:null,range:ie(e?.range)?e.range:null,rangeUnit:ie(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ie(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ie(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Gn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.TENANT,F.CUSTOMER,F.USER,F.DASHBOARD,F.RULE_CHAIN,F.RULE_NODE,F.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ie(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Lr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ie(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ie(e?.jsScript)?e.jsScript:null,tbelScript:ie(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Tr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ie(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ie(e?.jsScript)?e.jsScript:null,tbelScript:ie(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Ir{}e("RuleNodeCoreConfigFilterModule",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Ir.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Ir,declarations:[hr,vr,Cr,Fr,kr,Lr,Tr,br],imports:[$,M,jn],exports:[hr,vr,Cr,Fr,kr,Lr,Tr,br]}),Ir.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,imports:[$,M,jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:c,args:[{declarations:[hr,vr,Cr,Fr,kr,Lr,Tr,br],imports:[$,M,jn],exports:[hr,vr,Cr,Fr,kr,Lr,Tr,br]}]}]});class Nr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=vt,this.originatorSources=Object.keys(vt),this.originatorSourceTranslationMap=Ct,this.originatorSourceDescTranslationMap=Ft,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.USER,F.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===vt.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===vt.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:qe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:qe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:En,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:qn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Sr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:P.Store},{token:R.FormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + const qr=mt({passive:!0});class Ar{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return He;const t=Te(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new Ke,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,qr),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,qr)}}),r}stopMonitoring(e){const t=Te(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Ar,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Ar.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Ar,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Ar,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class Mr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new r}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,deps:[{token:t.ElementRef},{token:Ar}],target:t.ɵɵFactoryTarget.Directive}),Mr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Mr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,decorators:[{type:d,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Ar}]},propDecorators:{cdkAutofill:[{type:u}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Er{get minRows(){return this._minRows}set minRows(e){this._minRows=Ie(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=Ie(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Le(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new Ke,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();je(e,"resize").pipe(Pe(16),Ve(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Er,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Er.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Er,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Er,decorators:[{type:d,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:p},{type:m,args:[j]}]}]},propDecorators:{minRows:[{type:i,args:["cdkAutosizeMinRows"]}],maxRows:[{type:i,args:["cdkAutosizeMaxRows"]}],enabled:[{type:i,args:["cdkTextareaAutosize"]}],placeholder:[{type:i}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Gr{}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Gr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,declarations:[Mr,Er],exports:[Mr,Er]}),Gr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:c,args:[{declarations:[Mr,Er],exports:[Mr,Er]}]}]});class Dr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:ie(e?.fromTemplate)?e.fromTemplate:null,toTemplate:ie(e?.toTemplate)?e.toTemplate:null,ccTemplate:ie(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:ie(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:ie(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:ie(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:ie(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:ie(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Dr),Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Er,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:qe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:qe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:qn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class wr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=tn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.copyFrom?en.METADATA:en.DATA:ie(e?.copyFrom)?e.copyFrom:en.DATA,{keys:ie(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",wr),wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),wr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Vr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=rn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ie(e?.renameIn)?e?.renameIn:en.DATA,{renameKeysMapping:ie(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Vr),Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vr,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:An,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Rr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=nn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ie(e?.deleteFrom)?e?.deleteFrom:en.DATA,{keys:ie(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Bn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Or extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Gt,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Dt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[ie(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[ie(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[ie(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[ie(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[ie(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:_n,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:qn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class _r{}e("RulenodeCoreConfigTransformModule",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[],target:t.ɵɵFactoryTarget.NgModule}),_r.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:_r,declarations:[Nr,Sr,Dr,wr,Vr,Pr,Rr,Or],imports:[$,M,jn],exports:[Nr,Sr,Dr,wr,Vr,Pr,Rr,Or]}),_r.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,imports:[$,M,jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:c,args:[{declarations:[Nr,Sr,Dr,wr,Vr,Pr,Rr,Or],imports:[$,M,jn],exports:[Nr,Sr,Dr,wr,Vr,Pr,Rr,Or]}]}]});class Br extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=F}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Br,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Kr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class zr{}e("RuleNodeCoreConfigFlowModule",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),zr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:zr,declarations:[Br,Kr],imports:[$,M,jn],exports:[Br,Kr]}),zr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,imports:[$,M,jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:c,args:[{declarations:[Br,Kr],imports:[$,M,jn],exports:[Br,Kr]}]}]});class Ur{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 not exists","create-entity-if-not-exists-hint":"Create a new entity set above if it does not exist.","entity-name-pattern":"Name pattern","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 name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","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","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":"Timeseries keys","timeseries-keys-required":"At least one timeseries key should be selected.","add-timeseries-key":"Add timeseries key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-to-specific-entity":"Delete relation to specific entity","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"use-redis-queue":"Use redis queue for message persistence","ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","trim-redis-queue":"Trim redis queue","redis-queue-max-size":"Redis queue max size","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.","persist-alarm-rules":"Persist state of alarm rules","fetch-alarm-rules":"Fetch state of alarm rules","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","use-server-ts":"Use server ts","use-server-ts-hint":"Enable this setting to use the timestamp of the 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.","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":"timeseries 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 timeseries from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch timeseries 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 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."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),Ur.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Ur,declarations:[dt],imports:[$,M],exports:[$n,Ir,or,xr,_r,zr,dt]}),Ur.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,imports:[$,M,$n,Ir,or,xr,_r,zr]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:c,args:[{declarations:[dt],imports:[$,M],exports:[$n,Ir,or,xr,_r,zr,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map From e55d14325a7658193eca00115c7f918098a8406c Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 15 Feb 2024 17:09:32 +0200 Subject: [PATCH 240/397] Refactor rate limiting to be configurable and use existing class --- .../server/actors/ActorSystemContext.java | 4 + .../actors/ruleChain/DefaultTbContext.java | 5 + .../src/main/resources/thingsboard.yml | 9 ++ .../rule/engine/api/TbContext.java | 2 + .../rule/engine/action/TbDeviceStateNode.java | 91 +++++--------- .../engine/action/TbDeviceStateNodeTest.java | 114 +++++------------- 6 files changed, 80 insertions(+), 145 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index 6082c3f9f0..2a4f132be8 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -561,6 +561,10 @@ public class ActorSystemContext { @Getter private boolean externalNodeForceAck; + @Value("${state.rule.node.deviceState.rateLimit:1:1,30:60,60:3600}") + @Getter + private String deviceStateNodeRateLimitConfig; + @Getter @Setter private TbActorSystem actorSystem; diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java index b97201005c..9110ab794d 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java @@ -689,6 +689,11 @@ class DefaultTbContext implements TbContext { return mainCtx.getDeviceStateManager(); } + @Override + public String getDeviceStateNodeRateLimitConfig() { + return mainCtx.getDeviceStateNodeRateLimitConfig(); + } + @Override public TbClusterService getClusterService() { return mainCtx.getClusterService(); diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 82a347d41c..5b22a3b7be 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -794,6 +794,15 @@ state: # Used only when state.persistToTelemetry is set to 'true' and Cassandra is used for timeseries data. # 0 means time-to-live mechanism is disabled. telemetryTtl: "${STATE_TELEMETRY_TTL:0}" + # Configuration properties for rule nodes related to device activity state + rule: + node: + # Device state rule node + deviceState: + # Defines the rate at which device connectivity events can be triggered. + # Comma-separated list of capacity:duration pairs that define bandwidth capacity and refill duration for token bucket rate limit algorithm. + # Refill is set to be greedy. Please refer to Bucket4j library documentation for more details. + rateLimit: "${DEVICE_STATE_NODE_RATE_LIMIT_CONFIGURATION:1:1,30:60,60:3600}" # Tbel parameters tbel: diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java index 32fb81ccd9..fc2980650b 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java @@ -282,6 +282,8 @@ public interface TbContext { RuleEngineDeviceStateManager getDeviceStateManager(); + String getDeviceStateNodeRateLimitConfig(); + TbClusterService getClusterService(); DashboardService getDashboardService(); 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 b0f426d905..7925178b33 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 @@ -15,8 +15,8 @@ */ package org.thingsboard.rule.engine.action; -import com.google.common.base.Stopwatch; import lombok.extern.slf4j.Slf4j; +import org.springframework.util.ConcurrentReferenceHashMap; import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; import org.thingsboard.rule.engine.api.RuleNode; import org.thingsboard.rule.engine.api.TbContext; @@ -28,17 +28,15 @@ import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.msg.TbMsgType; +import org.thingsboard.server.common.data.msg.TbNodeConnectionType; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; -import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.TbCallback; +import org.thingsboard.server.common.msg.tools.TbRateLimits; -import java.time.Duration; import java.util.EnumSet; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; @Slf4j @RuleNode( @@ -47,8 +45,8 @@ import java.util.concurrent.ConcurrentMap; nodeDescription = "Triggers device connectivity events", nodeDetails = "If incoming message originator is a device, registers configured event for that device in the Device State Service, which sends appropriate message to the Rule Engine." + " If metadata ts property is present, it will be used as event timestamp. Otherwise, the message timestamp will be used." + - " Incoming message is forwarded using the Success chain, unless an unexpected error occurs during message processing" + - " then incoming message is forwarded using the Failure chain." + + " If originator entity type is not DEVICE or unexpected error happened during processing, then incoming message is forwarded using Failure chain." + + " If rate of connectivity events for a given originator is too high, then incoming message is forwarded using Rate limited chain. " + "
    " + "Supported device connectivity events are:" + "
      " + @@ -59,6 +57,7 @@ import java.util.concurrent.ConcurrentMap; "
    " + "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" ) @@ -67,12 +66,9 @@ public class TbDeviceStateNode implements TbNode { private static final Set SUPPORTED_EVENTS = EnumSet.of( TbMsgType.CONNECT_EVENT, TbMsgType.ACTIVITY_EVENT, TbMsgType.DISCONNECT_EVENT, TbMsgType.INACTIVITY_EVENT ); - private static final Duration ONE_SECOND = Duration.ofSeconds(1L); - private static final Duration ENTRY_EXPIRATION_TIME = Duration.ofDays(1L); - private static final Duration ENTRY_CLEANUP_PERIOD = Duration.ofHours(1L); - - private Stopwatch stopwatch; - private ConcurrentMap lastActivityEventTimestamps; + private static final String DEFAULT_RATE_LIMIT_CONFIG = "1:1,30:60,60:3600"; + private ConcurrentReferenceHashMap rateLimits; + private String rateLimitConfig; private TbMsgType event; @Override @@ -85,19 +81,19 @@ public class TbDeviceStateNode implements TbNode { throw new TbNodeException("Unsupported event: " + event, true); } this.event = event; - lastActivityEventTimestamps = new ConcurrentHashMap<>(); - stopwatch = Stopwatch.createStarted(); - scheduleCleanupMsg(ctx); + rateLimits = new ConcurrentReferenceHashMap<>(); + String deviceStateNodeRateLimitConfig = ctx.getDeviceStateNodeRateLimitConfig(); + try { + rateLimitConfig = new TbRateLimits(deviceStateNodeRateLimitConfig).getConfiguration(); + } catch (Exception e) { + log.error("[{}][{}] Invalid rate limit configuration provided: [{}]. Will use default value [{}].", + ctx.getTenantId().getId(), ctx.getSelfId().getId(), deviceStateNodeRateLimitConfig, DEFAULT_RATE_LIMIT_CONFIG, e); + rateLimitConfig = DEFAULT_RATE_LIMIT_CONFIG; + } } @Override public void onMsg(TbContext ctx, TbMsg msg) { - if (msg.isTypeOf(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG)) { - removeStaleEntries(); - scheduleCleanupMsg(ctx); - return; - } - EntityType originatorEntityType = msg.getOriginator().getEntityType(); if (!EntityType.DEVICE.equals(originatorEntityType)) { ctx.tellFailure(msg, new IllegalArgumentException( @@ -105,41 +101,18 @@ public class TbDeviceStateNode implements TbNode { )); return; } - DeviceId originator = new DeviceId(msg.getOriginator().getId()); - - lastActivityEventTimestamps.compute(originator, (__, lastEventTs) -> { - Duration now = stopwatch.elapsed(); - - if (lastEventTs == null) { - sendEventAndTell(ctx, originator, msg); - return now; + rateLimits.compute(originator, (__, rateLimit) -> { + if (rateLimit == null) { + rateLimit = new TbRateLimits(rateLimitConfig); } - - Duration elapsedSinceLastEventSent = now.minus(lastEventTs); - if (elapsedSinceLastEventSent.compareTo(ONE_SECOND) < 0) { - ctx.tellSuccess(msg); - return lastEventTs; + boolean isNotRateLimited = rateLimit.tryConsume(); + if (isNotRateLimited) { + sendEventAndTell(ctx, originator, msg); + } else { + ctx.tellNext(msg, "Rate limited"); } - - sendEventAndTell(ctx, originator, msg); - return now; - }); - } - - private void scheduleCleanupMsg(TbContext ctx) { - TbMsg cleanupMsg = ctx.newMsg( - null, TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG, ctx.getSelfId(), TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING - ); - ctx.tellSelf(cleanupMsg, ENTRY_CLEANUP_PERIOD.toMillis()); - } - - private void removeStaleEntries() { - lastActivityEventTimestamps.entrySet().removeIf(entry -> { - Duration now = stopwatch.elapsed(); - Duration lastEventTs = entry.getValue(); - Duration elapsedSinceLastEventSent = now.minus(lastEventTs); - return elapsedSinceLastEventSent.compareTo(ENTRY_EXPIRATION_TIME) > 0; + return rateLimit; }); } @@ -184,16 +157,16 @@ public class TbDeviceStateNode implements TbNode { @Override public void onPartitionChangeMsg(TbContext ctx, PartitionChangeMsg msg) { - lastActivityEventTimestamps.entrySet().removeIf(entry -> !ctx.isLocalEntity(entry.getKey())); + rateLimits.entrySet().removeIf(entry -> !ctx.isLocalEntity(entry.getKey())); } @Override public void destroy() { - if (lastActivityEventTimestamps != null) { - lastActivityEventTimestamps.clear(); - lastActivityEventTimestamps = null; + if (rateLimits != null) { + rateLimits.clear(); + rateLimits = null; } - stopwatch = null; + rateLimitConfig = null; event = null; } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java index 19cb3c55bd..9352d64809 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/action/TbDeviceStateNodeTest.java @@ -15,8 +15,6 @@ */ package org.thingsboard.rule.engine.action; -import com.google.common.base.Stopwatch; -import com.google.common.base.Ticker; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -29,6 +27,7 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.util.ConcurrentReferenceHashMap; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.RuleEngineDeviceStateManager; import org.thingsboard.rule.engine.api.TbContext; @@ -45,11 +44,9 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TbCallback; +import org.thingsboard.server.common.msg.tools.TbRateLimits; -import java.time.Duration; import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -57,9 +54,10 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; @ExtendWith(MockitoExtension.class) public class TbDeviceStateNodeTest { @@ -71,21 +69,12 @@ public class TbDeviceStateNodeTest { @Captor private static ArgumentCaptor callbackCaptor; private TbDeviceStateNode node; - private RuleNodeId nodeId; private TbDeviceStateNodeConfiguration config; private static final TenantId TENANT_ID = TenantId.fromUUID(UUID.randomUUID()); private static final DeviceId DEVICE_ID = new DeviceId(UUID.randomUUID()); private static final long METADATA_TS = 123L; - private TbMsg cleanupMsg; private TbMsg msg; - private long nowNanos; - private final Ticker controlledTicker = new Ticker() { - @Override - public long read() { - return nowNanos; - } - }; @BeforeEach public void setup() { @@ -96,8 +85,6 @@ public class TbDeviceStateNodeTest { var data = JacksonUtil.newObjectNode(); data.put("humidity", 58.3); msg = TbMsg.newMsg(TbMsgType.POST_TELEMETRY_REQUEST, DEVICE_ID, metaData, JacksonUtil.toString(data)); - nodeId = new RuleNodeId(UUID.randomUUID()); - cleanupMsg = TbMsg.newMsg(null, TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG, nodeId, TbMsgMetaData.EMPTY, TbMsg.EMPTY_STRING); } @BeforeEach @@ -121,80 +108,42 @@ public class TbDeviceStateNodeTest { } @Test - public void givenValidConfig_whenInit_thenSchedulesCleanupMsg() { + public void givenInvalidRateLimitConfig_whenInit_thenUsesDefaultConfig() { // GIVEN - given(ctxMock.getSelfId()).willReturn(nodeId); - given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); + given(ctxMock.getDeviceStateNodeRateLimitConfig()).willReturn("invalid rate limit config"); + given(ctxMock.getTenantId()).willReturn(TENANT_ID); + given(ctxMock.getSelfId()).willReturn(new RuleNodeId(UUID.randomUUID())); // WHEN try { initNode(TbMsgType.ACTIVITY_EVENT); } catch (Exception e) { - fail("Node failed to initialize."); + fail("Node failed to initialize!", e); } // THEN - verifyCleanupMsgSent(); - } - - @Test - public void givenCleanupMsg_whenOnMsg_thenCleansStaleEntries() { - // GIVEN - given(ctxMock.getSelfId()).willReturn(nodeId); - given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); - - ConcurrentMap lastActivityEventTimestamps = new ConcurrentHashMap<>(); - ReflectionTestUtils.setField(node, "lastActivityEventTimestamps", lastActivityEventTimestamps); - - Stopwatch stopwatch = Stopwatch.createStarted(controlledTicker); - ReflectionTestUtils.setField(node, "stopwatch", stopwatch); - - // WHEN - Duration expirationTime = Duration.ofDays(1L); - - DeviceId staleId = DEVICE_ID; - Duration staleTs = Duration.ofHours(4L); - lastActivityEventTimestamps.put(staleId, staleTs); - - DeviceId goodId = new DeviceId(UUID.randomUUID()); - Duration goodTs = staleTs.plus(expirationTime); - lastActivityEventTimestamps.put(goodId, goodTs); - - nowNanos = staleTs.toNanos() + expirationTime.toNanos() + 1; - node.onMsg(ctxMock, cleanupMsg); - - // THEN - assertThat(lastActivityEventTimestamps) - .containsKey(goodId) - .doesNotContainKey(staleId) - .size().isOne(); - - verifyCleanupMsgSent(); - then(ctxMock).shouldHaveNoMoreInteractions(); + String actualRateLimitConfig = (String) ReflectionTestUtils.getField(node, "rateLimitConfig"); + assertThat(actualRateLimitConfig).isEqualTo("1:1,30:60,60:3600"); } @Test public void givenMsgArrivedTooFast_whenOnMsg_thenRateLimitsThisMsg() { // GIVEN - ConcurrentMap lastActivityEventTimestamps = new ConcurrentHashMap<>(); - ReflectionTestUtils.setField(node, "lastActivityEventTimestamps", lastActivityEventTimestamps); + ConcurrentReferenceHashMap rateLimits = new ConcurrentReferenceHashMap<>(); + ReflectionTestUtils.setField(node, "rateLimits", rateLimits); - Stopwatch stopwatch = Stopwatch.createStarted(controlledTicker); - ReflectionTestUtils.setField(node, "stopwatch", stopwatch); + var rateLimitMock = mock(TbRateLimits.class); + rateLimits.put(DEVICE_ID, rateLimitMock); - // WHEN - Duration firstEventTs = Duration.ofMillis(1000L); - lastActivityEventTimestamps.put(DEVICE_ID, firstEventTs); + given(rateLimitMock.tryConsume()).willReturn(false); - Duration tooFastEventTs = firstEventTs.plus(Duration.ofMillis(999L)); - nowNanos = tooFastEventTs.toNanos(); + // WHEN node.onMsg(ctxMock, msg); // THEN - Duration actualEventTs = lastActivityEventTimestamps.get(DEVICE_ID); - assertThat(actualEventTs).isEqualTo(firstEventTs); - - then(ctxMock).should().tellSuccess(msg); + then(ctxMock).should().tellNext(msg, "Rate limited"); + then(ctxMock).should(never()).tellSuccess(any()); + then(ctxMock).should(never()).tellFailure(any(), any()); then(ctxMock).shouldHaveNoMoreInteractions(); then(deviceStateManagerMock).shouldHaveNoInteractions(); } @@ -202,25 +151,25 @@ public class TbDeviceStateNodeTest { @Test public void givenHasNonLocalDevices_whenOnPartitionChange_thenRemovesEntriesForNonLocalDevices() { // GIVEN - ConcurrentMap lastActivityEventTimestamps = new ConcurrentHashMap<>(); - ReflectionTestUtils.setField(node, "lastActivityEventTimestamps", lastActivityEventTimestamps); + ConcurrentReferenceHashMap rateLimits = new ConcurrentReferenceHashMap<>(); + ReflectionTestUtils.setField(node, "rateLimits", rateLimits); - lastActivityEventTimestamps.put(DEVICE_ID, Duration.ofHours(24L)); + rateLimits.put(DEVICE_ID, new TbRateLimits("1:1")); given(ctxMock.isLocalEntity(eq(DEVICE_ID))).willReturn(true); DeviceId nonLocalDeviceId1 = new DeviceId(UUID.randomUUID()); - lastActivityEventTimestamps.put(nonLocalDeviceId1, Duration.ofHours(30L)); + rateLimits.put(nonLocalDeviceId1, new TbRateLimits("2:2")); given(ctxMock.isLocalEntity(eq(nonLocalDeviceId1))).willReturn(false); DeviceId nonLocalDeviceId2 = new DeviceId(UUID.randomUUID()); - lastActivityEventTimestamps.put(nonLocalDeviceId2, Duration.ofHours(32L)); + rateLimits.put(nonLocalDeviceId2, new TbRateLimits("3:3")); given(ctxMock.isLocalEntity(eq(nonLocalDeviceId2))).willReturn(false); // WHEN node.onPartitionChangeMsg(ctxMock, new PartitionChangeMsg(ServiceType.TB_RULE_ENGINE)); // THEN - assertThat(lastActivityEventTimestamps) + assertThat(rateLimits) .containsKey(DEVICE_ID) .doesNotContainKey(nonLocalDeviceId1) .doesNotContainKey(nonLocalDeviceId2) @@ -275,6 +224,7 @@ public class TbDeviceStateNodeTest { @Test public void givenMetadataDoesNotContainTs_whenOnMsg_thenMsgTsIsUsedAsEventTs() { // GIVEN + given(ctxMock.getDeviceStateNodeRateLimitConfig()).willReturn("1:1"); try { initNode(TbMsgType.ACTIVITY_EVENT); } catch (TbNodeException e) { @@ -298,9 +248,8 @@ public class TbDeviceStateNodeTest { @MethodSource public void givenSupportedEventAndDeviceOriginator_whenOnMsg_thenCorrectEventIsSentWithCorrectCallback(TbMsgType supportedEventType, Runnable actionVerification) { // GIVEN - given(ctxMock.getSelfId()).willReturn(nodeId); - given(ctxMock.newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING))).willReturn(cleanupMsg); given(ctxMock.getTenantId()).willReturn(TENANT_ID); + given(ctxMock.getDeviceStateNodeRateLimitConfig()).willReturn("1:1"); given(ctxMock.getDeviceStateManager()).willReturn(deviceStateManagerMock); try { @@ -308,7 +257,6 @@ public class TbDeviceStateNodeTest { } catch (TbNodeException e) { fail("Node failed to initialize!", e); } - verifyCleanupMsgSent(); // WHEN node.onMsg(ctxMock, msg); @@ -345,10 +293,4 @@ public class TbDeviceStateNodeTest { node.init(ctxMock, nodeConfig); } - private void verifyCleanupMsgSent() { - then(ctxMock).should().getSelfId(); - then(ctxMock).should().newMsg(isNull(), eq(TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG), eq(nodeId), eq(TbMsgMetaData.EMPTY), eq(TbMsg.EMPTY_STRING)); - then(ctxMock).should().tellSelf(eq(cleanupMsg), eq(Duration.ofHours(1L).toMillis())); - } - } From 06bd88f7e9a4188459b5d1476685eb54c6280c27 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 15 Feb 2024 17:28:07 +0200 Subject: [PATCH 241/397] Remove device state entries cleanup message --- .../java/org/thingsboard/server/common/data/msg/TbMsgType.java | 1 - .../org/thingsboard/server/common/data/msg/TbMsgTypeTest.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/msg/TbMsgType.java b/common/data/src/main/java/org/thingsboard/server/common/data/msg/TbMsgType.java index b2014f4bb0..763f245a09 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/msg/TbMsgType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/msg/TbMsgType.java @@ -76,7 +76,6 @@ public enum TbMsgType { DEDUPLICATION_TIMEOUT_SELF_MSG(null, true), DELAY_TIMEOUT_SELF_MSG(null, true), MSG_COUNT_SELF_MSG(null, true), - DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG(null, true), // Custom or N/A type: NA; diff --git a/common/data/src/test/java/org/thingsboard/server/common/data/msg/TbMsgTypeTest.java b/common/data/src/test/java/org/thingsboard/server/common/data/msg/TbMsgTypeTest.java index 529f6e6646..2221b236bd 100644 --- a/common/data/src/test/java/org/thingsboard/server/common/data/msg/TbMsgTypeTest.java +++ b/common/data/src/test/java/org/thingsboard/server/common/data/msg/TbMsgTypeTest.java @@ -26,7 +26,6 @@ import static org.thingsboard.server.common.data.msg.TbMsgType.DEDUPLICATION_TIM import static org.thingsboard.server.common.data.msg.TbMsgType.DELAY_TIMEOUT_SELF_MSG; import static org.thingsboard.server.common.data.msg.TbMsgType.DEVICE_PROFILE_PERIODIC_SELF_MSG; import static org.thingsboard.server.common.data.msg.TbMsgType.DEVICE_PROFILE_UPDATE_SELF_MSG; -import static org.thingsboard.server.common.data.msg.TbMsgType.DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG; import static org.thingsboard.server.common.data.msg.TbMsgType.DEVICE_UPDATE_SELF_MSG; import static org.thingsboard.server.common.data.msg.TbMsgType.ENTITY_ASSIGNED_TO_EDGE; import static org.thingsboard.server.common.data.msg.TbMsgType.ENTITY_UNASSIGNED_FROM_EDGE; @@ -54,7 +53,6 @@ class TbMsgTypeTest { DEDUPLICATION_TIMEOUT_SELF_MSG, DELAY_TIMEOUT_SELF_MSG, MSG_COUNT_SELF_MSG, - DEVICE_STATE_STALE_ENTRIES_CLEANUP_SELF_MSG, NA ); From 89db4b1188477e2b61d645efaf61341bcfecefe0 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 15 Feb 2024 17:37:28 +0200 Subject: [PATCH 242/397] Change proto numbers to avoid conflicts with PE --- common/proto/src/main/proto/queue.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/proto/src/main/proto/queue.proto b/common/proto/src/main/proto/queue.proto index 8c1918d5ef..149ac9c81f 100644 --- a/common/proto/src/main/proto/queue.proto +++ b/common/proto/src/main/proto/queue.proto @@ -1295,9 +1295,9 @@ message ToCoreMsg { LifecycleEventProto lifecycleEventMsg = 8; ErrorEventProto errorEventMsg = 9; ToDeviceActorNotificationMsgProto toDeviceActorNotification = 10; - DeviceConnectProto deviceConnectMsg = 11; - DeviceDisconnectProto deviceDisconnectMsg = 12; - DeviceInactivityProto deviceInactivityMsg = 13; + DeviceConnectProto deviceConnectMsg = 13; + DeviceDisconnectProto deviceDisconnectMsg = 14; + DeviceInactivityProto deviceInactivityMsg = 15; } /* High priority messages with low latency are handled by ThingsBoard Core Service separately */ From e8b88ea7b1a6d2bc58807bed09c739998f2f3296 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 15 Feb 2024 17:45:21 +0200 Subject: [PATCH 243/397] UI: Fixed translate --- .../notification-template-configuration.component.html | 2 +- ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html index e39d7f27c8..0a992618b9 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.html @@ -124,7 +124,7 @@ + actionTitle="{{ 'notification.notification-tap-action' | translate }}"> 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 da8972c39e..e8a397bee9 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3214,7 +3214,6 @@ }, "notification": { "action-button": "Action button", - "action-on-click-notification": "Action on click notification", "action-type": "Action type", "active": "Active", "add-notification-recipients-group": "Add notification recipients group", @@ -3337,6 +3336,7 @@ "not-found-slack-recipient": "Slack recipient not found", "notification": "Notification", "notification-center": "Notification center", + "notification-tap-action": "Notification tap action", "notify": "notify", "notify-again": "Notify again", "notify-alarm-action": { From f8ab53b01878b608857ba2511733798e7ab300e8 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 15 Feb 2024 17:57:56 +0200 Subject: [PATCH 244/397] UI: Fixed translate --- ui-ngx/src/assets/locale/locale.constant-en_US.json | 1 + 1 file changed, 1 insertion(+) 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 f3e9470c45..625888bcd2 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3241,6 +3241,7 @@ "new-platform-version-trigger-settings": "New platform version trigger settings", "rate-limits-trigger-settings": "Exceeded rate limits trigger settings", "at-least-one-should-be-selected": "At least one should be selected", + "basic-settings": "Basic settings", "button-text": "Button text", "button-text-required": "Button text is required", "button-text-max-length": "Button text should be less than or equal to {{ length }} characters", From e586f367faa38044c4f6dee2958fb8bb022cf6e1 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 15 Feb 2024 18:05:01 +0200 Subject: [PATCH 245/397] Change log level to avoid cluttering logs --- .../service/state/DefaultRuleEngineDeviceStateManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManager.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManager.java index 087f470fed..722fcd1aac 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManager.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManager.java @@ -175,7 +175,7 @@ public class DefaultRuleEngineDeviceStateManager implements RuleEngineDeviceStat TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, deviceId); if (serviceInfoProvider.isService(ServiceType.TB_CORE) && tpi.isMyPartition() && deviceStateService.isPresent()) { - log.info("[{}][{}] Forwarding device connectivity event to local service. Event time: [{}].", tenantId.getId(), deviceId.getId(), eventTime); + log.debug("[{}][{}] Forwarding device connectivity event to local service. Event time: [{}].", tenantId.getId(), deviceId.getId(), eventTime); try { eventInfo.forwardToLocalService(); } catch (Exception e) { @@ -186,7 +186,7 @@ public class DefaultRuleEngineDeviceStateManager implements RuleEngineDeviceStat callback.onSuccess(); } else { TransportProtos.ToCoreMsg msg = eventInfo.toQueueMsg(); - log.info("[{}][{}] Sending device connectivity message to core. Event time: [{}].", tenantId.getId(), deviceId.getId(), eventTime); + log.debug("[{}][{}] Sending device connectivity message to core. Event time: [{}].", tenantId.getId(), deviceId.getId(), eventTime); clusterService.pushMsgToCore(tpi, UUID.randomUUID(), msg, new SimpleTbQueueCallback(__ -> callback.onSuccess(), callback::onFailure)); } } From dbaf72114075a41205da728223d1314579ad95eb Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 15 Feb 2024 17:12:47 +0100 Subject: [PATCH 246/397] fixed delete alarm events --- .../server/service/edge/EdgeEventSourcingListener.java | 2 ++ .../thingsboard/server/service/edge/rpc/EdgeGrpcSession.java | 1 + .../server/service/edge/rpc/processor/BaseEdgeProcessor.java | 1 + .../service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java | 2 +- .../service/edge/rpc/processor/alarm/BaseAlarmProcessor.java | 1 + .../server/service/entitiy/alarm/DefaultTbAlarmService.java | 2 +- .../thingsboard/server/controller/AlarmControllerTest.java | 4 ++-- .../server/common/data/edge/EdgeEventActionType.java | 1 + .../org/thingsboard/server/dao/audit/AuditLogServiceImpl.java | 1 + 9 files changed, 11 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java index ca7048c7e9..260707cf68 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java @@ -107,6 +107,8 @@ public class EdgeEventSourcingListener { private EdgeEventActionType getEdgeEventActionTypeForEntityEvent(Object entity) { if (entity instanceof AlarmComment) { return EdgeEventActionType.DELETED_COMMENT; + } else if (entity instanceof Alarm) { + return EdgeEventActionType.ALARM_DELETE; } return EdgeEventActionType.DELETED; } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 98346674ae..e5038d3b3a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -540,6 +540,7 @@ public final class EdgeGrpcSession implements Closeable { case UNASSIGNED_FROM_EDGE: case ALARM_ACK: case ALARM_CLEAR: + case ALARM_DELETE: case CREDENTIALS_UPDATED: case RELATION_ADD_OR_UPDATE: case RELATION_DELETED: diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java index 256f191215..db442f76b2 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java @@ -460,6 +460,7 @@ public abstract class BaseEdgeProcessor { case UNASSIGNED_FROM_EDGE: case RELATION_DELETED: case DELETED_COMMENT: + case ALARM_DELETE: return UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE; case ALARM_ACK: return UpdateMsgType.ALARM_ACK_RPC_MESSAGE; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java index f83cbbba9c..b578325961 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/AlarmEdgeProcessor.java @@ -105,7 +105,7 @@ public abstract class AlarmEdgeProcessor extends BaseAlarmProcessor implements A EdgeEventActionType actionType = EdgeEventActionType.valueOf(edgeNotificationMsg.getAction()); AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB())); EdgeId originatorEdgeId = safeGetEdgeId(edgeNotificationMsg.getOriginatorEdgeIdMSB(), edgeNotificationMsg.getOriginatorEdgeIdLSB()); - if (EdgeEventActionType.DELETED.equals(actionType)) { + if (EdgeEventActionType.DELETED.equals(actionType) || EdgeEventActionType.ALARM_DELETE.equals(actionType)) { Alarm deletedAlarm = JacksonUtil.fromString(edgeNotificationMsg.getBody(), Alarm.class); if (deletedAlarm == null) { return Futures.immediateFuture(null); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java index 97e1590b5b..ff2c0ca5f6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java @@ -154,6 +154,7 @@ public abstract class BaseAlarmProcessor extends BaseEdgeProcessor { .constructAlarmUpdatedMsg(msgType, alarm, findOriginatorEntityName(tenantId, alarm)); } break; + case ALARM_DELETE: case DELETED: Alarm deletedAlarm = JacksonUtil.convertValue(body, Alarm.class); if (deletedAlarm != null) { diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java index 5305018b84..3876efbc06 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmService.java @@ -196,7 +196,7 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb public Boolean delete(Alarm alarm, User user) { TenantId tenantId = alarm.getTenantId(); notificationEntityService.logEntityAction(tenantId, alarm.getOriginator(), alarm, alarm.getCustomerId(), - ActionType.DELETED, user); + ActionType.ALARM_DELETE, user); return alarmSubscriptionService.deleteAlarm(tenantId, alarm.getId()); } diff --git a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java index 1415e38d7e..5290b429c0 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AlarmControllerTest.java @@ -261,7 +261,7 @@ public class AlarmControllerTest extends AbstractControllerTest { doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isOk()); testNotifyEntityAllOneTime(new Alarm(alarm), alarm.getId(), alarm.getOriginator(), - tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.DELETED); + tenantId, customerId, customerUserId, CUSTOMER_USER_EMAIL, ActionType.ALARM_DELETE); } @Test @@ -274,7 +274,7 @@ public class AlarmControllerTest extends AbstractControllerTest { doDelete("/api/alarm/" + alarm.getId()).andExpect(status().isOk()); testNotifyEntityAllOneTime(new Alarm(alarm), alarm.getId(), alarm.getOriginator(), - tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.DELETED); + tenantId, customerId, tenantAdminUserId, TENANT_ADMIN_EMAIL, ActionType.ALARM_DELETE); } @Test diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventActionType.java b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventActionType.java index 680f744c7b..7bee0c6094 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventActionType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventActionType.java @@ -35,6 +35,7 @@ public enum EdgeEventActionType { RPC_CALL(ActionType.RPC_CALL), ALARM_ACK(ActionType.ALARM_ACK), ALARM_CLEAR(ActionType.ALARM_CLEAR), + ALARM_DELETE(ActionType.ALARM_DELETE), ALARM_ASSIGNED(ActionType.ALARM_ASSIGNED), ALARM_UNASSIGNED(ActionType.ALARM_UNASSIGNED), ADDED_COMMENT(ActionType.ADDED_COMMENT), diff --git a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java index 4350f2a5d1..ddaebef6e8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/audit/AuditLogServiceImpl.java @@ -190,6 +190,7 @@ public class AuditLogServiceImpl implements AuditLogService { AlarmComment comment = extractParameter(AlarmComment.class, additionalInfo); actionData.set("comment", comment.getComment()); break; + case ALARM_DELETE: case DELETED: case ACTIVATED: case SUSPENDED: From 11cf5e7de899ca4ab44ce6633dceb04c07241255 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 15 Feb 2024 18:36:16 +0200 Subject: [PATCH 247/397] Change proto numbering --- common/proto/src/main/proto/queue.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/proto/src/main/proto/queue.proto b/common/proto/src/main/proto/queue.proto index 149ac9c81f..e432b0dcec 100644 --- a/common/proto/src/main/proto/queue.proto +++ b/common/proto/src/main/proto/queue.proto @@ -1295,9 +1295,9 @@ message ToCoreMsg { LifecycleEventProto lifecycleEventMsg = 8; ErrorEventProto errorEventMsg = 9; ToDeviceActorNotificationMsgProto toDeviceActorNotification = 10; - DeviceConnectProto deviceConnectMsg = 13; - DeviceDisconnectProto deviceDisconnectMsg = 14; - DeviceInactivityProto deviceInactivityMsg = 15; + DeviceConnectProto deviceConnectMsg = 50; + DeviceDisconnectProto deviceDisconnectMsg = 51; + DeviceInactivityProto deviceInactivityMsg = 52; } /* High priority messages with low latency are handled by ThingsBoard Core Service separately */ From 73afd9a7f4e6190f1cc430a36af3c369e15dd8a3 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 15 Feb 2024 18:55:12 +0200 Subject: [PATCH 248/397] Make device state manage a rule engine component --- .../java/org/thingsboard/server/actors/ActorSystemContext.java | 2 +- .../service/state/DefaultRuleEngineDeviceStateManager.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java index 2a4f132be8..e3ebbdf892 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java @@ -204,7 +204,7 @@ public class ActorSystemContext { @Getter private DeviceCredentialsService deviceCredentialsService; - @Autowired + @Autowired(required = false) @Getter private RuleEngineDeviceStateManager deviceStateManager; diff --git a/application/src/main/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManager.java b/application/src/main/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManager.java index 722fcd1aac..af2b03ec8f 100644 --- a/application/src/main/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManager.java +++ b/application/src/main/java/org/thingsboard/server/service/state/DefaultRuleEngineDeviceStateManager.java @@ -29,12 +29,14 @@ import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.common.SimpleTbQueueCallback; import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.discovery.TbServiceInfoProvider; +import org.thingsboard.server.queue.util.TbRuleEngineComponent; import java.util.Optional; import java.util.UUID; @Slf4j @Service +@TbRuleEngineComponent public class DefaultRuleEngineDeviceStateManager implements RuleEngineDeviceStateManager { private final TbServiceInfoProvider serviceInfoProvider; From 977dd85fcfc18ae61ac2c4f0cbc2daaab74985ed Mon Sep 17 00:00:00 2001 From: Dmitriymush Date: Thu, 15 Feb 2024 18:56:49 +0200 Subject: [PATCH 249/397] UI: fixed typeList url query and alarm filter config translation --- .../components/alarm/alarm-filter-config.component.ts | 10 ++++++++-- ui-ngx/src/app/shared/models/alarm.models.ts | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts b/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts index 1218cedca2..609dbb8e7a 100644 --- a/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts @@ -45,6 +45,7 @@ import { deepClone } from '@core/utils'; import { EntityType } from '@shared/models/entity-type.models'; import { fromEvent, Subscription } from 'rxjs'; import { POSITION_MAP } from '@shared/models/overlay.models'; +import { UtilsService } from '@core/services/utils.service'; export const ALARM_FILTER_CONFIG_DATA = new InjectionToken('AlarmFilterConfigData'); @@ -127,7 +128,8 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal private translate: TranslateService, private overlay: Overlay, private nativeElement: ElementRef, - private viewContainerRef: ViewContainerRef) { + private viewContainerRef: ViewContainerRef, + private utils: UtilsService) { } ngOnInit(): void { @@ -298,7 +300,7 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal this.translate.instant(alarmSeverityTranslations.get(s))).join(', ')); } if (this.alarmFilterConfig?.typeList?.length) { - filterTextParts.push(this.alarmFilterConfig.typeList.join(', ')); + filterTextParts.push(this.alarmFilterConfig.typeList.map((type) => this.customTranslate(type)).join(', ')); } if (this.alarmFilterConfig?.assignedToCurrentUser) { filterTextParts.push(this.translate.instant('alarm.assigned-to-me')); @@ -313,4 +315,8 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal } } + private customTranslate(entity: string) { + return this.utils.customTranslation(entity, entity); + } + } diff --git a/ui-ngx/src/app/shared/models/alarm.models.ts b/ui-ngx/src/app/shared/models/alarm.models.ts index 43fd717ef7..57509368d5 100644 --- a/ui-ngx/src/app/shared/models/alarm.models.ts +++ b/ui-ngx/src/app/shared/models/alarm.models.ts @@ -335,7 +335,7 @@ export class AlarmQueryV2 { let query = this.affectedEntityId ? `/${this.affectedEntityId.entityType}/${this.affectedEntityId.id}` : ''; query += this.pageLink.toQuery(); if (this.typeList && this.typeList.length) { - query += `&typeList=${this.typeList.join(',')}`; + query += `&typeList=${this.typeList.map(type => encodeURIComponent(type)).join(',')}`; } if (this.statusList && this.statusList.length) { query += `&statusList=${this.statusList.join(',')}`; From 5c26757590a76f39d8088ae4d25d7f91cbaa1cf4 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Thu, 15 Feb 2024 19:39:33 +0100 Subject: [PATCH 250/397] fixed DefaultTbAlarmServiceTest --- .../server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java index 5d493193db..c9cec6fb1a 100644 --- a/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/entitiy/alarm/DefaultTbAlarmServiceTest.java @@ -129,7 +129,7 @@ public class DefaultTbAlarmServiceTest { public void testDelete() { service.delete(new Alarm(), new User()); - verify(notificationEntityService, times(1)).logEntityAction(any(), any(), any(), any(), eq(ActionType.DELETED), any()); + verify(notificationEntityService, times(1)).logEntityAction(any(), any(), any(), any(), eq(ActionType.ALARM_DELETE), any()); verify(alarmSubscriptionService, times(1)).deleteAlarm(any(), any()); } From 19259efd49937a37d178495d6ef9640478f93e69 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Fri, 16 Feb 2024 10:30:48 +0200 Subject: [PATCH 251/397] Use pageDataIterable instead of pageData --- .../edge/rpc/processor/BaseEdgeProcessor.java | 74 ++++++------------- .../customer/CustomerEdgeProcessor.java | 20 ++--- 2 files changed, 29 insertions(+), 65 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java index cd1876cd34..bfc1def11c 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java @@ -50,9 +50,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.msg.TbMsgType; -import org.thingsboard.server.common.data.page.PageData; +import org.thingsboard.server.common.data.page.PageDataIterable; import org.thingsboard.server.common.data.page.PageDataIterableByTenantIdEntityId; -import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.rule.RuleChain; @@ -405,15 +404,10 @@ public abstract class BaseEdgeProcessor { JsonNode body, EdgeId sourceEdgeId) { List> futures = new ArrayList<>(); if (TenantId.SYS_TENANT_ID.equals(tenantId)) { - PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); - PageData tenantsIds; - do { - tenantsIds = tenantService.findTenantsIds(pageLink); - for (TenantId tenantId1 : tenantsIds.getData()) { - futures.addAll(processActionForAllEdgesByTenantId(tenantId1, type, actionType, entityId, body, sourceEdgeId)); - } - pageLink = pageLink.nextPageLink(); - } while (tenantsIds.hasNext()); + PageDataIterable tenantIds = new PageDataIterable<>(link -> tenantService.findTenantsIds(link), 1024); + for (TenantId tenantId1 : tenantIds) { + futures.addAll(processActionForAllEdgesByTenantId(tenantId1, type, actionType, entityId, body, sourceEdgeId)); + } } else { futures = processActionForAllEdgesByTenantId(tenantId, type, actionType, entityId, null, sourceEdgeId); } @@ -426,22 +420,13 @@ public abstract class BaseEdgeProcessor { EntityId entityId, JsonNode body, EdgeId sourceEdgeId) { - PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); - PageData pageData; List> futures = new ArrayList<>(); - do { - pageData = edgeService.findEdgesByTenantId(tenantId, pageLink); - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { - for (Edge edge : pageData.getData()) { - if (!edge.getId().equals(sourceEdgeId)) { - futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, body)); - } - } - if (pageData.hasNext()) { - pageLink = pageLink.nextPageLink(); - } + PageDataIterable edges = new PageDataIterable<>(link -> edgeService.findEdgesByTenantId(tenantId, link), 1024); + for (Edge edge : edges) { + if (!edge.getId().equals(sourceEdgeId)) { + futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, entityId, body)); } - } while (pageData != null && pageData.hasNext()); + } return futures; } @@ -548,35 +533,24 @@ public abstract class BaseEdgeProcessor { } private ListenableFuture updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId) { - PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); - PageData pageData; List> futures = new ArrayList<>(); - do { - pageData = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, pageLink); - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { - for (RuleChain ruleChain : pageData.getData()) { - if (!ruleChain.getId().equals(processingRuleChainId)) { - List connectionInfos = - ruleChainService.loadRuleChainMetaData(ruleChain.getTenantId(), ruleChain.getId()).getRuleChainConnections(); - if (connectionInfos != null && !connectionInfos.isEmpty()) { - for (RuleChainConnectionInfo connectionInfo : connectionInfos) { - if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) { - futures.add(saveEdgeEvent(tenantId, - edgeId, - EdgeEventType.RULE_CHAIN_METADATA, - EdgeEventActionType.UPDATED, - ruleChain.getId(), - null)); - } - } - } + PageDataIterable ruleChains = new PageDataIterable<>(link -> ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, link), 1024); + for (RuleChain ruleChain : ruleChains) { + List connectionInfos = + ruleChainService.loadRuleChainMetaData(ruleChain.getTenantId(), ruleChain.getId()).getRuleChainConnections(); + if (connectionInfos != null && !connectionInfos.isEmpty()) { + for (RuleChainConnectionInfo connectionInfo : connectionInfos) { + if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) { + futures.add(saveEdgeEvent(tenantId, + edgeId, + EdgeEventType.RULE_CHAIN_METADATA, + EdgeEventActionType.UPDATED, + ruleChain.getId(), + null)); } } - if (pageData.hasNext()) { - pageLink = pageLink.nextPageLink(); - } } - } while (pageData != null && pageData.hasNext()); + } return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/customer/CustomerEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/customer/CustomerEdgeProcessor.java index 46daccfbe4..f6403629eb 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/customer/CustomerEdgeProcessor.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/customer/CustomerEdgeProcessor.java @@ -29,8 +29,7 @@ import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.common.data.page.PageData; -import org.thingsboard.server.common.data.page.PageLink; +import org.thingsboard.server.common.data.page.PageDataIterable; import org.thingsboard.server.gen.edge.v1.CustomerUpdateMsg; import org.thingsboard.server.gen.edge.v1.DownlinkMsg; import org.thingsboard.server.gen.edge.v1.EdgeVersion; @@ -85,20 +84,11 @@ public class CustomerEdgeProcessor extends BaseEdgeProcessor { CustomerId customerId = new CustomerId(EntityIdFactory.getByEdgeEventTypeAndUuid(type, uuid).getId()); switch (actionType) { case UPDATED: - PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); - PageData pageData; List> futures = new ArrayList<>(); - do { - pageData = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, pageLink); - if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) { - for (Edge edge : pageData.getData()) { - futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, customerId, null)); - } - if (pageData.hasNext()) { - pageLink = pageLink.nextPageLink(); - } - } - } while (pageData != null && pageData.hasNext()); + PageDataIterable edges = new PageDataIterable<>(link -> edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, link), 1024); + for (Edge edge : edges) { + futures.add(saveEdgeEvent(tenantId, edge.getId(), type, actionType, customerId, null)); + } return Futures.transform(Futures.allAsList(futures), voids -> null, dbCallbackExecutorService); case DELETED: EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB())); From adbf708cd771722955bb78a9cd6aea100aef221c Mon Sep 17 00:00:00 2001 From: Vladyslav Date: Fri, 16 Feb 2024 11:14:06 +0200 Subject: [PATCH 252/397] Update entity-subtype-list.component.html --- .../shared/components/entity/entity-subtype-list.component.html | 1 - 1 file changed, 1 deletion(-) diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.html b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.html index 26fb757c42..fa37de3901 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.html +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.html @@ -34,7 +34,6 @@ (blur)="addOnBlur($event)" formControlName="entitySubtype" matAutocompleteOrigin - matChipInputAddOnBlur="false" #origin="matAutocompleteOrigin" [matAutocompleteConnectedTo]="origin" [matAutocomplete]="entitySubtypeAutocomplete" From 9738c94339e58ccbc0f41bdb36bd21ae03de8f54 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Fri, 16 Feb 2024 11:52:47 +0200 Subject: [PATCH 253/397] Add @Lazy annotation to prevent circular dependency --- .../java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java index 136fd0485d..9655a2d8e4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java @@ -26,6 +26,7 @@ import lombok.extern.slf4j.Slf4j; import org.hibernate.exception.ConstraintViolationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.event.TransactionalEventListener; @@ -106,6 +107,7 @@ public class EdgeServiceImpl extends AbstractCachedEntityService Date: Fri, 16 Feb 2024 12:34:12 +0200 Subject: [PATCH 254/397] UI: Update rule node config --- .../static/rulenode/rulenode-core-config.js | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js index 5bfa26ada4..7e161bb6ba 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -1,25 +1,25 @@ -System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/checkbox","@angular/material/input","@angular/material/form-field","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/select","@angular/material/core","@angular/material/slide-toggle","@shared/components/hint-tooltip-icon.component","@core/public-api","@shared/components/js-func.component","@angular/material/button","@angular/material/icon","@angular/material/tooltip","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/chips","@shared/pipe/safe.pipe","@shared/components/entity/entity-type-select.component","@shared/components/entity/entity-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","rxjs","@shared/components/help-popup.component","@shared/components/entity/entity-subtype-list.component","@shared/components/relation/relation-type-autocomplete.component","@home/components/relation/relation-filters.component","@angular/material/expansion","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,f,g,y,x,b,h,v,C,F,k,L,T,I,N,S,q,A,M,E,G,D,w,V,P,R,O,_,B,K,z,U,H,j,$,Q,J,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,fe,ge,ye,xe,be,he,ve,Ce,Fe,ke,Le,Te,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,De,we,Ve,Pe,Re,Oe,_e,Be,Ke,ze,Ue,He,je,$e,Qe,Je,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.EventEmitter,o=e.ViewChild,a=e.forwardRef,i=e.Input,l=e.InjectionToken,s=e.Injectable,m=e.Inject,p=e.Optional,d=e.Directive,u=e.Output,c=e.NgModule},function(e){f=e.RuleNodeConfigurationComponent,g=e.AttributeScope,y=e.telemetryTypeTranslations,x=e.ScriptLanguage,b=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.entitySearchDirectionTranslations,F=e.EntityType,k=e.entityFields,L=e.PageComponent,T=e.coerceBoolean,I=e.MessageType,N=e.messageTypeNames,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,D=e.NotificationType,w=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,U=e.FormGroup},function(e){H=e,j=e.DOCUMENT,$=e.CommonModule},function(e){Q=e},function(e){J=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e.getCurrentAuthState,oe=e,ae=e.isEqual,ie=e.isDefinedAndNotNull,le=e.deepTrim,se=e.isObject,me=e.isNotEmptyStr},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e},function(e){fe=e},function(e){ge=e.ENTER,ye=e.COMMA,xe=e.SEMICOLON},function(e){be=e},function(e){he=e},function(e){ve=e},function(e){Ce=e},function(e){Fe=e.coerceBooleanProperty,ke=e.coerceElement,Le=e.coerceNumberProperty},function(e){Te=e},function(e){Ie=e},function(e){Ne=e},function(e){Se=e},function(e){qe=e.tap,Ae=e.map,Me=e.startWith,Ee=e.mergeMap,Ge=e.share,De=e.takeUntil,we=e.auditTime},function(e){Ve=e},function(e){Pe=e},function(e){Re=e.HomeComponentsModule},function(e){Oe=e.__decorate},function(e){_e=e.Subject,Be=e.takeUntil,Ke=e.of,ze=e.EMPTY,Ue=e.fromEvent},function(e){He=e},function(e){je=e},function(e){$e=e},function(e){Qe=e},function(e){Je=e},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
    ",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
    "}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ct extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===g.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ct),ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ct,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ft extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===x.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===x.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",ft),ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ft,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gt extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.alarmSeverities=Object.keys(b),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[ge,ye,xe],this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==x.TBEL||this.tbelEnabled||(r=x.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===x.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===x.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",gt),gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),gt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gt,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class yt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["entityType"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==F.DEVICE&&t!==F.ASSET?this.createRelationConfigForm.get("entityTypePattern").setValidators([]):this.createRelationConfigForm.get("entityTypePattern").setValidators([O.required,O.pattern(/.*\S.*/)]),this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",yt),yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yt,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bt extends f{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,O.required],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart,O.required]})}}e("DeviceProfileConfigComponent",bt),bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n',dependencies:[{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ht extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}var vt;e("GeneratorConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(vt||(vt={}));const Ct=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer"],[vt.TENANT,"tb.rulenode.originator-tenant"],[vt.RELATED,"tb.rulenode.originator-related"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[vt.ENTITY,"tb.rulenode.originator-entity"]]),Ft=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer-desc"],[vt.TENANT,"tb.rulenode.originator-tenant-desc"],[vt.RELATED,"tb.rulenode.originator-related-entity-desc"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[vt.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),kt=[k.createdTime,k.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},k.firstName,k.lastName,k.email,k.title,k.country,k.state,k.city,k.address,k.address2,k.zip,k.phone,k.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],Lt=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 Tt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Tt||(Tt={}));const It=new Map([[Tt.CIRCLE,"tb.rulenode.perimeter-circle"],[Tt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Nt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Nt||(Nt={}));const St=new Map([[Nt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Nt.SECONDS,"tb.rulenode.time-unit-seconds"],[Nt.MINUTES,"tb.rulenode.time-unit-minutes"],[Nt.HOURS,"tb.rulenode.time-unit-hours"],[Nt.DAYS,"tb.rulenode.time-unit-days"]]);var qt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(qt||(qt={}));const At=new Map([[qt.METER,"tb.rulenode.range-unit-meter"],[qt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[qt.FOOT,"tb.rulenode.range-unit-foot"],[qt.MILE,"tb.rulenode.range-unit-mile"],[qt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Mt;!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"}(Mt||(Mt={}));const Et=new Map([[Mt.ID,"tb.rulenode.entity-details-id"],[Mt.TITLE,"tb.rulenode.entity-details-title"],[Mt.COUNTRY,"tb.rulenode.entity-details-country"],[Mt.STATE,"tb.rulenode.entity-details-state"],[Mt.CITY,"tb.rulenode.entity-details-city"],[Mt.ZIP,"tb.rulenode.entity-details-zip"],[Mt.ADDRESS,"tb.rulenode.entity-details-address"],[Mt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Mt.PHONE,"tb.rulenode.entity-details-phone"],[Mt.EMAIL,"tb.rulenode.entity-details-email"],[Mt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Gt;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Gt||(Gt={}));const Dt=new Map([[Gt.FIRST,"tb.rulenode.first"],[Gt.LAST,"tb.rulenode.last"],[Gt.ALL,"tb.rulenode.all"]]),wt=new Map([[Gt.FIRST,"tb.rulenode.first-mode-hint"],[Gt.LAST,"tb.rulenode.last-mode-hint"],[Gt.ALL,"tb.rulenode.all-mode-hint"]]);var Vt,Pt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Vt||(Vt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(Pt||(Pt={}));const Rt=new Map([[Pt.ATTRIBUTES,"tb.rulenode.attributes"],[Pt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[Pt.FIELDS,"tb.rulenode.fields"]]),Ot=new Map([[Pt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[Pt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[Pt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),_t=new Map([[Vt.ASC,"tb.rulenode.ascending"],[Vt.DESC,"tb.rulenode.descending"]]);var Bt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Bt||(Bt={}));const Kt=new Map([[Bt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Bt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),zt=["anonymous","basic","cert.PEM"],Ut=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Ht=["sas","cert.PEM"],jt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var $t;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}($t||($t={}));const Qt=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],Jt=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 Yt;!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"}(Yt||(Yt={}));const Wt=new Map([[Yt.CUSTOM,{value:Yt.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[Yt.ADD,{value:Yt.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[Yt.SUB,{value:Yt.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[Yt.MULT,{value:Yt.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[Yt.DIV,{value:Yt.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[Yt.SIN,{value:Yt.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.SINH,{value:Yt.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[Yt.COS,{value:Yt.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.COSH,{value:Yt.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[Yt.TAN,{value:Yt.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[Yt.TANH,{value:Yt.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ACOS,{value:Yt.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[Yt.ASIN,{value:Yt.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN,{value:Yt.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN2,{value:Yt.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}],[Yt.EXP,{value:Yt.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[Yt.EXPM1,{value:Yt.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[Yt.SQRT,{value:Yt.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[Yt.CBRT,{value:Yt.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[Yt.GET_EXP,{value:Yt.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[Yt.HYPOT,{value:Yt.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[Yt.LOG,{value:Yt.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG10,{value:Yt.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG1P,{value:Yt.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[Yt.CEIL,{value:Yt.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR,{value:Yt.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR_DIV,{value:Yt.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[Yt.FLOOR_MOD,{value:Yt.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[Yt.ABS,{value:Yt.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[Yt.MIN,{value:Yt.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[Yt.MAX,{value:Yt.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[Yt.POW,{value:Yt.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}],[Yt.SIGNUM,{value:Yt.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[Yt.RAD,{value:Yt.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[Yt.DEG,{value:Yt.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var Zt,Xt,en;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(Zt||(Zt={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(Xt||(Xt={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(en||(en={}));const tn=new Map([[en.DATA,"tb.rulenode.message-to-metadata"],[en.METADATA,"tb.rulenode.metadata-to-message"]]),nn=(new Map([[en.DATA,"tb.rulenode.from-message"],[en.METADATA,"tb.rulenode.from-metadata"]]),new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.metadata"]])),rn=new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.message-metadata"]]),on=new Map([[Zt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[Zt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[Zt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[Zt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[Zt.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),an=new Map([[Xt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[Xt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[Xt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[Xt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),ln=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var sn,mn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(sn||(sn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(mn||(mn={}));const pn=new Map([[sn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[sn.SERVER_SCOPE,"tb.rulenode.server-scope"],[sn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);class dn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.keys(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.keys(qt),this.rangeUnitTranslationMap=At,this.timeUnits=Object.keys(Nt),this.timeUnitsTranslationMap=St}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([])):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required])),t||n!==Tt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",dn),dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.latitude-key-name\n \n \n {{ \'tb.rulenode.latitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.longitude-key-name\n \n \n {{ \'tb.rulenode.longitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.perimeter-type\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n \n tb.rulenode.perimeter-key-name\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.circle-center-latitude\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n tb.rulenode.circle-center-longitude\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.range\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n tb.rulenode.range-units\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
    \n \n tb.rulenode.latitude-key-name\n \n \n {{ \'tb.rulenode.latitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.longitude-key-name\n \n \n {{ \'tb.rulenode.longitude-key-name-required\' | translate }}\n \n \n \n tb.rulenode.perimeter-type\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n \n tb.rulenode.perimeter-key-name\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.circle-center-latitude\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n tb.rulenode.circle-center-longitude\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.range\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n tb.rulenode.range-units\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class un extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",un),un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:un,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:un,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:un,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",cn),cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",fn),fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",gn),gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",yn),yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",xn),xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xn,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",bn),bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bn,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:a((()=>hn)),multi:!0},{provide:K,useExisting:a((()=>hn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Te.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ie.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:a((()=>hn)),multi:!0},{provide:K,useExisting:a((()=>hn)),multi:!0}],template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],required:[{type:i}]}});class vn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:o,args:["attributeChipList"]}]}});class Ln extends L{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=Wt,this.ArgumentType=Zt,this.attributeScopeMap=pn,this.argumentTypeMap=on,this.arguments=Object.values(Zt),this.attributeScope=Object.values(sn),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===Yt.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===Zt.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==Zt.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(ln[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:a((()=>Ln)),multi:!0},{provide:K,useExisting:a((()=>Ln)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ne.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:Ne.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Se.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Se.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Se.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ie.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:a((()=>Ln)),multi:!0},{provide:K,useExisting:a((()=>Ln)),multi:!0}],template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],function:[{type:i}]}});class Tn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(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=[...Wt.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(qe((e=>{let t;t="string"==typeof e&&Yt[e]?Yt[e]:null,this.updateView(t)})),Ae((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=Wt.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Tn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Ve.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Ve.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Pe.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:a((()=>Tn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:i}],disabled:[{type:i}],operationInput:[{type:o,args:["operationInput",{static:!0}]}]}});class In extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=Yt,this.ArgumentTypeResult=Xt,this.argumentTypeResultMap=an,this.attributeScopeMap=pn,this.argumentsResult=Object.values(Xt),this.attributeScopeResult=Object.values(mn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===Yt.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===Xt.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ln,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:Tn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nn{constructor(){this.textAlign="left"}}e("ExampleHintComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:He.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:i}],popupHelpLink:[{type:i}],textAlign:[{type:i}]}});class Sn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new _e,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ae(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(Be(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>Sn)),multi:!0},{provide:K,useExisting:a((()=>Sn)),multi:!0}],ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Oe([T()],Sn.prototype,"disabled",void 0),Oe([T()],Sn.prototype,"uniqueKeyValuePairValidator",void 0),Oe([T()],Sn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:a((()=>Sn)),multi:!0},{provide:K,useExisting:a((()=>Sn)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class qn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.entityType=F,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>qn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:je.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:$e.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:a((()=>qn)),multi:!0}],template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class An extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>An)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Qe.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:a((()=>An)),multi:!0}],template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Mn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(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=[ge,ye,xe],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(I))this.messageTypesList.push({name:N.get(I[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Me(""),Ae((e=>e||"")),Ee((e=>this.fetchMessageTypes(e))),Ge())}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 Ke(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return Ke(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ve.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Ve.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:Ve.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Pe.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],label:[{type:i}],placeholder:[{type:i}],disabled:[{type:i}],chipList:[{type:o,args:["chipList",{static:!1}]}],matAutocomplete:[{type:o,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:o,args:["messageTypeInput",{static:!1}]}]}});class En extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=zt,this.credentialsTypeTranslationsMap=Ut,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){ie(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:a((()=>En)),multi:!0},{provide:K,useExisting:a((()=>En)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Je.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:Je.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:Je.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:Je.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:Je.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ye.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:a((()=>En)),multi:!0},{provide:K,useExisting:a((()=>En)),multi:!0}],template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],disableCertPemCredentials:[{type:i}],passwordFieldRequired:[{type:i}]}});const Gn=new l("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class Dn{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new _e,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Dn,deps:[{token:t.NgZone},{token:j},{token:Gn,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),Dn.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Dn,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Dn,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:m,args:[j]}]},{type:void 0,decorators:[{type:p},{type:m,args:[Gn]}]}]}});class wn{constructor(e,t,n,o){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=o,this.cbOnSuccess=new r,this.cbOnError=new r,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:wn,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:Dn}],target:t.ɵɵFactoryTarget.Directive}),wn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:wn,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:wn,decorators:[{type:d,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:Dn}]},propDecorators:{targetElm:[{type:i,args:["ngxClipboard"]}],container:[{type:i}],cbContent:[{type:i}],cbSuccessMsg:[{type:i}],cbOnSuccess:[{type:u}],cbOnError:[{type:u}]}});class Vn{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Vn,deps:[{token:Dn},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),Vn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:Vn,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Vn,decorators:[{type:d,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:Dn},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class Pn{}Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Pn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,declarations:[wn,Vn],imports:[$],exports:[wn,Vn]}),Pn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,decorators:[{type:c,args:[{imports:[$],declarations:[wn,Vn],exports:[wn,Vn]}]}]});class Rn{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 _e,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(Be(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(Be(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Rn),Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Rn)),multi:!0},{provide:K,useExisting:a((()=>Rn)),multi:!0}],ngImport:t,template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:wn,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Oe([T()],Rn.prototype,"disabled",void 0),Oe([T()],Rn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:a((()=>Rn)),multi:!0},{provide:K,useExisting:a((()=>Rn)),multi:!0}],template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:i}],disabled:[{type:i}],required:[{type:i}]}});class On{constructor(e,t){this.fb=e,this.translate=t,this.translation=nn,this.propagateChange=()=>{},this.destroy$=new _e,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(De(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",On),On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),On.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:On,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:a((()=>On)),multi:!0}],ngImport:t,template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:a((()=>On)),multi:!0}],template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:i}],translation:[{type:i}]}});class _n extends L{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new _e,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ae(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(De(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)ie(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(De(this.destroy$)).subscribe((t=>{const n=Lt.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>_n)),multi:!0},{provide:K,useExisting:a((()=>_n)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Ie.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Oe([T()],_n.prototype,"disabled",void 0),Oe([T()],_n.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:a((()=>_n)),multi:!0},{provide:K,useExisting:a((()=>_n)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:i}],disabled:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],targetKeyPrefix:[{type:i}],selectText:[{type:i}],selectRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class Bn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Fe(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Qe.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0}],template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Kn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new _e,this.separatorKeysCodes=[ge,ye,xe],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(De(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||ie(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0},{provide:K,useExisting:Kn,multi:!0}],ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0},{provide:K,useExisting:Kn,multi:!0}],template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:i}]}});class zn extends L{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new _e,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(De(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0}],template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Un{}e("RulenodeCoreConfigCommonModule",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Un.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Un,declarations:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn],imports:[$,M,Re],exports:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn]}),Un.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,imports:[$,M,Re]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:c,args:[{declarations:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn],imports:[$,M,Re],exports:[Sn,qn,An,Mn,En,Ln,Tn,Rn,hn,On,_n,Bn,Kn,zn,Nn]}]}]});class Hn{}e("RuleNodeCoreConfigActionModule",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Hn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Hn,declarations:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In],imports:[$,M,Re,Un],exports:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In]}),Hn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,imports:[$,M,Re,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:c,args:[{declarations:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In],imports:[$,M,Re,Un],exports:[kn,ct,Cn,bn,un,ut,ft,gt,yt,fn,xt,ht,dn,cn,xn,vn,Fn,bt,yn,gn,In]}]}]});class jn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]]})}prepareInputConfig(e){return{inputValueKey:ie(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:ie(e?.outputValueKey)?e.outputValueKey:null,useCache:!ie(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!ie(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:ie(e?.periodValueKey)?e.periodValueKey:null,round:ie(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!ie(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative}}prepareOutputConfig(e){return le(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class $n extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.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,le(e)}prepareInputConfig(e){let t,n;return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Qn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return se(e)&&(e.attributesControl={clientAttributeNames:ie(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ie(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ie(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ie(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:ie(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!ie(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Qn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:qn,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Kn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Jn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Mt))this.predefinedValues.push({value:Mt[e],name:this.translate.instant(Et.get(Mt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=ie(e?.addToMetadata)?e.addToMetadata?en.METADATA:en.DATA:e?.fetchTo?e.fetchTo:en.DATA,{detailsList:ie(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Yn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Gt,this.samplingOrders=Object.values(Vt),this.samplingOrdersTranslate=_t,this.timeUnits=Object.values(Nt),this.timeUnitsTranslationMap=St,this.deduplicationStrategiesHintTranslations=wt,this.headerOptions=[],this.timeUnitMap={[Nt.MILLISECONDS]:1,[Nt.SECONDS]:1e3,[Nt.MINUTES]:6e4,[Nt.HOURS]:36e5,[Nt.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 Dt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Dt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,le(e)}prepareInputConfig(e){return se(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:ie(e?.aggregation)?e.aggregation:E.NONE,fetchMode:ie(e?.fetchMode)?e.fetchMode:Gt.FIRST,orderBy:ie(e?.orderBy)?e.orderBy:Vt.ASC,limit:ie(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!ie(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:ie(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:ie(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Nt.MINUTES,endInterval:ie(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:ie(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Nt.MINUTES},startIntervalPattern:ie(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:ie(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Gt.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Gt.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:He.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Wn extends f{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 se(e)&&(e.attributesControl={clientAttributeNames:ie(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ie(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ie(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ie(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ie(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA,tellFailureIfAbsent:!!ie(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:ie(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Kn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Zn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of kt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return le(e)}prepareInputConfig(e){return{dataMapping:ie(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:ie(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:_n,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Xn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=Pt,this.msgMetadataLabelTranslations=Ot,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(kt))this.originatorFields.push({value:kt[e].value,name:this.translate.instant(kt[e].name)});for(const e of Rt.keys())this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===Pt.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,le(e)}prepareInputConfig(e){let t,n,r={[k.name.value]:`relatedEntity${this.translate.instant(k.name.name)}`},o={serialNumber:"sn"};return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,t===Pt.FIELDS?r=n:o=n,{relationsQuery:ie(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:An,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:_n,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class er extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=ie(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ie(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ie(e?.attrMapping)?e.attrMapping:ie(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class tr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:ie(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class nr{}e("RulenodeCoreConfigEnrichmentModule",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),nr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:nr,declarations:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr],imports:[$,M,Un],exports:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr]}),nr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:c,args:[{declarations:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr],imports:[$,M,Un],exports:[$n,Jn,Qn,Wn,Zn,Yn,Xn,er,jn,tr]}]}]});class rr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Ht,this.azureIotHubCredentialsTypeTranslationsMap=jt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Je.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:Je.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:Je.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:Je.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:Je.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ye.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class or extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=Qt,this.ToByteStandartCharsetTypeTranslationMap=Jt}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ar extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&me(e.clientId))},[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){me(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:En,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ir extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=D,this.entityType=F}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ir,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
    \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ye.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys($t)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],useRedisQueueForMsgPersistence:[!!e&&e.useRedisQueueForMsgPersistence,[]],trimQueue:[!!e&&e.trimQueue,[]],maxQueueSize:[e?e.maxQueueSize:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","useRedisQueueForMsgPersistence","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("useRedisQueueForMsgPersistence").value,r=this.restApiCallConfigForm.get("enableProxy").value,o=this.restApiCallConfigForm.get("useSystemProxyProperties").value;r&&!o?(this.restApiCallConfigForm.get("proxyHost").setValidators(r?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(r?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),n?this.restApiCallConfigForm.get("maxQueueSize").setValidators([O.min(0)]):this.restApiCallConfigForm.get("maxQueueSize").setValidators([]),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("maxQueueSize").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:En,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class dr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(w),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Bt,this.sqsQueueTypes=Object.keys(Bt),this.sqsQueueTypeTranslationsMap=Kt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:hn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr{}e("RulenodeCoreConfigExternalModule",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),gr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:gr,declarations:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur],imports:[$,M,Re,Un],exports:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur]}),gr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,imports:[$,M,Re,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:c,args:[{declarations:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur],imports:[$,M,Re,Un],exports:[cr,fr,lr,or,ar,ir,sr,mr,pr,rr,dr,ur]}]}]});class yr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ie(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:zn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class xr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ie(e?.messageNames)?e.messageNames:[],metadataNames:ie(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!ie(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:ie(e?.messageNames)?e.messageNames:[],metadataNames:ie(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class br extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=C}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ie(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ie(e?.direction)?e.direction:null,entityType:ie(e?.entityType)?e.entityType:null,entityId:ie(e?.entityId)?e.entityId:null,relationType:ie(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:$e.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.values(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.values(qt),this.rangeUnitTranslationMap=At,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ie(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ie(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ie(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ie(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ie(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ie(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ie(e?.centerLongitude)?e.centerLongitude:null,range:ie(e?.range)?e.range:null,rangeUnit:ie(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ie(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class vr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ie(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Mn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.TENANT,F.CUSTOMER,F.USER,F.DASHBOARD,F.RULE_CHAIN,F.RULE_NODE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ie(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ie(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ie(e?.jsScript)?e.jsScript:null,tbelScript:ie(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class kr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ie(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ie(e?.jsScript)?e.jsScript:null,tbelScript:ie(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Lr{}e("RuleNodeCoreConfigFilterModule",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Lr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Lr,declarations:[xr,br,hr,vr,Cr,Fr,kr,yr],imports:[$,M,Un],exports:[xr,br,hr,vr,Cr,Fr,kr,yr]}),Lr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:c,args:[{declarations:[xr,br,hr,vr,Cr,Fr,kr,yr],imports:[$,M,Un],exports:[xr,br,hr,vr,Cr,Fr,kr,yr]}]}]});class Tr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=vt,this.originatorSources=Object.keys(vt),this.originatorSourceTranslationMap=Ct,this.originatorSourceDescTranslationMap=Ft,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.USER,F.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===vt.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===vt.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Ne.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Ne.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Ir extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.FormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - const Nr=mt({passive:!0});class Sr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return ze;const t=ke(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new _e,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Nr),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Nr)}}),r}stopMonitoring(e){const t=ke(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Sr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Sr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Sr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Sr,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class qr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new r}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:qr,deps:[{token:t.ElementRef},{token:Sr}],target:t.ɵɵFactoryTarget.Directive}),qr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:qr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:qr,decorators:[{type:d,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Sr}]},propDecorators:{cdkAutofill:[{type:u}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Ar{get minRows(){return this._minRows}set minRows(e){this._minRows=Le(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=Le(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Fe(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new _e,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();Ue(e,"resize").pipe(we(16),De(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Ar,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Ar.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Ar,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Ar,decorators:[{type:d,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:p},{type:m,args:[j]}]}]},propDecorators:{minRows:[{type:i,args:["cdkAutosizeMinRows"]}],maxRows:[{type:i,args:["cdkAutosizeMaxRows"]}],enabled:[{type:i,args:["cdkTextareaAutosize"]}],placeholder:[{type:i}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Mr{}Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Mr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,declarations:[qr,Ar],exports:[qr,Ar]}),Mr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,decorators:[{type:c,args:[{declarations:[qr,Ar],exports:[qr,Ar]}]}]});class Er extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:ie(e?.fromTemplate)?e.fromTemplate:null,toTemplate:ie(e?.toTemplate)?e.toTemplate:null,ccTemplate:ie(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:ie(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:ie(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:ie(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:ie(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:ie(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Er),Er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Er,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:He.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Ar,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Ne.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Ne.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Gr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=tn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.copyFrom?en.METADATA:en.DATA:ie(e?.copyFrom)?e.copyFrom:en.DATA,{keys:ie(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Gr),Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Dr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=rn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ie(e?.renameIn)?e?.renameIn:en.DATA,{renameKeysMapping:ie(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Dr),Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dr,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Sn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dr,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class wr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",wr),wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),wr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wr,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Vr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=nn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=ie(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ie(e?.deleteFrom)?e?.deleteFrom:en.DATA,{keys:ie(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Vr),Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vr,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Ze.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:On,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Gt,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Dt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[ie(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[ie(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[ie(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[ie(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[ie(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Je.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:Je.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:Je.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Xe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:et.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Rn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:Nn,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Rr{}e("RulenodeCoreConfigTransformModule",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Rr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Rr,declarations:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr],imports:[$,M,Un],exports:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr]}),Rr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:c,args:[{declarations:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr],imports:[$,M,Un],exports:[Tr,Ir,Er,Gr,Dr,wr,Vr,Pr]}]}]});class Or extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=F}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class _r extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Br{}e("RuleNodeCoreConfigFlowModule",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Br,declarations:[Or,_r],imports:[$,M,Un],exports:[Or,_r]}),Br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,imports:[$,M,Un]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:c,args:[{declarations:[Or,_r],imports:[$,M,Un],exports:[Or,_r]}]}]});class Kr{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 not exists","create-entity-if-not-exists-hint":"Create a new entity set above if it does not exist.","entity-name-pattern":"Name pattern","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 name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","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","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":"Timeseries keys","timeseries-keys-required":"At least one timeseries key should be selected.","add-timeseries-key":"Add timeseries key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-to-specific-entity":"Delete relation to specific entity","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"use-redis-queue":"Use redis queue for message persistence","ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","trim-redis-queue":"Trim redis queue","redis-queue-max-size":"Redis queue max size","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.","persist-alarm-rules":"Persist state of alarm rules","fetch-alarm-rules":"Fetch state of alarm rules","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","use-server-ts":"Use server ts","use-server-ts-hint":"Enable this setting to use the timestamp of the 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.","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.","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":"timeseries 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 timeseries from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch timeseries 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 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."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),Kr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Kr,declarations:[dt],imports:[$,M],exports:[Hn,Lr,nr,gr,Rr,Br,dt]}),Kr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,imports:[$,M,Hn,Lr,nr,gr,Rr,Br]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:c,args:[{declarations:[dt],imports:[$,M],exports:[Hn,Lr,nr,gr,Rr,Br,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map +System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/checkbox","@angular/material/input","@angular/material/form-field","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/select","@angular/material/core","@angular/material/slide-toggle","@shared/components/hint-tooltip-icon.component","@core/public-api","@shared/components/js-func.component","@angular/material/button","@angular/material/icon","@angular/material/tooltip","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/chips","@shared/pipe/safe.pipe","@shared/components/entity/entity-type-select.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","rxjs","@shared/components/help-popup.component","@shared/components/entity/entity-subtype-list.component","@shared/components/relation/relation-type-autocomplete.component","@home/components/relation/relation-filters.component","@angular/material/expansion","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,f,g,y,x,b,h,v,C,F,k,L,T,I,N,S,q,A,M,E,G,D,w,V,P,R,O,_,B,K,z,U,H,j,$,Q,J,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,fe,ge,ye,xe,be,he,ve,Ce,Fe,ke,Le,Te,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,De,we,Ve,Pe,Re,Oe,_e,Be,Ke,ze,Ue,He,je,$e,Qe,Je,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.EventEmitter,o=e.ViewChild,a=e.forwardRef,i=e.Input,l=e.InjectionToken,s=e.Injectable,m=e.Inject,p=e.Optional,d=e.Directive,u=e.Output,c=e.NgModule},function(e){f=e.RuleNodeConfigurationComponent,g=e.AttributeScope,y=e.telemetryTypeTranslations,x=e.ScriptLanguage,b=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.entitySearchDirectionTranslations,F=e.EntityType,k=e.entityFields,L=e.PageComponent,T=e.messageTypeNames,I=e.MessageType,N=e.coerceBoolean,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,D=e.NotificationType,w=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,U=e.FormGroup},function(e){H=e,j=e.DOCUMENT,$=e.CommonModule},function(e){Q=e},function(e){J=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e.getCurrentAuthState,oe=e,ae=e.isDefinedAndNotNull,ie=e.isEqual,le=e.deepTrim,se=e.isObject,me=e.isNotEmptyStr},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e},function(e){fe=e},function(e){ge=e.ENTER,ye=e.COMMA,xe=e.SEMICOLON},function(e){be=e},function(e){he=e},function(e){ve=e},function(e){Ce=e},function(e){Fe=e},function(e){ke=e},function(e){Le=e.coerceBooleanProperty,Te=e.coerceElement,Ie=e.coerceNumberProperty},function(e){Ne=e},function(e){Se=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e.tap,Ee=e.map,Ge=e.startWith,De=e.mergeMap,we=e.share,Ve=e.takeUntil,Pe=e.auditTime},function(e){Re=e},function(e){Oe=e},function(e){_e=e.HomeComponentsModule},function(e){Be=e.__decorate},function(e){Ke=e.Subject,ze=e.takeUntil,Ue=e.of,He=e.EMPTY,je=e.fromEvent},function(e){$e=e},function(e){Qe=e},function(e){Je=e},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
    ",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
    "}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ct extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===g.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ct),ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ct,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ft extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===x.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===x.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",ft),ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ft,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ft,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gt extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.alarmSeverities=Object.keys(b),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[ge,ye,xe],this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==x.TBEL||this.tbelEnabled||(r=x.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===x.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===x.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===x.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===x.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",gt),gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),gt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gt,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gt,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
    \n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
    \n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
    \n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class yt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["entityType"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==F.DEVICE&&t!==F.ASSET?this.createRelationConfigForm.get("entityTypePattern").setValidators([]):this.createRelationConfigForm.get("entityTypePattern").setValidators([O.required,O.pattern(/.*\S.*/)]),this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",yt),yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yt,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yt,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-type-pattern\n \n \n {{ \'tb.rulenode.entity-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
    tb.rulenode.create-entity-if-not-exists-hint
    \n
    \n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
    tb.rulenode.remove-current-relations-hint
    \n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
    tb.rulenode.change-originator-to-related-entity-hint
    \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xt extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.entityType=F}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],entityCacheExpiration:[e?e.entityCacheExpiration:null,[O.required,O.min(0)]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
    \n \n {{ \'tb.rulenode.delete-relation-to-specific-entity\' | translate }}\n \n
    tb.rulenode.delete-relation-hint
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.relation-type-pattern\n \n \n {{ \'tb.rulenode.relation-type-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.entity-cache-expiration\n \n \n {{ \'tb.rulenode.entity-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.entity-cache-expiration-range\' | translate }}\n \n tb.rulenode.entity-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bt extends f{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,O.required],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart,O.required]})}}e("DeviceProfileConfigComponent",bt),bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n',dependencies:[{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
    \n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ht extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}var vt;e("GeneratorConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
    \n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
    \n \n \n \n
    \n\n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(vt||(vt={}));const Ct=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer"],[vt.TENANT,"tb.rulenode.originator-tenant"],[vt.RELATED,"tb.rulenode.originator-related"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[vt.ENTITY,"tb.rulenode.originator-entity"]]),Ft=new Map([[vt.CUSTOMER,"tb.rulenode.originator-customer-desc"],[vt.TENANT,"tb.rulenode.originator-tenant-desc"],[vt.RELATED,"tb.rulenode.originator-related-entity-desc"],[vt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[vt.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),kt=[k.createdTime,k.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},k.firstName,k.lastName,k.email,k.title,k.country,k.state,k.city,k.address,k.address2,k.zip,k.phone,k.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],Lt=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 Tt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Tt||(Tt={}));const It=new Map([[Tt.CIRCLE,"tb.rulenode.perimeter-circle"],[Tt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Nt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Nt||(Nt={}));const St=new Map([[Nt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Nt.SECONDS,"tb.rulenode.time-unit-seconds"],[Nt.MINUTES,"tb.rulenode.time-unit-minutes"],[Nt.HOURS,"tb.rulenode.time-unit-hours"],[Nt.DAYS,"tb.rulenode.time-unit-days"]]);var qt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(qt||(qt={}));const At=new Map([[qt.METER,"tb.rulenode.range-unit-meter"],[qt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[qt.FOOT,"tb.rulenode.range-unit-foot"],[qt.MILE,"tb.rulenode.range-unit-mile"],[qt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Mt;!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"}(Mt||(Mt={}));const Et=new Map([[Mt.ID,"tb.rulenode.entity-details-id"],[Mt.TITLE,"tb.rulenode.entity-details-title"],[Mt.COUNTRY,"tb.rulenode.entity-details-country"],[Mt.STATE,"tb.rulenode.entity-details-state"],[Mt.CITY,"tb.rulenode.entity-details-city"],[Mt.ZIP,"tb.rulenode.entity-details-zip"],[Mt.ADDRESS,"tb.rulenode.entity-details-address"],[Mt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Mt.PHONE,"tb.rulenode.entity-details-phone"],[Mt.EMAIL,"tb.rulenode.entity-details-email"],[Mt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Gt;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Gt||(Gt={}));const Dt=new Map([[Gt.FIRST,"tb.rulenode.first"],[Gt.LAST,"tb.rulenode.last"],[Gt.ALL,"tb.rulenode.all"]]),wt=new Map([[Gt.FIRST,"tb.rulenode.first-mode-hint"],[Gt.LAST,"tb.rulenode.last-mode-hint"],[Gt.ALL,"tb.rulenode.all-mode-hint"]]);var Vt,Pt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Vt||(Vt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(Pt||(Pt={}));const Rt=new Map([[Pt.ATTRIBUTES,"tb.rulenode.attributes"],[Pt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[Pt.FIELDS,"tb.rulenode.fields"]]),Ot=new Map([[Pt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[Pt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[Pt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),_t=new Map([[Vt.ASC,"tb.rulenode.ascending"],[Vt.DESC,"tb.rulenode.descending"]]);var Bt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Bt||(Bt={}));const Kt=new Map([[Bt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Bt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),zt=["anonymous","basic","cert.PEM"],Ut=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Ht=["sas","cert.PEM"],jt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var $t;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}($t||($t={}));const Qt=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],Jt=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 Yt;!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"}(Yt||(Yt={}));const Wt=new Map([[Yt.CUSTOM,{value:Yt.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[Yt.ADD,{value:Yt.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[Yt.SUB,{value:Yt.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[Yt.MULT,{value:Yt.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[Yt.DIV,{value:Yt.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[Yt.SIN,{value:Yt.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.SINH,{value:Yt.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[Yt.COS,{value:Yt.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[Yt.COSH,{value:Yt.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[Yt.TAN,{value:Yt.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[Yt.TANH,{value:Yt.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ACOS,{value:Yt.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[Yt.ASIN,{value:Yt.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN,{value:Yt.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[Yt.ATAN2,{value:Yt.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}],[Yt.EXP,{value:Yt.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[Yt.EXPM1,{value:Yt.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[Yt.SQRT,{value:Yt.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[Yt.CBRT,{value:Yt.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[Yt.GET_EXP,{value:Yt.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[Yt.HYPOT,{value:Yt.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[Yt.LOG,{value:Yt.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG10,{value:Yt.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[Yt.LOG1P,{value:Yt.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[Yt.CEIL,{value:Yt.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR,{value:Yt.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[Yt.FLOOR_DIV,{value:Yt.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[Yt.FLOOR_MOD,{value:Yt.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[Yt.ABS,{value:Yt.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[Yt.MIN,{value:Yt.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[Yt.MAX,{value:Yt.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[Yt.POW,{value:Yt.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}],[Yt.SIGNUM,{value:Yt.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[Yt.RAD,{value:Yt.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[Yt.DEG,{value:Yt.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var Zt,Xt,en;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(Zt||(Zt={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(Xt||(Xt={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(en||(en={}));const tn=new Map([[en.DATA,"tb.rulenode.message-to-metadata"],[en.METADATA,"tb.rulenode.metadata-to-message"]]),nn=(new Map([[en.DATA,"tb.rulenode.from-message"],[en.METADATA,"tb.rulenode.from-metadata"]]),new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.metadata"]])),rn=new Map([[en.DATA,"tb.rulenode.message"],[en.METADATA,"tb.rulenode.message-metadata"]]),on=new Map([[Zt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[Zt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[Zt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[Zt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[Zt.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),an=new Map([[Xt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[Xt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[Xt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[Xt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),ln=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var sn,mn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(sn||(sn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(mn||(mn={}));const pn=new Map([[sn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[sn.SERVER_SCOPE,"tb.rulenode.server-scope"],[sn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var dn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(dn||(dn={}));const un=new Map([[dn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[dn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class cn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.keys(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.keys(qt),this.rangeUnitTranslationMap=At,this.presenceMonitoringStrategies=un,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Nt),this.timeUnitsTranslationMap=St,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[O.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",cn),cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n
    \n
    \n
    {{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
    \n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
    \n
    {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
    \n
    \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n
    \n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n
    \n
    \n
    {{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
    \n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
    \n
    {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
    \n
    \n
    \n
    \n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fn extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",fn),fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class gn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",gn),gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
    \n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",yn),yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
    \n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",xn),xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class bn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",bn),bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:bn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:bn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
    \n \n attribute.attributes-scope\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
    \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
    \n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Cn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:a((()=>Cn)),multi:!0},{provide:K,useExisting:a((()=>Cn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Se.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:a((()=>Cn)),multi:!0},{provide:K,useExisting:a((()=>Cn)),multi:!0}],template:'
    \n
    \n {{ keyText | translate }}\n {{ valText | translate }}\n \n
    \n
    \n
    \n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
    \n
    \n
    \n \n
    \n \n
    \n
    \n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],required:[{type:i}]}});class Fn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
    \n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
    \n \n tb.rulenode.default-ttl\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
    tb.rulenode.use-server-ts-hint
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ln extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],customerCacheExpiration:[e?e.customerCacheExpiration:null,[O.required,O.min(0)]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
    \n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.customer-cache-expiration\n \n \n {{ \'tb.rulenode.customer-cache-expiration-required\' | translate }}\n \n \n {{ \'tb.rulenode.customer-cache-expiration-range\' | translate }}\n \n tb.rulenode.customer-cache-expiration-hint\n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=g,this.attributeScopes=Object.keys(g),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==g.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
    \n \n {{ \'attribute.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
    tb.rulenode.send-attributes-deleted-notification-hint
    \n
    \n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
    tb.rulenode.notify-device-on-delete-hint
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:o,args:["attributeChipList"]}]}});class In extends L{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=Wt,this.ArgumentType=Zt,this.attributeScopeMap=pn,this.argumentTypeMap=on,this.arguments=Object.values(Zt),this.attributeScope=Object.values(sn),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===Yt.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===Zt.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==Zt.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(ln[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:a((()=>In)),multi:!0},{provide:K,useExisting:a((()=>In)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:qe.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:qe.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Ae.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Ae.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Ae.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Se.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:a((()=>In)),multi:!0},{provide:K,useExisting:a((()=>In)),multi:!0}],template:'
    \n\n
    \n \n \n
    \n \n
    \n {{argumentControl.get(\'name\').value}}.\n
    \n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
    \n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n tb.rulenode.no-arguments-prompt\n
    \n \n
    \n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],function:[{type:i}]}});class Nn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(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=[...Wt.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(Me((e=>{let t;t="string"==typeof e&&Yt[e]?Yt[e]:null,this.updateView(t)})),Ee((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=Wt.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Nn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Re.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Re.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Oe.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:a((()=>Nn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:i}],disabled:[{type:i}],operationInput:[{type:o,args:["operationInput",{static:!0}]}]}});class Sn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=Yt,this.ArgumentTypeResult=Xt,this.argumentTypeResultMap=an,this.attributeScopeMap=pn,this.argumentsResult=Object.values(Xt),this.attributeScopeResult=Object.values(mn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===Yt.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===Xt.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:In,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:Nn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
    \n \n \n
    \n tb.rulenode.argument-tile\n \n \n
    \n
    \n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
    \n
    \n tb.rulenode.result-title\n
    \n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
    \n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
    \n
    \n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
    \n
    \n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
    \n
    \n
    \n
    \n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class qn extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=T,this.eventOptions=[I.CONNECT_EVENT,I.ACTIVITY_EVENT,I.DISCONNECT_EVENT,I.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:ae(e?.event)?e.event:I.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[O.required]]})}}e("DeviceStateConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-action-node-device-state-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-action-node-device-state-config",template:'
    \n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class An{constructor(){this.textAlign="left"}}e("ExampleHintComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
    \n
    \n
    \n
    \n
    \n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:i}],popupHelpLink:[{type:i}],textAlign:[{type:i}]}});class Mn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new Ke,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ie(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(ze(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0},{provide:K,useExisting:a((()=>Mn)),multi:!0}],ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([N()],Mn.prototype,"disabled",void 0),Be([N()],Mn.prototype,"uniqueKeyValuePairValidator",void 0),Be([N()],Mn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:a((()=>Mn)),multi:!0},{provide:K,useExisting:a((()=>Mn)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n {{ requiredText }}\n
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
    \n
    \n
    \n
    \n
    \n
    {{ keyText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],uniqueKeyValuePairValidator:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],keyText:[{type:i}],keyRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class En extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.entityType=F,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>En)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Qe.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:Je.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:a((()=>En)),multi:!0}],template:'
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n \n \n help\n \n
    \n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Gn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Gn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Ye.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:a((()=>Gn)),multi:!0}],template:'
    \n
    tb.rulenode.relations-query
    \n
    \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
    \n
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n
    \n
    \n
    relation.relation-filters
    \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Dn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(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=[ge,ye,xe],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(I))this.messageTypesList.push({name:T.get(I[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Ge(""),Ee((e=>e||"")),De((e=>this.fetchMessageTypes(e))),we())}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 Ue(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return Ue(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:a((()=>Dn)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Re.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:Re.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:Re.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:be.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:be.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:be.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:be.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Oe.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:a((()=>Dn)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
    \n
    \n tb.rulenode.no-message-types-found\n
    \n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
    \n
    \n
    \n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],label:[{type:i}],placeholder:[{type:i}],disabled:[{type:i}],chipList:[{type:o,args:["chipList",{static:!1}]}],matAutocomplete:[{type:o,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:o,args:["messageTypeInput",{static:!1}]}]}});class wn extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=zt,this.credentialsTypeTranslationsMap=Ut,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){ae(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",wn),wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:a((()=>wn)),multi:!0},{provide:K,useExisting:a((()=>wn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:We.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:We.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:a((()=>wn)),multi:!0},{provide:K,useExisting:a((()=>wn)),multi:!0}],template:'
    \n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
    {{ \'tb.rulenode.credentials-pem-hint\' | translate }}
    \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
    \n
    \n
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:i}],disableCertPemCredentials:[{type:i}],passwordFieldRequired:[{type:i}]}});const Vn=new l("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class Pn{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new Ke,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,deps:[{token:t.NgZone},{token:j},{token:Vn,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),Pn.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Pn,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:m,args:[j]}]},{type:void 0,decorators:[{type:p},{type:m,args:[Vn]}]}]}});class Rn{constructor(e,t,n,o){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=o,this.cbOnSuccess=new r,this.cbOnError=new r,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Rn,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:Pn}],target:t.ɵɵFactoryTarget.Directive}),Rn.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:Rn,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:Rn,decorators:[{type:d,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:Pn}]},propDecorators:{targetElm:[{type:i,args:["ngxClipboard"]}],container:[{type:i}],cbContent:[{type:i}],cbSuccessMsg:[{type:i}],cbOnSuccess:[{type:u}],cbOnError:[{type:u}]}});class On{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,deps:[{token:Pn},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),On.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:On,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:On,decorators:[{type:d,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:Pn},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class _n{}_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,deps:[],target:t.ɵɵFactoryTarget.NgModule}),_n.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,declarations:[Rn,On],imports:[$],exports:[Rn,On]}),_n.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:_n,decorators:[{type:c,args:[{imports:[$],declarations:[Rn,On],exports:[Rn,On]}]}]});class Bn{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 Ke,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(ze(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(ze(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0},{provide:K,useExisting:a((()=>Bn)),multi:!0}],ngImport:t,template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Rn,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([N()],Bn.prototype,"disabled",void 0),Be([N()],Bn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:a((()=>Bn)),multi:!0},{provide:K,useExisting:a((()=>Bn)),multi:!0}],template:'
    \n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
    \n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:i}],disabled:[{type:i}],required:[{type:i}]}});class Kn{constructor(e,t){this.fb=e,this.translate=t,this.translation=nn,this.propagateChange=()=>{},this.destroy$=new Ke,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0}],ngImport:t,template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:a((()=>Kn)),multi:!0}],template:'
    \n
    {{ labelText }}
    \n \n {{ option.name }}\n \n
    \n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:i}],translation:[{type:i}]}});class zn extends L{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new Ke,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ie(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(Ve(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)ae(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(Ve(this.destroy$)).subscribe((t=>{const n=Lt.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:a((()=>zn)),multi:!0},{provide:K,useExisting:a((()=>zn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Se.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:H.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Be([N()],zn.prototype,"disabled",void 0),Be([N()],zn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:a((()=>zn)),multi:!0},{provide:K,useExisting:a((()=>zn)),multi:!0}],template:'
    \n
    \n
    {{ labelText }}
    \n
    \n tb.rulenode.map-fields-required\n
    \n
    \n {{ requiredText }}\n
    \n
    \n
    \n
    \n
    \n
    {{ selectText }}
    \n
    {{ valText }}
    \n
    \n
    \n
    \n
    \n \n \n \n {{option.name}}\n \n \n \n \n \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n
    \n \n
    \n \n
    \n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:i}],disabled:[{type:i}],labelText:[{type:i}],requiredText:[{type:i}],targetKeyPrefix:[{type:i}],selectText:[{type:i}],selectRequiredText:[{type:i}],valText:[{type:i}],valRequiredText:[{type:i}],hintText:[{type:i}],popupHelpLink:[{type:i}],required:[{type:i}]}});class Un extends L{get required(){return this.requiredValue}set required(e){this.requiredValue=Le(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=C,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:a((()=>Un)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ye.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:a((()=>Un)),multi:!0}],template:'
    \n \n {{ \'alias.last-level-relation\' | translate }}\n \n
    \n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
    \n
    relation.relation-filters
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:i}],required:[{type:i}]}});class Hn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new Ke,this.separatorKeysCodes=[ge,ye,xe],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||ae(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:a((()=>Hn)),multi:!0},{provide:K,useExisting:Hn,multi:!0}],ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:a((()=>Hn)),multi:!0},{provide:K,useExisting:Hn,multi:!0}],template:'
    \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
    \n
    \n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:i}]}});class jn extends L{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new Ke,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(Ve(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>jn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:be.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:be.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:a((()=>jn)),multi:!0}],template:'
    \n \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
    \n
    \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
    \n
    \n
    \n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class $n{}e("RulenodeCoreConfigCommonModule",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[],target:t.ɵɵFactoryTarget.NgModule}),$n.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$n,declarations:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An],imports:[$,M,_e],exports:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An]}),$n.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,imports:[$,M,_e]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:c,args:[{declarations:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An],imports:[$,M,_e],exports:[Mn,En,Gn,Dn,wn,In,Nn,Bn,Cn,Kn,zn,Un,Hn,jn,An]}]}]});class Qn{}e("RuleNodeCoreConfigActionModule",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Qn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Qn,declarations:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn],imports:[$,M,_e,$n],exports:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn]}),Qn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,imports:[$,M,_e,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:c,args:[{declarations:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn],imports:[$,M,_e,$n],exports:[Tn,ct,kn,vn,fn,ut,ft,gt,yt,yn,xt,ht,cn,gn,hn,Fn,Ln,bt,bn,xn,Sn,qn]}]}]});class Jn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]]})}prepareInputConfig(e){return{inputValueKey:ae(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:ae(e?.outputValueKey)?e.outputValueKey:null,useCache:!ae(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!ae(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:ae(e?.periodValueKey)?e.periodValueKey:null,round:ae(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!ae(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative}}prepareOutputConfig(e){return le(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
    \n
    \n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
    \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
    \n
    \n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
    \n
    \n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
    \n
    \n
    \n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
    \n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
    \n
    \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Yn extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.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,le(e)}prepareInputConfig(e){let t,n;return t=ae(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ae(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ae(e?.attrMapping)?e.attrMapping:ae(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-customers
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Wn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return se(e)&&(e.attributesControl={clientAttributeNames:ae(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ae(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ae(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ae(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ae(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:ae(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!ae(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:En,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
    \n
    \n
    tb.rulenode.device-relations-query
    \n \n \n
    \n
    \n
    \n
    tb.rulenode.related-device-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Zn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Mt))this.predefinedValues.push({value:Mt[e],name:this.translate.instant(Et.get(Mt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=ae(e?.addToMetadata)?e.addToMetadata?en.METADATA:en.DATA:e?.fetchTo?e.fetchTo:en.DATA,{detailsList:ae(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
    \n \n \n help\n \n \n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Xn extends f{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ge,ye,xe],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Gt,this.samplingOrders=Object.values(Vt),this.samplingOrdersTranslate=_t,this.timeUnits=Object.values(Nt),this.timeUnitsTranslationMap=St,this.deduplicationStrategiesHintTranslations=wt,this.headerOptions=[],this.timeUnitMap={[Nt.MILLISECONDS]:1,[Nt.SECONDS]:1e3,[Nt.MINUTES]:6e4,[Nt.HOURS]:36e5,[Nt.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 Dt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Dt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,le(e)}prepareInputConfig(e){return se(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:ae(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:ae(e?.aggregation)?e.aggregation:E.NONE,fetchMode:ae(e?.fetchMode)?e.fetchMode:Gt.FIRST,orderBy:ae(e?.orderBy)?e.orderBy:Vt.ASC,limit:ae(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!ae(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:ae(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:ae(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Nt.MINUTES,endInterval:ae(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:ae(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Nt.MINUTES},startIntervalPattern:ae(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:ae(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Gt.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Gt.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
    \n \n
    \n help\n \n
    \n
    \n
    tb.rulenode.fetch-interval
    \n
    \n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
    \n
    \n
    \n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
    \n
    \n error_outline\n
    \n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
    \n
    \n
    \n \n
    \n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
    \n
    \n
    \n
    \n
    tb.rulenode.fetch-strategy
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
    \n
    \n
    \n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
    \n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
    \n
    \n
    \n
    \n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class er extends f{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 se(e)&&(e.attributesControl={clientAttributeNames:ae(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ae(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ae(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ae(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ae(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA,tellFailureIfAbsent:!!ae(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:ae(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
    \n
    \n
    \n
    tb.rulenode.originator-attributes
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n \n \n \n
    \n
    \n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class tr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of kt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return le(e)}prepareInputConfig(e){return{dataMapping:ae(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:ae(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n',dependencies:[{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:zn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
    \n \n \n \n \n
    \n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class nr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=Pt,this.msgMetadataLabelTranslations=Ot,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(kt))this.originatorFields.push({value:kt[e].value,name:this.translate.instant(kt[e].name)});for(const e of Rt.keys())this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===Pt.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,le(e)}prepareInputConfig(e){let t,n,r={[k.name.value]:`relatedEntity${this.translate.instant(k.name.name)}`},o={serialNumber:"sn"};return t=ae(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ae(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ae(e?.attrMapping)?e.attrMapping:ae(e?.dataMapping)?e.dataMapping:null,t===Pt.FIELDS?r=n:o=n,{relationsQuery:ae(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===Pt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Gn,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:zn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
    \n \n \n
    \n
    tb.rulenode.data-to-fetch
    \n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class rr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Pt;for(const e of Rt.keys())e!==Pt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Rt.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=ae(e?.telemetry)?e.telemetry?Pt.LATEST_TELEMETRY:Pt.ATTRIBUTES:ae(e?.dataToFetch)?e.dataToFetch:Pt.ATTRIBUTES,n=ae(e?.attrMapping)?e.attrMapping:ae(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===Pt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
    \n
    tb.rulenode.mapping-of-tenant
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class or extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:ae(e?.fetchTo)?e.fetchTo:en.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class ar{}e("RulenodeCoreConfigEnrichmentModule",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[],target:t.ɵɵFactoryTarget.NgModule}),ar.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:ar,declarations:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or],imports:[$,M,$n],exports:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or]}),ar.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:c,args:[{declarations:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or],imports:[$,M,$n],exports:[Yn,Zn,Wn,er,tr,Xn,nr,rr,Jn,or]}]}]});class ir extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Ht,this.azureIotHubCredentialsTypeTranslationsMap=jt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ir,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:H.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:H.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:We.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:We.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
    \n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
    \n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
    \n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
    \n
    \n
    \n
    \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=Qt,this.ToByteStandartCharsetTypeTranslationMap=Jt}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
    tb.rulenode.key-pattern-hint
    \n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    \n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&me(e.clientId))},[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){me(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:wn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
    \n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
    \n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    \n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
    \n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=D,this.entityType=F}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n
    \n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
    \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class pr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
    \n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class dr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
    \n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
    \n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys($t)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],useRedisQueueForMsgPersistence:[!!e&&e.useRedisQueueForMsgPersistence,[]],trimQueue:[!!e&&e.trimQueue,[]],maxQueueSize:[e?e.maxQueueSize:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","useRedisQueueForMsgPersistence","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("useRedisQueueForMsgPersistence").value,r=this.restApiCallConfigForm.get("enableProxy").value,o=this.restApiCallConfigForm.get("useSystemProxyProperties").value;r&&!o?(this.restApiCallConfigForm.get("proxyHost").setValidators(r?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(r?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),n?this.restApiCallConfigForm.get("maxQueueSize").setValidators([O.min(0)]):this.restApiCallConfigForm.get("maxQueueSize").setValidators([]),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("maxQueueSize").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:wn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
    \n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
    tb.rulenode.parse-to-plain-text-hint
    \n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n
    \n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
    \n \n \n \n {{ \'tb.rulenode.use-redis-queue\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.trim-redis-queue\' | translate }}\n \n \n tb.rulenode.redis-queue-max-size\n \n \n
    \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
    \n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
    \n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
    \n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
    \n
    \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
    \n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
    \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
    \n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(w),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Q.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
    \n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
    \n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class yr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
    \n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Bt,this.sqsQueueTypes=Object.keys(Bt),this.sqsQueueTypeTranslationsMap=Kt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Cn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:he.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
    \n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
    \n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class br{}e("RulenodeCoreConfigExternalModule",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[],target:t.ɵɵFactoryTarget.NgModule}),br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:br,declarations:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr],imports:[$,M,_e,$n],exports:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr]}),br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,imports:[$,M,_e,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:c,args:[{declarations:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr],imports:[$,M,_e,$n],exports:[yr,xr,pr,lr,sr,mr,dr,ur,cr,ir,fr,gr]}]}]});class hr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ae(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:jn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
    \n
    \n
    tb.rulenode.alarm-status
    \n
    \n tb.rulenode.alarm-required\n
    \n
    \n \n
    \n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class vr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ae(e?.messageNames)?e.messageNames:[],metadataNames:ae(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!ae(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:ae(e?.messageNames)?e.messageNames:[],metadataNames:ae(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
    \n
    \n
    tb.rulenode.fields-to-check
    \n
    \n tb.rulenode.at-least-one-field-required\n
    \n
    \n \n help\n \n \n help\n \n
    \n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Cr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=C}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ae(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ae(e?.direction)?e.direction:null,entityType:ae(e?.entityType)?e.entityType:null,entityId:ae(e?.entityId)?e.entityId:null,relationType:ae(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Je.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
    \n
    tb.rulenode.relation-search-parameters
    \n
    \n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
    \n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
    \n
    \n \n \n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Tt,this.perimeterTypes=Object.values(Tt),this.perimeterTypeTranslationMap=It,this.rangeUnits=Object.values(qt),this.rangeUnitTranslationMap=At,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ae(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ae(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ae(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ae(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ae(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ae(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ae(e?.centerLongitude)?e.centerLongitude:null,range:ae(e?.range)?e.range:null,rangeUnit:ae(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ae(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Tt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Tt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:te.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ne.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
    \n
    \n
    tb.rulenode.coordinate-field-names
    \n
    \n
    \n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
    \n
    tb.rulenode.coordinate-field-hint
    \n
    \n
    \n
    \n
    tb.rulenode.geofence-configuration
    \n
    \n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
    \n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
    \n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
    \n
    \n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
    \n
    \n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class kr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ae(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Dn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Lr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.TENANT,F.CUSTOMER,F.USER,F.DASHBOARD,F.RULE_CHAIN,F.RULE_NODE,F.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ae(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
    \n \n help\n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ae(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ae(e?.jsScript)?e.jsScript:null,tbelScript:ae(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Ir extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),{scriptLang:ae(e?.scriptLang)?e.scriptLang:x.JS,jsScript:ae(e?.jsScript)?e.jsScript:null,tbelScript:ae(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
    \n \n \n \n \n \n \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}});class Nr{}e("RuleNodeCoreConfigFilterModule",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Nr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Nr,declarations:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr],imports:[$,M,$n],exports:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr]}),Nr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:c,args:[{declarations:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr],imports:[$,M,$n],exports:[vr,Cr,Fr,kr,Lr,Tr,Ir,hr]}]}]});class Sr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=vt,this.originatorSources=Object.keys(vt),this.originatorSourceTranslationMap=Ct,this.originatorSourceDescTranslationMap=Ft,this.allowedEntityTypes=[F.DEVICE,F.ASSET,F.ENTITY_VIEW,F.USER,F.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===vt.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===vt.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n',dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:qe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:qe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Gn,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
    \n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
    \n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
    \n
    \n
    \n
    \n \n \n
    \n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
    \n
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class qr extends f{constructor(e,t,n,o){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=o,this.tbelEnabled=re(this.store).tbelEnabled,this.scriptLanguage=x,this.changeScript=new r,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:x.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==x.TBEL||this.tbelEnabled||(t=x.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===x.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===x.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=x.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===x.JS?"jsScript":"tbelScript",r=t===x.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===x.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",qr),qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,deps:[{token:P.Store},{token:R.FormBuilder},{token:oe.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),qr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qr,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n',dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:pe.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","noValidate","required"]},{kind:"component",type:de.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:de.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
    \n \n \n \n \n \n \n \n
    \n \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:oe.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:o,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:o,args:["tbelFuncComponent",{static:!1}]}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + const Ar=mt({passive:!0});class Mr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return He;const t=Te(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new Ke,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Ar),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Ar)}}),r}stopMonitoring(e){const t=Te(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Mr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Mr,decorators:[{type:s,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class Er{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new r}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}Er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Er,deps:[{token:t.ElementRef},{token:Mr}],target:t.ɵɵFactoryTarget.Directive}),Er.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Er,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Er,decorators:[{type:d,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Mr}]},propDecorators:{cdkAutofill:[{type:u}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Gr{get minRows(){return this._minRows}set minRows(e){this._minRows=Ie(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=Ie(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Le(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new Ke,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();je(e,"resize").pipe(Pe(16),Ve(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Gr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Gr,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:d,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:p},{type:m,args:[j]}]}]},propDecorators:{minRows:[{type:i,args:["cdkAutosizeMinRows"]}],maxRows:[{type:i,args:["cdkAutosizeMaxRows"]}],enabled:[{type:i,args:["cdkTextareaAutosize"]}],placeholder:[{type:i}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Dr{}Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Dr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,declarations:[Er,Gr],exports:[Er,Gr]}),Dr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,decorators:[{type:c,args:[{declarations:[Er,Gr],exports:[Er,Gr]}]}]});class wr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:ae(e?.fromTemplate)?e.fromTemplate:null,toTemplate:ae(e?.toTemplate)?e.toTemplate:null,ccTemplate:ae(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:ae(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:ae(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:ae(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:ae(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:ae(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",wr),wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),wr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:$e.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Gr,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:X.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:X.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ee.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:qe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:qe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
    \n
    \n
    tb.rulenode.email-sender
    \n
    \n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
    \n
    \n
    \n
    \n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
    \n
    \n
    \n
    \n
    \n
    tb.rulenode.recipients
    \n \n \n
    \n
    \n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
    \n
    \n
    \n
    tb.rulenode.message-subject-and-content
    \n \n \n
    \n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
    \n \n {{ type.description | translate }}\n \n
    \n
    \n
    \n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
    \n
    \n
    \n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Vr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=tn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=ae(e?.fromMetadata)?e.copyFrom?en.METADATA:en.DATA:ae(e?.copyFrom)?e.copyFrom:en.DATA,{keys:ae(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Vr),Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Pr extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=rn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=ae(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ae(e?.renameIn)?e?.renameIn:en.DATA,{renameKeysMapping:ae(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Mn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
    \n
    tb.rulenode.rename-keys-in
    \n
    \n
    \n \n \n {{ data.name }}\n \n \n
    \n
    \n \n \n
    \n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Rr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n",dependencies:[{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
    \n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
    \n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Or extends f{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=nn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=ae(e?.fromMetadata)?e.fromMetadata?en.METADATA:en.DATA:ae(e?.deleteFrom)?e?.deleteFrom:en.DATA,{keys:ae(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Kn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
    \n \n \n \n \n help\n \n \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class _r extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Gt,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Dt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[ae(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[ae(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[ae(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[ae(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[ae(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:H.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:H.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:ce.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:We.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:We.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:We.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Fe.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:ke.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Bn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:An,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
    \n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    tb.rulenode.strategy
    \n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
    \n \n \n
    \n
    \n
    \n \n \n tb.rulenode.advanced-settings\n \n
    \n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
    \n
    \n
    \n
    \n
    \n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Br{}e("RulenodeCoreConfigTransformModule",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Br.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Br,declarations:[Sr,qr,wr,Vr,Pr,Rr,Or,_r],imports:[$,M,$n],exports:[Sr,qr,wr,Vr,Pr,Rr,Or,_r]}),Br.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:c,args:[{declarations:[Sr,qr,wr,Vr,Pr,Rr,Or,_r],imports:[$,M,$n],exports:[Sr,qr,wr,Vr,Pr,Rr,Or,_r]}]}]});class Kr extends f{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=F}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
    \n \n \n
    \n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
    \n \n \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class zr extends f{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),zr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zr,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
    \n
    \n
    \n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
    \n
    \n
    \n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ur{}e("RuleNodeCoreConfigFlowModule",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Ur.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Ur,declarations:[Kr,zr],imports:[$,M,$n],exports:[Kr,zr]}),Ur.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,imports:[$,M,$n]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:c,args:[{declarations:[Kr,zr],imports:[$,M,$n],exports:[Kr,zr]}]}]});class Hr{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 not exists","create-entity-if-not-exists-hint":"Create a new entity set above if it does not exist.","select-device-connectivity-event":"Select device connectivity event","entity-name-pattern":"Name pattern","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 name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","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","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":"Timeseries keys","timeseries-keys-required":"At least one timeseries key should be selected.","add-timeseries-key":"Add timeseries key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-to-specific-entity":"Delete relation to specific entity","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"use-redis-queue":"Use redis queue for message persistence","ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","trim-redis-queue":"Trim redis queue","redis-queue-max-size":"Redis queue max size","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.","persist-alarm-rules":"Persist state of alarm rules","fetch-alarm-rules":"Fetch state of alarm rules","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","use-server-ts":"Use server ts","use-server-ts-hint":"Enable this setting to use the timestamp of the 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.","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":"timeseries 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 timeseries from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch timeseries 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 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."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",Hr),Hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),Hr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Hr,declarations:[dt],imports:[$,M],exports:[Qn,Nr,ar,br,Br,Ur,dt]}),Hr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,imports:[$,M,Qn,Nr,ar,br,Br,Ur]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,decorators:[{type:c,args:[{declarations:[dt],imports:[$,M],exports:[Qn,Nr,ar,br,Br,Ur,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map From 7ba158b2bc2fa3d81c9b6dc40e90998d0b63f508 Mon Sep 17 00:00:00 2001 From: nick Date: Fri, 16 Feb 2024 12:46:30 +0200 Subject: [PATCH 255/397] fix_bug: any(AttributeScope.class) --- .../rule/engine/geo/TbGpsGeofencingActionNodeTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeTest.java index 5cd7e02c59..a0b57ba948 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNodeTest.java @@ -30,6 +30,7 @@ import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.msg.TbMsgType; @@ -137,7 +138,7 @@ class TbGpsGeofencingActionNodeTest extends AbstractRuleNodeUpgradeTest { node.onMsg(ctx, msg); // THEN - verify(ctx.getAttributesService(), never()).find(any(), any(), any(), anyString()); + verify(ctx.getAttributesService(), never()).find(any(), any(), any(AttributeScope.class), anyString()); verify(ctx, never()).tellFailure(any(), any(Throwable.class)); verify(ctx, never()).enqueueForTellNext(any(), eq(expectedOutput), any(), any()); verify(ctx, never()).ack(any()); From 3d4b70618124f7de2fd4e4953fac6ae5c260225f Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Fri, 16 Feb 2024 12:50:29 +0200 Subject: [PATCH 256/397] UI: Implement toggle button widget. --- .../json/system/widget_bundles/buttons.json | 1 + .../widget_bundles/control_widgets.json | 1 + .../system/widget_types/toggle_button.json | 37 ++++ .../basic/basic-widget-config.module.ts | 12 +- .../power-button-basic-config.component.html | 2 +- .../toggle-button-basic-config.component.html | 177 ++++++++++++++++ .../toggle-button-basic-config.component.ts | 192 ++++++++++++++++++ .../toggle-button-widget.component.html | 34 ++++ .../toggle-button-widget.component.scss | 70 +++++++ .../button/toggle-button-widget.component.ts | 142 +++++++++++++ .../lib/button/toggle-button-widget.models.ts | 143 +++++++++++++ ...ggle-button-widget-settings.component.html | 119 +++++++++++ ...toggle-button-widget-settings.component.ts | 94 +++++++++ ...value-action-settings-panel.component.html | 2 +- .../widget-button-appearance.component.html | 7 +- .../widget-button-appearance.component.ts | 19 +- ...t-button-custom-style-panel.component.html | 1 + ...get-button-custom-style-panel.component.ts | 3 + .../widget-button-custom-style.component.html | 1 + .../widget-button-custom-style.component.ts | 4 + .../common/css-size-input.component.html | 5 +- .../common/css-size-input.component.ts | 16 +- .../lib/settings/widget-settings.module.ts | 12 +- .../widget/widget-components.module.ts | 7 +- .../button/widget-button.component.html | 3 +- .../button/widget-button.component.scss | 4 + .../button/widget-button.component.ts | 25 ++- .../components/button/widget-button.models.ts | 1 + .../shared/models/widget-settings.models.ts | 12 +- .../assets/locale/locale.constant-en_US.json | 14 ++ ui-ngx/src/form.scss | 3 +- 31 files changed, 1143 insertions(+), 20 deletions(-) create mode 100644 application/src/main/data/json/system/widget_types/toggle_button.json create mode 100644 ui-ngx/src/app/modules/home/components/widget/config/basic/button/toggle-button-basic-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/config/basic/button/toggle-button-basic-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.models.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.ts diff --git a/application/src/main/data/json/system/widget_bundles/buttons.json b/application/src/main/data/json/system/widget_bundles/buttons.json index effff6a27a..1c498fc0c4 100644 --- a/application/src/main/data/json/system/widget_bundles/buttons.json +++ b/application/src/main/data/json/system/widget_bundles/buttons.json @@ -10,6 +10,7 @@ "widgetTypeFqns": [ "action_button", "command_button", + "toggle_button", "power_button" ] } \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_bundles/control_widgets.json b/application/src/main/data/json/system/widget_bundles/control_widgets.json index 560063a2c4..f61219bfe6 100644 --- a/application/src/main/data/json/system/widget_bundles/control_widgets.json +++ b/application/src/main/data/json/system/widget_bundles/control_widgets.json @@ -10,6 +10,7 @@ "widgetTypeFqns": [ "single_switch", "command_button", + "toggle_button", "power_button", "slider", "control_widgets.switch_control", diff --git a/application/src/main/data/json/system/widget_types/toggle_button.json b/application/src/main/data/json/system/widget_types/toggle_button.json new file mode 100644 index 0000000000..a7e2ae9312 --- /dev/null +++ b/application/src/main/data/json/system/widget_types/toggle_button.json @@ -0,0 +1,37 @@ +{ + "fqn": "toggle_button", + "name": "Toggle button", + "deprecated": false, + "image": "tb-image:VG9nZ2xlIGJ1dHRvbnMuc3Zn:IlRvZ2dsZSBidXR0b24iIHN5c3RlbSB3aWRnZXQgaW1hZ2U=;data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjE2IiBoZWlnaHQ9IjE2MCIgdmlld0JveD0iMCAwIDIxNiAxNjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGZpbHRlcj0idXJsKCNmaWx0ZXIwX2RfNDY5N18zNjcxMykiPgo8cmVjdCB4PSI4Ljc1IiB5PSIxNi43NSIgd2lkdGg9IjE5OC41IiBoZWlnaHQ9IjU4LjUiIHJ4PSIzLjI1IiBzdHJva2U9IiMxOTgwMzgiIHN0cm9rZS13aWR0aD0iMS41IiBzaGFwZS1yZW5kZXJpbmc9ImNyaXNwRWRnZXMiLz4KPG1hc2sgaWQ9Im1hc2swXzQ2OTdfMzY3MTMiIHN0eWxlPSJtYXNrLXR5cGU6YWxwaGEiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjYyIiB5PSIzNCIgd2lkdGg9IjI1IiBoZWlnaHQ9IjI0Ij4KPHJlY3QgeD0iNjIuNSIgeT0iMzQiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0iI0Q5RDlEOSIvPgo8L21hc2s+CjxnIG1hc2s9InVybCgjbWFzazBfNDY5N18zNjcxMykiPgo8cGF0aCBkPSJNNjguNSA0Mkg3Ny41VjQwQzc3LjUgMzkuMTY2NyA3Ny4yMDgzIDM4LjQ1ODMgNzYuNjI1IDM3Ljg3NUM3Ni4wNDE3IDM3LjI5MTcgNzUuMzMzMyAzNyA3NC41IDM3QzczLjY2NjcgMzcgNzIuOTU4MyAzNy4yOTE3IDcyLjM3NSAzNy44NzVDNzEuNzkxNyAzOC40NTgzIDcxLjUgMzkuMTY2NyA3MS41IDQwSDY5LjVDNjkuNSAzOC42MTY3IDY5Ljk4NzUgMzcuNDM3NSA3MC45NjI1IDM2LjQ2MjVDNzEuOTM3NSAzNS40ODc1IDczLjExNjcgMzUgNzQuNSAzNUM3NS44ODMzIDM1IDc3LjA2MjUgMzUuNDg3NSA3OC4wMzc1IDM2LjQ2MjVDNzkuMDEyNSAzNy40Mzc1IDc5LjUgMzguNjE2NyA3OS41IDQwVjQySDgwLjVDODEuMDUgNDIgODEuNTIwOCA0Mi4xOTU4IDgxLjkxMjUgNDIuNTg3NUM4Mi4zMDQyIDQyLjk3OTIgODIuNSA0My40NSA4Mi41IDQ0VjU0QzgyLjUgNTQuNTUgODIuMzA0MiA1NS4wMjA4IDgxLjkxMjUgNTUuNDEyNUM4MS41MjA4IDU1LjgwNDIgODEuMDUgNTYgODAuNSA1Nkg2OC41QzY3Ljk1IDU2IDY3LjQ3OTIgNTUuODA0MiA2Ny4wODc1IDU1LjQxMjVDNjYuNjk1OCA1NS4wMjA4IDY2LjUgNTQuNTUgNjYuNSA1NFY0NEM2Ni41IDQzLjQ1IDY2LjY5NTggNDIuOTc5MiA2Ny4wODc1IDQyLjU4NzVDNjcuNDc5MiA0Mi4xOTU4IDY3Ljk1IDQyIDY4LjUgNDJaTTY4LjUgNTRIODAuNVY0NEg2OC41VjU0Wk03NC41IDUxQzc1LjA1IDUxIDc1LjUyMDggNTAuODA0MiA3NS45MTI1IDUwLjQxMjVDNzYuMzA0MiA1MC4wMjA4IDc2LjUgNDkuNTUgNzYuNSA0OUM3Ni41IDQ4LjQ1IDc2LjMwNDIgNDcuOTc5MiA3NS45MTI1IDQ3LjU4NzVDNzUuNTIwOCA0Ny4xOTU4IDc1LjA1IDQ3IDc0LjUgNDdDNzMuOTUgNDcgNzMuNDc5MiA0Ny4xOTU4IDczLjA4NzUgNDcuNTg3NUM3Mi42OTU4IDQ3Ljk3OTIgNzIuNSA0OC40NSA3Mi41IDQ5QzcyLjUgNDkuNTUgNzIuNjk1OCA1MC4wMjA4IDczLjA4NzUgNTAuNDEyNUM3My40NzkyIDUwLjgwNDIgNzMuOTUgNTEgNzQuNSA1MVoiIGZpbGw9IiMxOTgwMzgiLz4KPC9nPgo8cGF0aCBkPSJNMTAyLjEzMSA0NS4yNVY0NS45NTMxQzEwMi4xMzEgNDYuOTE5OSAxMDIuMDA1IDQ3Ljc4NzEgMTAxLjc1MyA0OC41NTQ3QzEwMS41MDEgNDkuMzIyMyAxMDEuMTQxIDQ5Ljk3NTYgMTAwLjY3MiA1MC41MTQ2QzEwMC4yMDkgNTEuMDUzNyA5OS42NTIzIDUxLjQ2NjggOTkuMDAyIDUxLjc1MzlDOTguMzUxNiA1Mi4wMzUyIDk3LjYzMDkgNTIuMTc1OCA5Ni44Mzk4IDUyLjE3NThDOTYuMDU0NyA1Mi4xNzU4IDk1LjMzNjkgNTIuMDM1MiA5NC42ODY1IDUxLjc1MzlDOTQuMDQyIDUxLjQ2NjggOTMuNDgyNCA1MS4wNTM3IDkzLjAwNzggNTAuNTE0NkM5Mi41MzMyIDQ5Ljk3NTYgOTIuMTY0MSA0OS4zMjIzIDkxLjkwMDQgNDguNTU0N0M5MS42NDI2IDQ3Ljc4NzEgOTEuNTEzNyA0Ni45MTk5IDkxLjUxMzcgNDUuOTUzMVY0NS4yNUM5MS41MTM3IDQ0LjI4MzIgOTEuNjQyNiA0My40MTg5IDkxLjkwMDQgNDIuNjU3MkM5Mi4xNTgyIDQxLjg4OTYgOTIuNTIxNSA0MS4yMzYzIDkyLjk5MDIgNDAuNjk3M0M5My40NjQ4IDQwLjE1MjMgOTQuMDI0NCAzOS43MzkzIDk0LjY2ODkgMzkuNDU4Qzk1LjMxOTMgMzkuMTcwOSA5Ni4wMzcxIDM5LjAyNzMgOTYuODIyMyAzOS4wMjczQzk3LjYxMzMgMzkuMDI3MyA5OC4zMzQgMzkuMTcwOSA5OC45ODQ0IDM5LjQ1OEM5OS42MzQ4IDM5LjczOTMgMTAwLjE5NCA0MC4xNTIzIDEwMC42NjMgNDAuNjk3M0MxMDEuMTMyIDQxLjIzNjMgMTAxLjQ5MiA0MS44ODk2IDEwMS43NDQgNDIuNjU3MkMxMDIuMDAyIDQzLjQxODkgMTAyLjEzMSA0NC4yODMyIDEwMi4xMzEgNDUuMjVaTTk5LjkyNDggNDUuOTUzMVY0NS4yMzI0Qzk5LjkyNDggNDQuNTE3NiA5OS44NTQ1IDQzLjg4NzcgOTkuNzEzOSA0My4zNDI4Qzk5LjU3OTEgNDIuNzkyIDk5LjM3NyA0Mi4zMzIgOTkuMTA3NCA0MS45NjI5Qzk4Ljg0MzggNDEuNTg3OSA5OC41MTg2IDQxLjMwNjYgOTguMTMxOCA0MS4xMTkxQzk3Ljc0NTEgNDAuOTI1OCA5Ny4zMDg2IDQwLjgyOTEgOTYuODIyMyA0MC44MjkxQzk2LjMzNTkgNDAuODI5MSA5NS45MDIzIDQwLjkyNTggOTUuNTIxNSA0MS4xMTkxQzk1LjE0MDYgNDEuMzA2NiA5NC44MTU0IDQxLjU4NzkgOTQuNTQ1OSA0MS45NjI5Qzk0LjI4MjIgNDIuMzMyIDk0LjA4MDEgNDIuNzkyIDkzLjkzOTUgNDMuMzQyOEM5My43OTg4IDQzLjg4NzcgOTMuNzI4NSA0NC41MTc2IDkzLjcyODUgNDUuMjMyNFY0NS45NTMxQzkzLjcyODUgNDYuNjY4IDkzLjc5ODggNDcuMzAwOCA5My45Mzk1IDQ3Ljg1MTZDOTQuMDgwMSA0OC40MDIzIDk0LjI4NTIgNDguODY4MiA5NC41NTQ3IDQ5LjI0OUM5NC44MzAxIDQ5LjYyNCA5NS4xNTgyIDQ5LjkwODIgOTUuNTM5MSA1MC4xMDE2Qzk1LjkxOTkgNTAuMjg5MSA5Ni4zNTM1IDUwLjM4MjggOTYuODM5OCA1MC4zODI4Qzk3LjMzMiA1MC4zODI4IDk3Ljc2ODYgNTAuMjg5MSA5OC4xNDk0IDUwLjEwMTZDOTguNTMwMyA0OS45MDgyIDk4Ljg1MjUgNDkuNjI0IDk5LjExNjIgNDkuMjQ5Qzk5LjM3OTkgNDguODY4MiA5OS41NzkxIDQ4LjQwMjMgOTkuNzEzOSA0Ny44NTE2Qzk5Ljg1NDUgNDcuMzAwOCA5OS45MjQ4IDQ2LjY2OCA5OS45MjQ4IDQ1Ljk1MzFaTTEwNi40MDMgNDQuMzE4NFY1NS42NTYySDEwNC4yODVWNDIuNDkwMkgxMDYuMjM2TDEwNi40MDMgNDQuMzE4NFpNMTEyLjU5OSA0Ny4xNTcyVjQ3LjM0MThDMTEyLjU5OSA0OC4wMzMyIDExMi41MTcgNDguNjc0OCAxMTIuMzUzIDQ5LjI2NjZDMTEyLjE5NSA0OS44NTI1IDExMS45NTggNTAuMzY1MiAxMTEuNjQxIDUwLjgwNDdDMTExLjMzMSA1MS4yMzgzIDExMC45NDcgNTEuNTc1MiAxMTAuNDkgNTEuODE1NEMxMTAuMDMzIDUyLjA1NTcgMTA5LjUwNSA1Mi4xNzU4IDEwOC45MDggNTIuMTc1OEMxMDguMzE2IDUyLjE3NTggMTA3Ljc5NyA1Mi4wNjc0IDEwNy4zNTIgNTEuODUwNkMxMDYuOTEzIDUxLjYyNzkgMTA2LjU0MSA1MS4zMTQ1IDEwNi4yMzYgNTAuOTEwMkMxMDUuOTMxIDUwLjUwNTkgMTA1LjY4NSA1MC4wMzEyIDEwNS40OTggNDkuNDg2M0MxMDUuMzE2IDQ4LjkzNTUgMTA1LjE4NyA0OC4zMzIgMTA1LjExMSA0Ny42NzU4VjQ2Ljk2MzlDMTA1LjE4NyA0Ni4yNjY2IDEwNS4zMTYgNDUuNjMzOCAxMDUuNDk4IDQ1LjA2NTRDMTA1LjY4NSA0NC40OTcxIDEwNS45MzEgNDQuMDA3OCAxMDYuMjM2IDQzLjU5NzdDMTA2LjU0MSA0My4xODc1IDEwNi45MTMgNDIuODcxMSAxMDcuMzUyIDQyLjY0ODRDMTA3Ljc5MiA0Mi40MjU4IDEwOC4zMDQgNDIuMzE0NSAxMDguODkgNDIuMzE0NUMxMDkuNDg4IDQyLjMxNDUgMTEwLjAxOCA0Mi40MzE2IDExMC40ODEgNDIuNjY2QzExMC45NDQgNDIuODk0NSAxMTEuMzM0IDQzLjIyMjcgMTExLjY1IDQzLjY1MDRDMTExLjk2NiA0NC4wNzIzIDExMi4yMDQgNDQuNTgyIDExMi4zNjIgNDUuMTc5N0MxMTIuNTIgNDUuNzcxNSAxMTIuNTk5IDQ2LjQzMDcgMTEyLjU5OSA0Ny4xNTcyWk0xMTAuNDgxIDQ3LjM0MThWNDcuMTU3MkMxMTAuNDgxIDQ2LjcxNzggMTEwLjQ0IDQ2LjMxMDUgMTEwLjM1OCA0NS45MzU1QzExMC4yNzYgNDUuNTU0NyAxMTAuMTQ3IDQ1LjIyMDcgMTA5Ljk3MSA0NC45MzM2QzEwOS43OTYgNDQuNjQ2NSAxMDkuNTcgNDQuNDIzOCAxMDkuMjk1IDQ0LjI2NTZDMTA5LjAyNSA0NC4xMDE2IDEwOC43IDQ0LjAxOTUgMTA4LjMxOSA0NC4wMTk1QzEwNy45NDQgNDQuMDE5NSAxMDcuNjIyIDQ0LjA4NCAxMDcuMzUyIDQ0LjIxMjlDMTA3LjA4MyA0NC4zMzU5IDEwNi44NTcgNDQuNTA4OCAxMDYuNjc1IDQ0LjczMTRDMTA2LjQ5NCA0NC45NTQxIDEwNi4zNTMgNDUuMjE0OCAxMDYuMjU0IDQ1LjUxMzdDMTA2LjE1NCA0NS44MDY2IDEwNi4wODQgNDYuMTI2IDEwNi4wNDMgNDYuNDcxN1Y0OC4xNzY4QzEwNi4xMTMgNDguNTk4NiAxMDYuMjMzIDQ4Ljk4NTQgMTA2LjQwMyA0OS4zMzY5QzEwNi41NzMgNDkuNjg4NSAxMDYuODEzIDQ5Ljk2OTcgMTA3LjEyNCA1MC4xODA3QzEwNy40NCA1MC4zODU3IDEwNy44NDQgNTAuNDg4MyAxMDguMzM3IDUwLjQ4ODNDMTA4LjcxNyA1MC40ODgzIDEwOS4wNDMgNTAuNDA2MiAxMDkuMzEyIDUwLjI0MjJDMTA5LjU4MiA1MC4wNzgxIDEwOS44MDEgNDkuODUyNSAxMDkuOTcxIDQ5LjU2NTRDMTEwLjE0NyA0OS4yNzI1IDExMC4yNzYgNDguOTM1NSAxMTAuMzU4IDQ4LjU1NDdDMTEwLjQ0IDQ4LjE3MzggMTEwLjQ4MSA0Ny43Njk1IDExMC40ODEgNDcuMzQxOFpNMTE4Ljc0MyA1Mi4xNzU4QzExOC4wNCA1Mi4xNzU4IDExNy40MDQgNTIuMDYxNSAxMTYuODM2IDUxLjgzM0MxMTYuMjc0IDUxLjU5ODYgMTE1Ljc5MyA1MS4yNzM0IDExNS4zOTUgNTAuODU3NEMxMTUuMDAyIDUwLjQ0MTQgMTE0LjcgNDkuOTUyMSAxMTQuNDg5IDQ5LjM4OTZDMTE0LjI3OSA0OC44MjcxIDExNC4xNzMgNDguMjIwNyAxMTQuMTczIDQ3LjU3MDNWNDcuMjE4OEMxMTQuMTczIDQ2LjQ3NDYgMTE0LjI4MSA0NS44MDA4IDExNC40OTggNDUuMTk3M0MxMTQuNzE1IDQ0LjU5MzggMTE1LjAxNyA0NC4wNzgxIDExNS40MDQgNDMuNjUwNEMxMTUuNzkgNDMuMjE2OCAxMTYuMjQ3IDQyLjg4NTcgMTE2Ljc3NSA0Mi42NTcyQzExNy4zMDIgNDIuNDI4NyAxMTcuODczIDQyLjMxNDUgMTE4LjQ4OCA0Mi4zMTQ1QzExOS4xNjggNDIuMzE0NSAxMTkuNzYzIDQyLjQyODcgMTIwLjI3MyA0Mi42NTcyQzEyMC43ODIgNDIuODg1NyAxMjEuMjA0IDQzLjIwOCAxMjEuNTM4IDQzLjYyNEMxMjEuODc4IDQ0LjAzNDIgMTIyLjEzIDQ0LjUyMzQgMTIyLjI5NCA0NS4wOTE4QzEyMi40NjQgNDUuNjYwMiAxMjIuNTQ5IDQ2LjI4NzEgMTIyLjU0OSA0Ni45NzI3VjQ3Ljg3NzlIMTE1LjIwMVY0Ni4zNTc0SDEyMC40NTdWNDYuMTkwNEMxMjAuNDQ2IDQ1LjgwOTYgMTIwLjM2OSA0NS40NTIxIDEyMC4yMjkgNDUuMTE4MkMxMjAuMDk0IDQ0Ljc4NDIgMTE5Ljg4NiA0NC41MTQ2IDExOS42MDUgNDQuMzA5NkMxMTkuMzIzIDQ0LjEwNDUgMTE4Ljk0OCA0NC4wMDIgMTE4LjQ4IDQ0LjAwMkMxMTguMTI4IDQ0LjAwMiAxMTcuODE1IDQ0LjA3ODEgMTE3LjUzOSA0NC4yMzA1QzExNy4yNyA0NC4zNzcgMTE3LjA0NCA0NC41OTA4IDExNi44NjIgNDQuODcyMUMxMTYuNjgxIDQ1LjE1MzMgMTE2LjU0IDQ1LjQ5MzIgMTE2LjQ0MSA0NS44OTE2QzExNi4zNDcgNDYuMjg0MiAxMTYuMyA0Ni43MjY2IDExNi4zIDQ3LjIxODhWNDcuNTcwM0MxMTYuMyA0Ny45ODYzIDExNi4zNTYgNDguMzczIDExNi40NjcgNDguNzMwNUMxMTYuNTg0IDQ5LjA4MiAxMTYuNzU0IDQ5LjM4OTYgMTE2Ljk3NyA0OS42NTMzQzExNy4xOTkgNDkuOTE3IDExNy40NjkgNTAuMTI1IDExNy43ODUgNTAuMjc3M0MxMTguMTAyIDUwLjQyMzggMTE4LjQ2MiA1MC40OTcxIDExOC44NjYgNTAuNDk3MUMxMTkuMzc2IDUwLjQ5NzEgMTE5LjgzIDUwLjM5NDUgMTIwLjIyOSA1MC4xODk1QzEyMC42MjcgNDkuOTg0NCAxMjAuOTczIDQ5LjY5NDMgMTIxLjI2NiA0OS4zMTkzTDEyMi4zODIgNTAuNDAwNEMxMjIuMTc3IDUwLjY5OTIgMTIxLjkxIDUwLjk4NjMgMTIxLjU4MiA1MS4yNjE3QzEyMS4yNTQgNTEuNTMxMiAxMjAuODUzIDUxLjc1MSAxMjAuMzc4IDUxLjkyMDlDMTE5LjkwOSA1Mi4wOTA4IDExOS4zNjQgNTIuMTc1OCAxMTguNzQzIDUyLjE3NThaTTEyNi40NTIgNDQuNTIwNVY1MkgxMjQuMzM0VjQyLjQ5MDJIMTI2LjMyOUwxMjYuNDUyIDQ0LjUyMDVaTTEyNi4wNzQgNDYuODkzNkwxMjUuMzg4IDQ2Ljg4NDhDMTI1LjM5NCA0Ni4yMTA5IDEyNS40ODggNDUuNTkyOCAxMjUuNjcgNDUuMDMwM0MxMjUuODU3IDQ0LjQ2NzggMTI2LjExNSA0My45ODQ0IDEyNi40NDMgNDMuNTgwMUMxMjYuNzc3IDQzLjE3NTggMTI3LjE3NiA0Mi44NjUyIDEyNy42MzggNDIuNjQ4NEMxMjguMTAxIDQyLjQyNTggMTI4LjYxNyA0Mi4zMTQ1IDEyOS4xODUgNDIuMzE0NUMxMjkuNjQyIDQyLjMxNDUgMTMwLjA1NSA0Mi4zNzg5IDEzMC40MjUgNDIuNTA3OEMxMzAuOCA0Mi42MzA5IDEzMS4xMTkgNDIuODMzIDEzMS4zODMgNDMuMTE0M0MxMzEuNjUyIDQzLjM5NTUgMTMxLjg1NyA0My43NjE3IDEzMS45OTggNDQuMjEyOUMxMzIuMTM4IDQ0LjY1ODIgMTMyLjIwOSA0NS4yMDYxIDEzMi4yMDkgNDUuODU2NFY1MkgxMzAuMDgyVjQ1Ljg0NzdDMTMwLjA4MiA0NS4zOTA2IDEzMC4wMTQgNDUuMDMwMyAxMjkuODggNDQuNzY2NkMxMjkuNzUxIDQ0LjQ5NzEgMTI5LjU2IDQ0LjMwNjYgMTI5LjMwOCA0NC4xOTUzQzEyOS4wNjIgNDQuMDc4MSAxMjguNzU1IDQ0LjAxOTUgMTI4LjM4NiA0NC4wMTk1QzEyOC4wMjIgNDQuMDE5NSAxMjcuNjk3IDQ0LjA5NTcgMTI3LjQxIDQ0LjI0OEMxMjcuMTIzIDQ0LjQwMDQgMTI2Ljg4IDQ0LjYwODQgMTI2LjY4IDQ0Ljg3MjFDMTI2LjQ4NyA0NS4xMzU3IDEyNi4zMzggNDUuNDQwNCAxMjYuMjMyIDQ1Ljc4NjFDMTI2LjEyNyA0Ni4xMzE4IDEyNi4wNzQgNDYuNTAxIDEyNi4wNzQgNDYuODkzNlpNMTM4LjcxMyA1Mi4xNzU4QzEzOC4wMSA1Mi4xNzU4IDEzNy4zNzQgNTIuMDYxNSAxMzYuODA2IDUxLjgzM0MxMzYuMjQ0IDUxLjU5ODYgMTM1Ljc2MyA1MS4yNzM0IDEzNS4zNjUgNTAuODU3NEMxMzQuOTcyIDUwLjQ0MTQgMTM0LjY3IDQ5Ljk1MjEgMTM0LjQ1OSA0OS4zODk2QzEzNC4yNDggNDguODI3MSAxMzQuMTQzIDQ4LjIyMDcgMTM0LjE0MyA0Ny41NzAzVjQ3LjIxODhDMTM0LjE0MyA0Ni40NzQ2IDEzNC4yNTEgNDUuODAwOCAxMzQuNDY4IDQ1LjE5NzNDMTM0LjY4NSA0NC41OTM4IDEzNC45ODcgNDQuMDc4MSAxMzUuMzczIDQzLjY1MDRDMTM1Ljc2IDQzLjIxNjggMTM2LjIxNyA0Mi44ODU3IDEzNi43NDUgNDIuNjU3MkMxMzcuMjcyIDQyLjQyODcgMTM3Ljg0MyA0Mi4zMTQ1IDEzOC40NTggNDIuMzE0NUMxMzkuMTM4IDQyLjMxNDUgMTM5LjczMyA0Mi40Mjg3IDE0MC4yNDMgNDIuNjU3MkMxNDAuNzUyIDQyLjg4NTcgMTQxLjE3NCA0My4yMDggMTQxLjUwOCA0My42MjRDMTQxLjg0OCA0NC4wMzQyIDE0Mi4xIDQ0LjUyMzQgMTQyLjI2NCA0NS4wOTE4QzE0Mi40MzQgNDUuNjYwMiAxNDIuNTE5IDQ2LjI4NzEgMTQyLjUxOSA0Ni45NzI3VjQ3Ljg3NzlIMTM1LjE3MVY0Ni4zNTc0SDE0MC40MjdWNDYuMTkwNEMxNDAuNDE1IDQ1LjgwOTYgMTQwLjMzOSA0NS40NTIxIDE0MC4xOTkgNDUuMTE4MkMxNDAuMDY0IDQ0Ljc4NDIgMTM5Ljg1NiA0NC41MTQ2IDEzOS41NzUgNDQuMzA5NkMxMzkuMjkzIDQ0LjEwNDUgMTM4LjkxOCA0NC4wMDIgMTM4LjQ1IDQ0LjAwMkMxMzguMDk4IDQ0LjAwMiAxMzcuNzg1IDQ0LjA3ODEgMTM3LjUwOSA0NC4yMzA1QzEzNy4yNCA0NC4zNzcgMTM3LjAxNCA0NC41OTA4IDEzNi44MzIgNDQuODcyMUMxMzYuNjUxIDQ1LjE1MzMgMTM2LjUxIDQ1LjQ5MzIgMTM2LjQxMSA0NS44OTE2QzEzNi4zMTcgNDYuMjg0MiAxMzYuMjcgNDYuNzI2NiAxMzYuMjcgNDcuMjE4OFY0Ny41NzAzQzEzNi4yNyA0Ny45ODYzIDEzNi4zMjYgNDguMzczIDEzNi40MzcgNDguNzMwNUMxMzYuNTU0IDQ5LjA4MiAxMzYuNzI0IDQ5LjM4OTYgMTM2Ljk0NyA0OS42NTMzQzEzNy4xNjkgNDkuOTE3IDEzNy40MzkgNTAuMTI1IDEzNy43NTUgNTAuMjc3M0MxMzguMDcyIDUwLjQyMzggMTM4LjQzMiA1MC40OTcxIDEzOC44MzYgNTAuNDk3MUMxMzkuMzQ2IDUwLjQ5NzEgMTM5LjggNTAuMzk0NSAxNDAuMTk5IDUwLjE4OTVDMTQwLjU5NyA0OS45ODQ0IDE0MC45NDMgNDkuNjk0MyAxNDEuMjM2IDQ5LjMxOTNMMTQyLjM1MiA1MC40MDA0QzE0Mi4xNDcgNTAuNjk5MiAxNDEuODggNTAuOTg2MyAxNDEuNTUyIDUxLjI2MTdDMTQxLjIyNCA1MS41MzEyIDE0MC44MjMgNTEuNzUxIDE0MC4zNDggNTEuOTIwOUMxMzkuODc5IDUyLjA5MDggMTM5LjMzNCA1Mi4xNzU4IDEzOC43MTMgNTIuMTc1OFpNMTUwLjEyMiA1MC4wMzEyVjM4LjVIMTUyLjI0OVY1MkgxNTAuMzI0TDE1MC4xMjIgNTAuMDMxMlpNMTQzLjkzNSA0Ny4zNTA2VjQ3LjE2NkMxNDMuOTM1IDQ2LjQ0NTMgMTQ0LjAyIDQ1Ljc4OTEgMTQ0LjE4OSA0NS4xOTczQzE0NC4zNTkgNDQuNTk5NiAxNDQuNjA1IDQ0LjA4NjkgMTQ0LjkyOCA0My42NTkyQzE0NS4yNSA0My4yMjU2IDE0NS42NDMgNDIuODk0NSAxNDYuMTA1IDQyLjY2NkMxNDYuNTY4IDQyLjQzMTYgMTQ3LjA5IDQyLjMxNDUgMTQ3LjY3IDQyLjMxNDVDMTQ4LjI0NCA0Mi4zMTQ1IDE0OC43NDggNDIuNDI1OCAxNDkuMTgyIDQyLjY0ODRDMTQ5LjYxNSA0Mi44NzExIDE0OS45ODQgNDMuMTkwNCAxNTAuMjg5IDQzLjYwNjRDMTUwLjU5NCA0NC4wMTY2IDE1MC44MzcgNDQuNTA4OCAxNTEuMDE5IDQ1LjA4M0MxNTEuMiA0NS42NTE0IDE1MS4zMjkgNDYuMjg0MiAxNTEuNDA1IDQ2Ljk4MTRWNDcuNTcwM0MxNTEuMzI5IDQ4LjI1IDE1MS4yIDQ4Ljg3MTEgMTUxLjAxOSA0OS40MzM2QzE1MC44MzcgNDkuOTk2MSAxNTAuNTk0IDUwLjQ4MjQgMTUwLjI4OSA1MC44OTI2QzE0OS45ODQgNTEuMzAyNyAxNDkuNjEyIDUxLjYxOTEgMTQ5LjE3MyA1MS44NDE4QzE0OC43MzkgNTIuMDY0NSAxNDguMjMyIDUyLjE3NTggMTQ3LjY1MiA1Mi4xNzU4QzE0Ny4wNzggNTIuMTc1OCAxNDYuNTYgNTIuMDU1NyAxNDYuMDk3IDUxLjgxNTRDMTQ1LjY0IDUxLjU3NTIgMTQ1LjI1IDUxLjIzODMgMTQ0LjkyOCA1MC44MDQ3QzE0NC42MDUgNTAuMzcxMSAxNDQuMzU5IDQ5Ljg2MTMgMTQ0LjE4OSA0OS4yNzU0QzE0NC4wMiA0OC42ODM2IDE0My45MzUgNDguMDQyIDE0My45MzUgNDcuMzUwNlpNMTQ2LjA1MyA0Ny4xNjZWNDcuMzUwNkMxNDYuMDUzIDQ3Ljc4NDIgMTQ2LjA5MSA0OC4xODg1IDE0Ni4xNjcgNDguNTYzNUMxNDYuMjQ5IDQ4LjkzODUgMTQ2LjM3NSA0OS4yNjk1IDE0Ni41NDUgNDkuNTU2NkMxNDYuNzE1IDQ5LjgzNzkgMTQ2LjkzNSA1MC4wNjA1IDE0Ny4yMDQgNTAuMjI0NkMxNDcuNDc5IDUwLjM4MjggMTQ3LjgwOCA1MC40NjE5IDE0OC4xODggNTAuNDYxOUMxNDguNjY5IDUwLjQ2MTkgMTQ5LjA2NCA1MC4zNTY0IDE0OS4zNzUgNTAuMTQ1NUMxNDkuNjg2IDQ5LjkzNDYgMTQ5LjkyOSA0OS42NTA0IDE1MC4xMDQgNDkuMjkzQzE1MC4yODYgNDguOTI5NyAxNTAuNDA5IDQ4LjUyNTQgMTUwLjQ3NCA0OC4wODAxVjQ2LjQ4OTNDMTUwLjQzOCA0Ni4xNDM2IDE1MC4zNjUgNDUuODIxMyAxNTAuMjU0IDQ1LjUyMjVDMTUwLjE0OCA0NS4yMjM2IDE1MC4wMDUgNDQuOTYyOSAxNDkuODIzIDQ0Ljc0MDJDMTQ5LjY0MiA0NC41MTE3IDE0OS40MTYgNDQuMzM1OSAxNDkuMTQ2IDQ0LjIxMjlDMTQ4Ljg4MyA0NC4wODQgMTQ4LjU2OSA0NC4wMTk1IDE0OC4yMDYgNDQuMDE5NUMxNDcuODE5IDQ0LjAxOTUgMTQ3LjQ5MSA0NC4xMDE2IDE0Ny4yMjIgNDQuMjY1NkMxNDYuOTUyIDQ0LjQyOTcgMTQ2LjcyOSA0NC42NTUzIDE0Ni41NTQgNDQuOTQyNEMxNDYuMzg0IDQ1LjIyOTUgMTQ2LjI1OCA0NS41NjM1IDE0Ni4xNzYgNDUuOTQ0M0MxNDYuMDk0IDQ2LjMyNTIgMTQ2LjA1MyA0Ni43MzI0IDE0Ni4wNTMgNDcuMTY2WiIgZmlsbD0iIzE5ODAzOCIvPgo8L2c+CjxtYXNrIGlkPSJwYXRoLTYtaW5zaWRlLTFfNDY5N18zNjcxMyIgZmlsbD0id2hpdGUiPgo8cGF0aCBkPSJNOCA4OEM4IDg1Ljc5MDkgOS43OTA4NiA4NCAxMiA4NEgyMDRDMjA2LjIwOSA4NCAyMDggODUuNzkwOSAyMDggODhWMTQwQzIwOCAxNDIuMjA5IDIwNi4yMDkgMTQ0IDIwNCAxNDRIMTJDOS43OTA4NiAxNDQgOCAxNDIuMjA5IDggMTQwVjg4WiIvPgo8L21hc2s+CjxwYXRoIGQ9Ik04IDg4QzggODUuNzkwOSA5Ljc5MDg2IDg0IDEyIDg0SDIwNEMyMDYuMjA5IDg0IDIwOCA4NS43OTA5IDIwOCA4OFYxNDBDMjA4IDE0Mi4yMDkgMjA2LjIwOSAxNDQgMjA0IDE0NEgxMkM5Ljc5MDg2IDE0NCA4IDE0Mi4yMDkgOCAxNDBWODhaIiBmaWxsPSIjRDEyNzMwIi8+CjxwYXRoIGQ9Ik04IDg0SDIwOEg4Wk0yMDggMTQwQzIwOCAxNDMuMzE0IDIwNS4zMTQgMTQ2IDIwMiAxNDZIMTRDMTAuNjg2MyAxNDYgOCAxNDMuMzE0IDggMTQwQzggMTQxLjEwNSA5Ljc5MDg2IDE0MiAxMiAxNDJIMjA0QzIwNi4yMDkgMTQyIDIwOCAxNDEuMTA1IDIwOCAxNDBaTTggMTQ0Vjg0VjE0NFpNMjA4IDg0VjE0NFY4NFoiIGZpbGw9IiNEMTI3MzAiIG1hc2s9InVybCgjcGF0aC02LWluc2lkZS0xXzQ2OTdfMzY3MTMpIi8+CjxtYXNrIGlkPSJtYXNrMV80Njk3XzM2NzEzIiBzdHlsZT0ibWFzay10eXBlOmFscGhhIiBtYXNrVW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4PSI2NSIgeT0iMTAyIiB3aWR0aD0iMjUiIGhlaWdodD0iMjQiPgo8cmVjdCB4PSI2NS41IiB5PSIxMDIiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0iI0Q5RDlEOSIvPgo8L21hc2s+CjxnIG1hc2s9InVybCgjbWFzazFfNDY5N18zNjcxMykiPgo8cGF0aCBkPSJNNzEuNSAxMjRDNzAuOTUgMTI0IDcwLjQ3OTIgMTIzLjgwNCA3MC4wODc1IDEyMy40MTNDNjkuNjk1OCAxMjMuMDIxIDY5LjUgMTIyLjU1IDY5LjUgMTIyVjExMkM2OS41IDExMS40NSA2OS42OTU4IDExMC45NzkgNzAuMDg3NSAxMTAuNTg4QzcwLjQ3OTIgMTEwLjE5NiA3MC45NSAxMTAgNzEuNSAxMTBINzIuNVYxMDhDNzIuNSAxMDYuNjE3IDcyLjk4NzUgMTA1LjQzOCA3My45NjI1IDEwNC40NjJDNzQuOTM3NSAxMDMuNDg3IDc2LjExNjcgMTAzIDc3LjUgMTAzQzc4Ljg4MzMgMTAzIDgwLjA2MjUgMTAzLjQ4NyA4MS4wMzc1IDEwNC40NjJDODIuMDEyNSAxMDUuNDM4IDgyLjUgMTA2LjYxNyA4Mi41IDEwOFYxMTBIODMuNUM4NC4wNSAxMTAgODQuNTIwOCAxMTAuMTk2IDg0LjkxMjUgMTEwLjU4OEM4NS4zMDQyIDExMC45NzkgODUuNSAxMTEuNDUgODUuNSAxMTJWMTIyQzg1LjUgMTIyLjU1IDg1LjMwNDIgMTIzLjAyMSA4NC45MTI1IDEyMy40MTNDODQuNTIwOCAxMjMuODA0IDg0LjA1IDEyNCA4My41IDEyNEg3MS41Wk03MS41IDEyMkg4My41VjExMkg3MS41VjEyMlpNNzcuNSAxMTlDNzguMDUgMTE5IDc4LjUyMDggMTE4LjgwNCA3OC45MTI1IDExOC40MTNDNzkuMzA0MiAxMTguMDIxIDc5LjUgMTE3LjU1IDc5LjUgMTE3Qzc5LjUgMTE2LjQ1IDc5LjMwNDIgMTE1Ljk3OSA3OC45MTI1IDExNS41ODhDNzguNTIwOCAxMTUuMTk2IDc4LjA1IDExNSA3Ny41IDExNUM3Ni45NSAxMTUgNzYuNDc5MiAxMTUuMTk2IDc2LjA4NzUgMTE1LjU4OEM3NS42OTU4IDExNS45NzkgNzUuNSAxMTYuNDUgNzUuNSAxMTdDNzUuNSAxMTcuNTUgNzUuNjk1OCAxMTguMDIxIDc2LjA4NzUgMTE4LjQxM0M3Ni40NzkyIDExOC44MDQgNzYuOTUgMTE5IDc3LjUgMTE5Wk03NC41IDExMEg4MC41VjEwOEM4MC41IDEwNy4xNjcgODAuMjA4MyAxMDYuNDU4IDc5LjYyNSAxMDUuODc1Qzc5LjA0MTcgMTA1LjI5MiA3OC4zMzMzIDEwNSA3Ny41IDEwNUM3Ni42NjY3IDEwNSA3NS45NTgzIDEwNS4yOTIgNzUuMzc1IDEwNS44NzVDNzQuNzkxNyAxMDYuNDU4IDc0LjUgMTA3LjE2NyA3NC41IDEwOFYxMTBaIiBmaWxsPSJ3aGl0ZSIvPgo8L2c+CjxwYXRoIGQ9Ik0xMDIuNjc2IDExNS44MzRIMTA0Ljg3M0MxMDQuODAzIDExNi42NzIgMTA0LjU2OCAxMTcuNDE5IDEwNC4xNyAxMTguMDc1QzEwMy43NzEgMTE4LjcyNiAxMDMuMjEyIDExOS4yMzggMTAyLjQ5MSAxMTkuNjEzQzEwMS43NzEgMTE5Ljk4OCAxMDAuODk1IDEyMC4xNzYgOTkuODYzMyAxMjAuMTc2Qzk5LjA3MjMgMTIwLjE3NiA5OC4zNjA0IDEyMC4wMzUgOTcuNzI3NSAxMTkuNzU0Qzk3LjA5NDcgMTE5LjQ2NyA5Ni41NTI3IDExOS4wNjIgOTYuMTAxNiAxMTguNTQxQzk1LjY1MDQgMTE4LjAxNCA5NS4zMDQ3IDExNy4zNzggOTUuMDY0NSAxMTYuNjM0Qzk0LjgzMDEgMTE1Ljg5IDk0LjcxMjkgMTE1LjA1OCA5NC43MTI5IDExNC4xMzhWMTEzLjA3NEM5NC43MTI5IDExMi4xNTQgOTQuODMzIDExMS4zMjIgOTUuMDczMiAxMTAuNTc4Qzk1LjMxOTMgMTA5LjgzNCA5NS42NzA5IDEwOS4xOTggOTYuMTI3OSAxMDguNjcxQzk2LjU4NSAxMDguMTM4IDk3LjEzMjggMTA3LjczIDk3Ljc3MTUgMTA3LjQ0OUM5OC40MTYgMTA3LjE2OCA5OS4xMzk2IDEwNy4wMjcgOTkuOTQyNCAxMDcuMDI3QzEwMC45NjIgMTA3LjAyNyAxMDEuODIzIDEwNy4yMTUgMTAyLjUyNiAxMDcuNTlDMTAzLjIyOSAxMDcuOTY1IDEwMy43NzQgMTA4LjQ4MyAxMDQuMTYxIDEwOS4xNDZDMTA0LjU1NCAxMDkuODA4IDEwNC43OTQgMTEwLjU2NiAxMDQuODgyIDExMS40MjJIMTAyLjY4NUMxMDIuNjI2IDExMC44NzEgMTAyLjQ5NyAxMTAuMzk5IDEwMi4yOTggMTEwLjAwN0MxMDIuMTA0IDEwOS42MTQgMTAxLjgxNyAxMDkuMzE1IDEwMS40MzcgMTA5LjExQzEwMS4wNTYgMTA4Ljg5OSAxMDAuNTU4IDEwOC43OTQgOTkuOTQyNCAxMDguNzk0Qzk5LjQzODUgMTA4Ljc5NCA5OC45OTkgMTA4Ljg4OCA5OC42MjQgMTA5LjA3NUM5OC4yNDkgMTA5LjI2MyA5Ny45MzU1IDEwOS41MzggOTcuNjgzNiAxMDkuOTAxQzk3LjQzMTYgMTEwLjI2NSA5Ny4yNDEyIDExMC43MTMgOTcuMTEyMyAxMTEuMjQ2Qzk2Ljk4OTMgMTExLjc3MyA5Ni45Mjc3IDExMi4zNzcgOTYuOTI3NyAxMTMuMDU3VjExNC4xMzhDOTYuOTI3NyAxMTQuNzgyIDk2Ljk4MzQgMTE1LjM2OCA5Ny4wOTQ3IDExNS44OTZDOTcuMjExOSAxMTYuNDE3IDk3LjM4NzcgMTE2Ljg2NSA5Ny42MjIxIDExNy4yNEM5Ny44NjIzIDExNy42MTUgOTguMTY3IDExNy45MDUgOTguNTM2MSAxMTguMTFDOTguOTA1MyAxMTguMzE1IDk5LjM0NzcgMTE4LjQxOCA5OS44NjMzIDExOC40MThDMTAwLjQ5IDExOC40MTggMTAwLjk5NyAxMTguMzE4IDEwMS4zODQgMTE4LjExOUMxMDEuNzc2IDExNy45MiAxMDIuMDcyIDExNy42MyAxMDIuMjcxIDExNy4yNDlDMTAyLjQ3NyAxMTYuODYyIDEwMi42MTEgMTE2LjM5MSAxMDIuNjc2IDExNS44MzRaTTEwOS4wODQgMTA2LjVWMTIwSDEwNi45NTdWMTA2LjVIMTA5LjA4NFpNMTExLjE1IDExNS4zNTFWMTE1LjE0OEMxMTEuMTUgMTE0LjQ2MyAxMTEuMjQ5IDExMy44MjcgMTExLjQ0OCAxMTMuMjQxQzExMS42NDggMTEyLjY0OSAxMTEuOTM1IDExMi4xMzcgMTEyLjMxIDExMS43MDNDMTEyLjY5MSAxMTEuMjY0IDExMy4xNTQgMTEwLjkyNCAxMTMuNjk4IDExMC42ODRDMTE0LjI0OSAxMTAuNDM4IDExNC44NyAxMTAuMzE0IDExNS41NjIgMTEwLjMxNEMxMTYuMjU5IDExMC4zMTQgMTE2Ljg4IDExMC40MzggMTE3LjQyNSAxMTAuNjg0QzExNy45NzYgMTEwLjkyNCAxMTguNDQyIDExMS4yNjQgMTE4LjgyMiAxMTEuNzAzQzExOS4yMDMgMTEyLjEzNyAxMTkuNDkzIDExMi42NDkgMTE5LjY5MyAxMTMuMjQxQzExOS44OTIgMTEzLjgyNyAxMTkuOTkxIDExNC40NjMgMTE5Ljk5MSAxMTUuMTQ4VjExNS4zNTFDMTE5Ljk5MSAxMTYuMDM2IDExOS44OTIgMTE2LjY3MiAxMTkuNjkzIDExNy4yNThDMTE5LjQ5MyAxMTcuODQ0IDExOS4yMDMgMTE4LjM1NiAxMTguODIyIDExOC43OTZDMTE4LjQ0MiAxMTkuMjI5IDExNy45NzkgMTE5LjU2OSAxMTcuNDM0IDExOS44MTVDMTE2Ljg4OSAxMjAuMDU2IDExNi4yNzEgMTIwLjE3NiAxMTUuNTc5IDEyMC4xNzZDMTE0Ljg4MiAxMjAuMTc2IDExNC4yNTggMTIwLjA1NiAxMTMuNzA3IDExOS44MTVDMTEzLjE2MiAxMTkuNTY5IDExMi42OTkgMTE5LjIyOSAxMTIuMzE5IDExOC43OTZDMTExLjkzOCAxMTguMzU2IDExMS42NDggMTE3Ljg0NCAxMTEuNDQ4IDExNy4yNThDMTExLjI0OSAxMTYuNjcyIDExMS4xNSAxMTYuMDM2IDExMS4xNSAxMTUuMzUxWk0xMTMuMjY4IDExNS4xNDhWMTE1LjM1MUMxMTMuMjY4IDExNS43NzggMTEzLjMxMiAxMTYuMTgzIDExMy40IDExNi41NjNDMTEzLjQ4NyAxMTYuOTQ0IDExMy42MjUgMTE3LjI3OCAxMTMuODEzIDExNy41NjVDMTE0IDExNy44NTMgMTE0LjI0IDExOC4wNzggMTE0LjUzMyAxMTguMjQyQzExNC44MjYgMTE4LjQwNiAxMTUuMTc1IDExOC40ODggMTE1LjU3OSAxMTguNDg4QzExNS45NzIgMTE4LjQ4OCAxMTYuMzEyIDExOC40MDYgMTE2LjU5OSAxMTguMjQyQzExNi44OTIgMTE4LjA3OCAxMTcuMTMyIDExNy44NTMgMTE3LjMyIDExNy41NjVDMTE3LjUwNyAxMTcuMjc4IDExNy42NDUgMTE2Ljk0NCAxMTcuNzMzIDExNi41NjNDMTE3LjgyNiAxMTYuMTgzIDExNy44NzMgMTE1Ljc3OCAxMTcuODczIDExNS4zNTFWMTE1LjE0OEMxMTcuODczIDExNC43MjcgMTE3LjgyNiAxMTQuMzI4IDExNy43MzMgMTEzLjk1M0MxMTcuNjQ1IDExMy41NzIgMTE3LjUwNCAxMTMuMjM1IDExNy4zMTEgMTEyLjk0MkMxMTcuMTIzIDExMi42NDkgMTE2Ljg4MyAxMTIuNDIxIDExNi41OSAxMTIuMjU3QzExNi4zMDMgMTEyLjA4NyAxMTUuOTYgMTEyLjAwMiAxMTUuNTYyIDExMi4wMDJDMTE1LjE2MyAxMTIuMDAyIDExNC44MTggMTEyLjA4NyAxMTQuNTI1IDExMi4yNTdDMTE0LjIzNyAxMTIuNDIxIDExNCAxMTIuNjQ5IDExMy44MTMgMTEyLjk0MkMxMTMuNjI1IDExMy4yMzUgMTEzLjQ4NyAxMTMuNTcyIDExMy40IDExMy45NTNDMTEzLjMxMiAxMTQuMzI4IDExMy4yNjggMTE0LjcyNyAxMTMuMjY4IDExNS4xNDhaTTEyNy4yNTIgMTE3LjQyNUMxMjcuMjUyIDExNy4yMTQgMTI3LjE5OSAxMTcuMDIzIDEyNy4wOTQgMTE2Ljg1NEMxMjYuOTg4IDExNi42NzggMTI2Ljc4NiAxMTYuNTIgMTI2LjQ4NyAxMTYuMzc5QzEyNi4xOTQgMTE2LjIzOCAxMjUuNzYxIDExNi4xMDkgMTI1LjE4NiAxMTUuOTkyQzEyNC42ODIgMTE1Ljg4MSAxMjQuMjIgMTE1Ljc0OSAxMjMuNzk4IDExNS41OTdDMTIzLjM4MiAxMTUuNDM4IDEyMy4wMjQgMTE1LjI0OCAxMjIuNzI1IDExNS4wMjVDMTIyLjQyNyAxMTQuODAzIDEyMi4xOTUgMTE0LjUzOSAxMjIuMDMxIDExNC4yMzRDMTIxLjg2NyAxMTMuOTMgMTIxLjc4NSAxMTMuNTc4IDEyMS43ODUgMTEzLjE4QzEyMS43ODUgMTEyLjc5MyAxMjEuODcgMTEyLjQyNyAxMjIuMDQgMTEyLjA4MUMxMjIuMjEgMTExLjczNSAxMjIuNDUzIDExMS40MzEgMTIyLjc2OSAxMTEuMTY3QzEyMy4wODYgMTEwLjkwMyAxMjMuNDcgMTEwLjY5NSAxMjMuOTIxIDExMC41NDNDMTI0LjM3OCAxMTAuMzkxIDEyNC44ODggMTEwLjMxNCAxMjUuNDUgMTEwLjMxNEMxMjYuMjQ3IDExMC4zMTQgMTI2LjkyOSAxMTAuNDQ5IDEyNy40OTggMTEwLjcxOUMxMjguMDcyIDExMC45ODIgMTI4LjUxMiAxMTEuMzQzIDEyOC44MTYgMTExLjhDMTI5LjEyMSAxMTIuMjUxIDEyOS4yNzMgMTEyLjc2MSAxMjkuMjczIDExMy4zMjlIMTI3LjE1NUMxMjcuMTU1IDExMy4wNzcgMTI3LjA5MSAxMTIuODQzIDEyNi45NjIgMTEyLjYyNkMxMjYuODM5IDExMi40MDMgMTI2LjY1MSAxMTIuMjI1IDEyNi4zOTkgMTEyLjA5QzEyNi4xNDcgMTExLjk0OSAxMjUuODMxIDExMS44NzkgMTI1LjQ1IDExMS44NzlDMTI1LjA4NyAxMTEuODc5IDEyNC43ODUgMTExLjkzOCAxMjQuNTQ1IDExMi4wNTVDMTI0LjMxIDExMi4xNjYgMTI0LjEzNSAxMTIuMzEyIDEyNC4wMTcgMTEyLjQ5NEMxMjMuOTA2IDExMi42NzYgMTIzLjg1IDExMi44NzUgMTIzLjg1IDExMy4wOTJDMTIzLjg1IDExMy4yNSAxMjMuODggMTEzLjM5NCAxMjMuOTM4IDExMy41MjJDMTI0LjAwMyAxMTMuNjQ2IDEyNC4xMDggMTEzLjc2IDEyNC4yNTUgMTEzLjg2NUMxMjQuNDAxIDExMy45NjUgMTI0LjYgMTE0LjA1OSAxMjQuODUyIDExNC4xNDZDMTI1LjExIDExNC4yMzQgMTI1LjQzMiAxMTQuMzE5IDEyNS44MTkgMTE0LjQwMUMxMjYuNTQ2IDExNC41NTQgMTI3LjE3IDExNC43NSAxMjcuNjkxIDExNC45OUMxMjguMjE5IDExNS4yMjUgMTI4LjYyMyAxMTUuNTI5IDEyOC45MDQgMTE1LjkwNEMxMjkuMTg1IDExNi4yNzMgMTI5LjMyNiAxMTYuNzQyIDEyOS4zMjYgMTE3LjMxMUMxMjkuMzI2IDExNy43MzIgMTI5LjIzNSAxMTguMTE5IDEyOS4wNTQgMTE4LjQ3MUMxMjguODc4IDExOC44MTYgMTI4LjYyIDExOS4xMTggMTI4LjI4IDExOS4zNzZDMTI3Ljk0IDExOS42MjggMTI3LjUzMyAxMTkuODI0IDEyNy4wNTggMTE5Ljk2NUMxMjYuNTkgMTIwLjEwNSAxMjYuMDYyIDEyMC4xNzYgMTI1LjQ3NiAxMjAuMTc2QzEyNC42MTUgMTIwLjE3NiAxMjMuODg2IDEyMC4wMjMgMTIzLjI4OCAxMTkuNzE5QzEyMi42OSAxMTkuNDA4IDEyMi4yMzYgMTE5LjAxMyAxMjEuOTI2IDExOC41MzJDMTIxLjYyMSAxMTguMDQ2IDEyMS40NjkgMTE3LjU0MiAxMjEuNDY5IDExNy4wMjFIMTIzLjUxNkMxMjMuNTQgMTE3LjQxMyAxMjMuNjQ4IDExNy43MjcgMTIzLjg0MiAxMTcuOTYxQzEyNC4wNDEgMTE4LjE4OSAxMjQuMjg3IDExOC4zNTYgMTI0LjU4IDExOC40NjJDMTI0Ljg3OSAxMTguNTYyIDEyNS4xODYgMTE4LjYxMSAxMjUuNTAzIDExOC42MTFDMTI1Ljg4NCAxMTguNjExIDEyNi4yMDMgMTE4LjU2MiAxMjYuNDYxIDExOC40NjJDMTI2LjcxOSAxMTguMzU2IDEyNi45MTUgMTE4LjIxNiAxMjcuMDUgMTE4LjA0QzEyNy4xODQgMTE3Ljg1OCAxMjcuMjUyIDExNy42NTMgMTI3LjI1MiAxMTcuNDI1Wk0xMzUuNTIzIDEyMC4xNzZDMTM0LjgyIDEyMC4xNzYgMTM0LjE4NCAxMjAuMDYyIDEzMy42MTYgMTE5LjgzM0MxMzMuMDUzIDExOS41OTkgMTMyLjU3MyAxMTkuMjczIDEzMi4xNzQgMTE4Ljg1N0MxMzEuNzgyIDExOC40NDEgMTMxLjQ4IDExNy45NTIgMTMxLjI2OSAxMTcuMzlDMTMxLjA1OCAxMTYuODI3IDEzMC45NTMgMTE2LjIyMSAxMzAuOTUzIDExNS41N1YxMTUuMjE5QzEzMC45NTMgMTE0LjQ3NSAxMzEuMDYxIDExMy44MDEgMTMxLjI3OCAxMTMuMTk3QzEzMS40OTUgMTEyLjU5NCAxMzEuNzk2IDExMi4wNzggMTMyLjE4MyAxMTEuNjVDMTMyLjU3IDExMS4yMTcgMTMzLjAyNyAxMTAuODg2IDEzMy41NTQgMTEwLjY1N0MxMzQuMDgxIDExMC40MjkgMTM0LjY1MyAxMTAuMzE0IDEzNS4yNjggMTEwLjMxNEMxMzUuOTQ4IDExMC4zMTQgMTM2LjU0MiAxMTAuNDI5IDEzNy4wNTIgMTEwLjY1N0MxMzcuNTYyIDExMC44ODYgMTM3Ljk4NCAxMTEuMjA4IDEzOC4zMTggMTExLjYyNEMxMzguNjU4IDExMi4wMzQgMTM4LjkxIDExMi41MjMgMTM5LjA3NCAxMTMuMDkyQzEzOS4yNDQgMTEzLjY2IDEzOS4zMjkgMTE0LjI4NyAxMzkuMzI5IDExNC45NzNWMTE1Ljg3OEgxMzEuOTgxVjExNC4zNTdIMTM3LjIzN1YxMTQuMTlDMTM3LjIyNSAxMTMuODEgMTM3LjE0OSAxMTMuNDUyIDEzNy4wMDggMTEzLjExOEMxMzYuODczIDExMi43ODQgMTM2LjY2NSAxMTIuNTE1IDEzNi4zODQgMTEyLjMxQzEzNi4xMDMgMTEyLjEwNCAxMzUuNzI4IDExMi4wMDIgMTM1LjI1OSAxMTIuMDAyQzEzNC45MDggMTEyLjAwMiAxMzQuNTk0IDExMi4wNzggMTM0LjMxOSAxMTIuMjNDMTM0LjA0OSAxMTIuMzc3IDEzMy44MjQgMTEyLjU5MSAxMzMuNjQyIDExMi44NzJDMTMzLjQ2IDExMy4xNTMgMTMzLjMyIDExMy40OTMgMTMzLjIyIDExMy44OTJDMTMzLjEyNiAxMTQuMjg0IDEzMy4wNzkgMTE0LjcyNyAxMzMuMDc5IDExNS4yMTlWMTE1LjU3QzEzMy4wNzkgMTE1Ljk4NiAxMzMuMTM1IDExNi4zNzMgMTMzLjI0NiAxMTYuNzNDMTMzLjM2NCAxMTcuMDgyIDEzMy41MzQgMTE3LjM5IDEzMy43NTYgMTE3LjY1M0MxMzMuOTc5IDExNy45MTcgMTM0LjI0OCAxMTguMTI1IDEzNC41NjUgMTE4LjI3N0MxMzQuODgxIDExOC40MjQgMTM1LjI0MiAxMTguNDk3IDEzNS42NDYgMTE4LjQ5N0MxMzYuMTU2IDExOC40OTcgMTM2LjYxIDExOC4zOTUgMTM3LjAwOCAxMTguMTg5QzEzNy40MDcgMTE3Ljk4NCAxMzcuNzUyIDExNy42OTQgMTM4LjA0NSAxMTcuMzE5TDEzOS4xNjIgMTE4LjRDMTM4Ljk1NiAxMTguNjk5IDEzOC42OSAxMTguOTg2IDEzOC4zNjIgMTE5LjI2MkMxMzguMDM0IDExOS41MzEgMTM3LjYzMiAxMTkuNzUxIDEzNy4xNTggMTE5LjkyMUMxMzYuNjg5IDEyMC4wOTEgMTM2LjE0NCAxMjAuMTc2IDEzNS41MjMgMTIwLjE3NlpNMTQ2LjkzMiAxMTguMDMxVjEwNi41SDE0OS4wNTlWMTIwSDE0Ny4xMzRMMTQ2LjkzMiAxMTguMDMxWk0xNDAuNzQ0IDExNS4zNTFWMTE1LjE2NkMxNDAuNzQ0IDExNC40NDUgMTQwLjgyOSAxMTMuNzg5IDE0MC45OTkgMTEzLjE5N0MxNDEuMTY5IDExMi42IDE0MS40MTUgMTEyLjA4NyAxNDEuNzM3IDExMS42NTlDMTQyLjA2IDExMS4yMjYgMTQyLjQ1MiAxMTAuODk1IDE0Mi45MTUgMTEwLjY2NkMxNDMuMzc4IDExMC40MzIgMTQzLjg5OSAxMTAuMzE0IDE0NC40NzkgMTEwLjMxNEMxNDUuMDU0IDExMC4zMTQgMTQ1LjU1OCAxMTAuNDI2IDE0NS45OTEgMTEwLjY0OEMxNDYuNDI1IDExMC44NzEgMTQ2Ljc5NCAxMTEuMTkgMTQ3LjA5OSAxMTEuNjA2QzE0Ny40MDMgMTEyLjAxNyAxNDcuNjQ2IDExMi41MDkgMTQ3LjgyOCAxMTMuMDgzQzE0OC4wMSAxMTMuNjUxIDE0OC4xMzkgMTE0LjI4NCAxNDguMjE1IDExNC45ODFWMTE1LjU3QzE0OC4xMzkgMTE2LjI1IDE0OC4wMSAxMTYuODcxIDE0Ny44MjggMTE3LjQzNEMxNDcuNjQ2IDExNy45OTYgMTQ3LjQwMyAxMTguNDgyIDE0Ny4wOTkgMTE4Ljg5M0MxNDYuNzk0IDExOS4zMDMgMTQ2LjQyMiAxMTkuNjE5IDE0NS45ODIgMTE5Ljg0MkMxNDUuNTQ5IDEyMC4wNjQgMTQ1LjA0MiAxMjAuMTc2IDE0NC40NjIgMTIwLjE3NkMxNDMuODg4IDEyMC4xNzYgMTQzLjM2OSAxMjAuMDU2IDE0Mi45MDYgMTE5LjgxNUMxNDIuNDQ5IDExOS41NzUgMTQyLjA2IDExOS4yMzggMTQxLjczNyAxMTguODA1QzE0MS40MTUgMTE4LjM3MSAxNDEuMTY5IDExNy44NjEgMTQwLjk5OSAxMTcuMjc1QzE0MC44MjkgMTE2LjY4NCAxNDAuNzQ0IDExNi4wNDIgMTQwLjc0NCAxMTUuMzUxWk0xNDIuODYyIDExNS4xNjZWMTE1LjM1MUMxNDIuODYyIDExNS43ODQgMTQyLjkgMTE2LjE4OCAxNDIuOTc3IDExNi41NjNDMTQzLjA1OSAxMTYuOTM4IDE0My4xODUgMTE3LjI3IDE0My4zNTQgMTE3LjU1N0MxNDMuNTI0IDExNy44MzggMTQzLjc0NCAxMTguMDYxIDE0NC4wMTQgMTE4LjIyNUMxNDQuMjg5IDExOC4zODMgMTQ0LjYxNyAxMTguNDYyIDE0NC45OTggMTE4LjQ2MkMxNDUuNDc5IDExOC40NjIgMTQ1Ljg3NCAxMTguMzU2IDE0Ni4xODUgMTE4LjE0NkMxNDYuNDk1IDExNy45MzUgMTQ2LjczOCAxMTcuNjUgMTQ2LjkxNCAxMTcuMjkzQzE0Ny4wOTYgMTE2LjkzIDE0Ny4yMTkgMTE2LjUyNSAxNDcuMjgzIDExNi4wOFYxMTQuNDg5QzE0Ny4yNDggMTE0LjE0NCAxNDcuMTc1IDExMy44MjEgMTQ3LjA2MyAxMTMuNTIyQzE0Ni45NTggMTEzLjIyNCAxNDYuODE0IDExMi45NjMgMTQ2LjYzMyAxMTIuNzRDMTQ2LjQ1MSAxMTIuNTEyIDE0Ni4yMjYgMTEyLjMzNiAxNDUuOTU2IDExMi4yMTNDMTQ1LjY5MiAxMTIuMDg0IDE0NS4zNzkgMTEyLjAyIDE0NS4wMTYgMTEyLjAyQzE0NC42MjkgMTEyLjAyIDE0NC4zMDEgMTEyLjEwMiAxNDQuMDMxIDExMi4yNjZDMTQzLjc2MiAxMTIuNDMgMTQzLjUzOSAxMTIuNjU1IDE0My4zNjMgMTEyLjk0MkMxNDMuMTkzIDExMy4yMjkgMTQzLjA2NyAxMTMuNTYzIDE0Mi45ODUgMTEzLjk0NEMxNDIuOTAzIDExNC4zMjUgMTQyLjg2MiAxMTQuNzMyIDE0Mi44NjIgMTE1LjE2NloiIGZpbGw9IndoaXRlIi8+CjxkZWZzPgo8ZmlsdGVyIGlkPSJmaWx0ZXIwX2RfNDY5N18zNjcxMyIgeD0iMCIgeT0iMTIiIHdpZHRoPSIyMTYiIGhlaWdodD0iNzYiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQ29sb3JNYXRyaXggaW49IlNvdXJjZUFscGhhIiB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMTI3IDAiIHJlc3VsdD0iaGFyZEFscGhhIi8+CjxmZU9mZnNldCBkeT0iNCIvPgo8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSI0Ii8+CjxmZUNvbXBvc2l0ZSBpbjI9ImhhcmRBbHBoYSIgb3BlcmF0b3I9Im91dCIvPgo8ZmVDb2xvck1hdHJpeCB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMC4wOCAwIi8+CjxmZUJsZW5kIG1vZGU9Im5vcm1hbCIgaW4yPSJCYWNrZ3JvdW5kSW1hZ2VGaXgiIHJlc3VsdD0iZWZmZWN0MV9kcm9wU2hhZG93XzQ2OTdfMzY3MTMiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbj0iU291cmNlR3JhcGhpYyIgaW4yPSJlZmZlY3QxX2Ryb3BTaGFkb3dfNDY5N18zNjcxMyIgcmVzdWx0PSJzaGFwZSIvPgo8L2ZpbHRlcj4KPC9kZWZzPgo8L3N2Zz4K", + "description": "Sends the command to the device or updates attribute/time-series when the user toggles the button. Widget settings will enable you to configure behavior how to fetch the initial state and what to trigger when button checked/unchecked states.", + "descriptor": { + "type": "rpc", + "sizeX": 4, + "sizeY": 2, + "resources": [], + "templateHtml": "\n", + "templateCss": "", + "controllerScript": "self.onInit = function() {\n self.ctx.$scope.actionWidget.onInit();\n}\n\nself.typeParameters = function() {\n return {\n previewWidth: '300px',\n previewHeight: '150px',\n embedTitlePanel: true,\n displayRpcMessageToast: false\n };\n};\n\nself.onDestroy = function() {\n}\n", + "settingsSchema": "", + "dataKeySettingsSchema": "{}\n", + "settingsDirective": "tb-toggle-button-widget-settings", + "hasBasicMode": true, + "basicModeDirective": "tb-toggle-button-basic-config", + "defaultConfig": "{\"showTitle\":true,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{},\"title\":\"Door\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"actions\":{},\"widgetCss\":\"\",\"noDataDisplayMessage\":\"\",\"titleFont\":{\"size\":16,\"sizeUnit\":\"px\",\"family\":\"Roboto\",\"weight\":\"500\",\"style\":null,\"lineHeight\":\"1.6\"},\"showTitleIcon\":false,\"titleTooltip\":\"\",\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"pageSize\":1024,\"titleIcon\":\"home\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"configMode\":\"basic\",\"targetDevice\":null,\"titleColor\":null,\"borderRadius\":null}" + }, + "tags": [ + "command", + "downlink", + "device configuration", + "device control", + "invocation", + "remote method", + "remote function", + "interface", + "subroutine call", + "inter-process communication", + "server request", + "toggle", + "button" + ] +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts index 32a6a755b4..c4aaac2a9e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/basic-widget-config.module.ts @@ -104,6 +104,9 @@ import { PowerButtonBasicConfigComponent } from '@home/components/widget/config/basic/button/power-button-basic-config.component'; import { SliderBasicConfigComponent } from '@home/components/widget/config/basic/rpc/slider-basic-config.component'; +import { + ToggleButtonBasicConfigComponent +} from '@home/components/widget/config/basic/button/toggle-button-basic-config.component'; @NgModule({ declarations: [ @@ -137,7 +140,8 @@ import { SliderBasicConfigComponent } from '@home/components/widget/config/basic ActionButtonBasicConfigComponent, CommandButtonBasicConfigComponent, PowerButtonBasicConfigComponent, - SliderBasicConfigComponent + SliderBasicConfigComponent, + ToggleButtonBasicConfigComponent ], imports: [ CommonModule, @@ -175,7 +179,8 @@ import { SliderBasicConfigComponent } from '@home/components/widget/config/basic ActionButtonBasicConfigComponent, CommandButtonBasicConfigComponent, PowerButtonBasicConfigComponent, - SliderBasicConfigComponent + SliderBasicConfigComponent, + ToggleButtonBasicConfigComponent ] }) export class BasicWidgetConfigModule { @@ -207,5 +212,6 @@ export const basicWidgetConfigComponentsMap: {[key: string]: Type
    widgets.power-button.power-on
    + + +
    +
    widgets.toggle-button.behavior
    +
    +
    widgets.rpc-state.initial-state
    + +
    +
    +
    widgets.toggle-button.check
    + +
    +
    +
    widgets.toggle-button.uncheck
    + +
    +
    +
    widgets.rpc-state.disabled-state
    + +
    +
    +
    +
    widget-config.appearance
    +
    + + + + + {{ 'widgets.toggle-button.auto-scale' | translate }} + + + + +
    + + {{ 'widgets.toggle-button.horizontal-fill' | translate }} + +
    +
    + + {{ 'widgets.toggle-button.vertical-fill' | translate }} + +
    +
    +
    +
    +
    + + {{ 'widget-config.title' | translate }} + +
    + + + + + + + +
    +
    +
    + + {{ 'widget-config.card-icon' | translate }} + +
    + + + + + + + + +
    +
    +
    +
    +
    +
    widgets.toggle-button.button-appearance
    + + {{ 'widgets.toggle-button.checked' | translate }} + {{ 'widgets.toggle-button.unchecked' | translate }} + +
    + + + + +
    +
    +
    widget-config.card-appearance
    +
    +
    {{ 'widgets.background.background' | translate }}
    + + +
    +
    +
    widget-config.show-card-buttons
    + + {{ 'fullscreen.fullscreen' | translate }} + +
    +
    +
    {{ 'widget-config.card-border-radius' | translate }}
    + + + +
    +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/button/toggle-button-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/toggle-button-basic-config.component.ts new file mode 100644 index 0000000000..e93a3a9e38 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/button/toggle-button-basic-config.component.ts @@ -0,0 +1,192 @@ +/// +/// 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 { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { BasicWidgetConfigComponent } from '@home/components/widget/config/widget-config.component.models'; +import { WidgetConfigComponentData } from '@home/models/widget-component.models'; +import { TargetDevice, TargetDeviceType, WidgetConfig, } from '@shared/models/widget.models'; +import { WidgetConfigComponent } from '@home/components/widget/widget-config.component'; +import { isUndefined } from '@core/utils'; +import { ValueType } from '@shared/models/constants'; +import { cssSizeToStrSize, resolveCssSize } from '@shared/models/widget-settings.models'; +import { + toggleButtonDefaultSettings, + ToggleButtonWidgetSettings +} from '@home/components/widget/lib/button/toggle-button-widget.models'; + +type ButtonAppearanceType = 'checked' | 'unchecked'; + +@Component({ + selector: 'tb-toggle-button-basic-config', + templateUrl: './toggle-button-basic-config.component.html', + styleUrls: ['../basic-config.scss'] +}) +export class ToggleButtonBasicConfigComponent extends BasicWidgetConfigComponent { + + get targetDevice(): TargetDevice { + return this.toggleButtonWidgetConfigForm.get('targetDevice').value; + } + + valueType = ValueType; + + buttonAppearanceType: ButtonAppearanceType = 'checked'; + + toggleButtonWidgetConfigForm: UntypedFormGroup; + + constructor(protected store: Store, + protected widgetConfigComponent: WidgetConfigComponent, + private fb: UntypedFormBuilder) { + super(store, widgetConfigComponent); + } + + protected configForm(): UntypedFormGroup { + return this.toggleButtonWidgetConfigForm; + } + + protected onConfigSet(configData: WidgetConfigComponentData) { + const settings: ToggleButtonWidgetSettings = {...toggleButtonDefaultSettings, ...(configData.config.settings || {})}; + const iconSize = resolveCssSize(configData.config.iconSize); + this.toggleButtonWidgetConfigForm = this.fb.group({ + targetDevice: [configData.config.targetDevice, []], + + initialState: [settings.initialState, []], + checkState: [settings.checkState, []], + uncheckState: [settings.uncheckState, []], + disabledState: [settings.disabledState, []], + + showTitle: [configData.config.showTitle, []], + title: [configData.config.title, []], + titleFont: [configData.config.titleFont, []], + titleColor: [configData.config.titleColor, []], + + showIcon: [configData.config.showTitleIcon, []], + iconSize: [iconSize[0], [Validators.min(0)]], + iconSizeUnit: [iconSize[1], []], + icon: [configData.config.titleIcon, []], + iconColor: [configData.config.iconColor, []], + + autoScale: [settings.autoScale, []], + horizontalFill: [settings.horizontalFill, []], + verticalFill: [settings.verticalFill, []], + + checkedAppearance: [settings.checkedAppearance, []], + uncheckedAppearance: [settings.uncheckedAppearance, []], + + background: [settings.background, []], + + cardButtons: [this.getCardButtons(configData.config), []], + borderRadius: [configData.config.borderRadius, []], + + actions: [configData.config.actions || {}, []] + }); + } + + protected prepareOutputConfig(config: any): WidgetConfigComponentData { + this.widgetConfig.config.targetDevice = config.targetDevice; + + this.widgetConfig.config.showTitle = config.showTitle; + this.widgetConfig.config.title = config.title; + this.widgetConfig.config.titleFont = config.titleFont; + this.widgetConfig.config.titleColor = config.titleColor; + + this.widgetConfig.config.showTitleIcon = config.showIcon; + this.widgetConfig.config.iconSize = cssSizeToStrSize(config.iconSize, config.iconSizeUnit); + this.widgetConfig.config.titleIcon = config.icon; + this.widgetConfig.config.iconColor = config.iconColor; + + this.widgetConfig.config.settings = this.widgetConfig.config.settings || {}; + + this.widgetConfig.config.settings.initialState = config.initialState; + this.widgetConfig.config.settings.checkState = config.checkState; + this.widgetConfig.config.settings.uncheckState = config.uncheckState; + this.widgetConfig.config.settings.disabledState = config.disabledState; + + this.widgetConfig.config.settings.autoScale = config.autoScale; + this.widgetConfig.config.settings.horizontalFill = config.horizontalFill; + this.widgetConfig.config.settings.verticalFill = config.verticalFill; + + this.widgetConfig.config.settings.checkedAppearance = config.checkedAppearance; + this.widgetConfig.config.settings.uncheckedAppearance = config.uncheckedAppearance; + + this.widgetConfig.config.settings.background = config.background; + + this.setCardButtons(config.cardButtons, this.widgetConfig.config); + this.widgetConfig.config.borderRadius = config.borderRadius; + + this.widgetConfig.config.actions = config.actions; + return this.widgetConfig; + } + + protected validatorTriggers(): string[] { + return ['showTitle', 'showIcon', 'autoScale']; + } + + protected updateValidators(emitEvent: boolean, trigger?: string) { + const showTitle: boolean = this.toggleButtonWidgetConfigForm.get('showTitle').value; + const showIcon: boolean = this.toggleButtonWidgetConfigForm.get('showIcon').value; + const autoScale: boolean = this.toggleButtonWidgetConfigForm.get('autoScale').value; + if (showTitle) { + this.toggleButtonWidgetConfigForm.get('title').enable(); + this.toggleButtonWidgetConfigForm.get('titleFont').enable(); + this.toggleButtonWidgetConfigForm.get('titleColor').enable(); + this.toggleButtonWidgetConfigForm.get('showIcon').enable({emitEvent: false}); + if (showIcon) { + this.toggleButtonWidgetConfigForm.get('iconSize').enable(); + this.toggleButtonWidgetConfigForm.get('iconSizeUnit').enable(); + this.toggleButtonWidgetConfigForm.get('icon').enable(); + this.toggleButtonWidgetConfigForm.get('iconColor').enable(); + } else { + this.toggleButtonWidgetConfigForm.get('iconSize').disable(); + this.toggleButtonWidgetConfigForm.get('iconSizeUnit').disable(); + this.toggleButtonWidgetConfigForm.get('icon').disable(); + this.toggleButtonWidgetConfigForm.get('iconColor').disable(); + } + } else { + this.toggleButtonWidgetConfigForm.get('title').disable(); + this.toggleButtonWidgetConfigForm.get('titleFont').disable(); + this.toggleButtonWidgetConfigForm.get('titleColor').disable(); + this.toggleButtonWidgetConfigForm.get('showIcon').disable({emitEvent: false}); + this.toggleButtonWidgetConfigForm.get('iconSize').disable(); + this.toggleButtonWidgetConfigForm.get('iconSizeUnit').disable(); + this.toggleButtonWidgetConfigForm.get('icon').disable(); + this.toggleButtonWidgetConfigForm.get('iconColor').disable(); + } + if (autoScale) { + this.toggleButtonWidgetConfigForm.get('horizontalFill').disable(); + this.toggleButtonWidgetConfigForm.get('verticalFill').disable(); + } else { + this.toggleButtonWidgetConfigForm.get('horizontalFill').enable(); + this.toggleButtonWidgetConfigForm.get('verticalFill').enable(); + } + } + + private getCardButtons(config: WidgetConfig): string[] { + const buttons: string[] = []; + if (isUndefined(config.enableFullscreen) || config.enableFullscreen) { + buttons.push('fullscreen'); + } + return buttons; + } + + private setCardButtons(buttons: string[], config: WidgetConfig) { + config.enableFullscreen = buttons.includes('fullscreen'); + } + + protected readonly TargetDeviceType = TargetDeviceType; +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.html new file mode 100644 index 0000000000..366b7d3290 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.html @@ -0,0 +1,34 @@ + +
    +
    + +
    + + +
    + +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.scss new file mode 100644 index 0000000000..07cc8599e2 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.scss @@ -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. + */ +.tb-toggle-button-panel { + width: 100%; + height: 100%; + position: relative; + display: flex; + flex-direction: column; + gap: 8px; + padding: 20px 24px 24px 24px; + + > div:not(.tb-toggle-button-overlay) { + z-index: 1; + } + + .tb-toggle-button-overlay { + position: absolute; + top: 12px; + left: 12px; + bottom: 12px; + right: 12px; + } + + div.tb-widget-title { + padding: 0; + } + + .tb-toggle-button-container { + flex: 1; + min-width: 0; + min-height: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + &.auto-scale { + tb-widget-button { + flex: 1; + min-width: 0; + min-height: 0; + width: 100%; + height: 100%; + } + } + &.horizontal-fill { + tb-widget-button { + width: 100%; + } + } + &.vertical-fill { + tb-widget-button { + height: 100%; + } + } + } + +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.ts new file mode 100644 index 0000000000..b6943775a7 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.component.ts @@ -0,0 +1,142 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { AfterViewInit, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { BasicActionWidgetComponent, ValueSetter } from '@home/components/widget/lib/action/action-widget.models'; +import { ImagePipe } from '@shared/pipe/image.pipe'; +import { DomSanitizer } from '@angular/platform-browser'; +import { ValueType } from '@shared/models/constants'; +import { WidgetButtonAppearance } from '@shared/components/button/widget-button.models'; +import { + toggleButtonDefaultSettings, + ToggleButtonWidgetSettings +} from '@home/components/widget/lib/button/toggle-button-widget.models'; +import { Observable } from 'rxjs'; +import { backgroundStyle, ComponentStyle, overlayStyle } from '@shared/models/widget-settings.models'; + +@Component({ + selector: 'tb-toggle-button-widget', + templateUrl: './toggle-button-widget.component.html', + styleUrls: ['../action/action-widget.scss', './toggle-button-widget.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class ToggleButtonWidgetComponent extends + BasicActionWidgetComponent implements OnInit, AfterViewInit, OnDestroy { + + settings: ToggleButtonWidgetSettings; + + backgroundStyle$: Observable; + overlayStyle: ComponentStyle = {}; + + value = false; + disabled = false; + + autoScale: boolean; + horizontalFill: boolean; + verticalFill: boolean; + appearance: WidgetButtonAppearance; + + private checkValueSetter: ValueSetter; + private uncheckValueSetter: ValueSetter; + + constructor(protected imagePipe: ImagePipe, + protected sanitizer: DomSanitizer, + protected cd: ChangeDetectorRef) { + super(cd); + } + + ngOnInit(): void { + super.ngOnInit(); + this.settings = {...toggleButtonDefaultSettings, ...this.ctx.settings}; + + this.autoScale = this.settings.autoScale; + this.horizontalFill = this.settings.horizontalFill; + this.verticalFill = this.settings.verticalFill; + + this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); + this.overlayStyle = overlayStyle(this.settings.background.overlay); + + const getInitialStateSettings = + {...this.settings.initialState, actionLabel: this.ctx.translate.instant('widgets.rpc-state.initial-state')}; + this.createValueGetter(getInitialStateSettings, ValueType.BOOLEAN, { + next: (value) => this.onValue(value) + }); + + const disabledStateSettings = + {...this.settings.disabledState, actionLabel: this.ctx.translate.instant('widgets.button-state.disabled-state')}; + this.createValueGetter(disabledStateSettings, ValueType.BOOLEAN, { + next: (value) => this.onDisabled(value) + }); + + const checkStateSettings = {...this.settings.checkState, + actionLabel: this.ctx.translate.instant('widgets.toggle-button.check')}; + this.checkValueSetter = this.createValueSetter(checkStateSettings); + + const uncheckStateSettings = {...this.settings.uncheckState, + actionLabel: this.ctx.translate.instant('widgets.toggle-button.uncheck')}; + this.uncheckValueSetter = this.createValueSetter(uncheckStateSettings); + + this.appearance = this.value ? this.settings.checkedAppearance : this.settings.uncheckedAppearance; + } + + ngAfterViewInit(): void { + super.ngAfterViewInit(); + } + + ngOnDestroy() { + super.ngOnDestroy(); + } + + public onInit() { + super.onInit(); + const borderRadius = this.ctx.$widgetElement.css('borderRadius'); + this.overlayStyle = {...this.overlayStyle, ...{borderRadius}}; + this.cd.detectChanges(); + } + + private onValue(value: boolean): void { + const newValue = !!value; + if (this.value !== newValue) { + this.value = newValue; + this.appearance = this.value ? this.settings.checkedAppearance : this.settings.uncheckedAppearance; + this.cd.markForCheck(); + } + } + + private onDisabled(value: boolean): void { + const newDisabled = !!value; + if (this.disabled !== newDisabled) { + this.disabled = newDisabled; + this.cd.markForCheck(); + } + } + + public onClick(_$event: MouseEvent) { + if (!this.ctx.isEdit && !this.ctx.isPreview) { + this.onValue(!this.value); + const targetValue = this.value; + const targetSetter = targetValue ? this.checkValueSetter : this.uncheckValueSetter; + this.updateValue(targetSetter, targetValue, { + next: () => { + this.onValue(targetValue); + }, + error: () => { + this.onValue(!targetValue); + } + }); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.models.ts new file mode 100644 index 0000000000..8307a09bd3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/button/toggle-button-widget.models.ts @@ -0,0 +1,143 @@ +/// +/// 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 { + WidgetButtonAppearance, + widgetButtonDefaultAppearance, + WidgetButtonType +} from '@shared/components/button/widget-button.models'; +import { + DataToValueType, + GetValueAction, + GetValueSettings, + SetValueAction, + SetValueSettings, + ValueToDataType +} from '@shared/models/action-widget-settings.models'; +import { BackgroundSettings, BackgroundType } from '@shared/models/widget-settings.models'; +import { AttributeScope } from '@shared/models/telemetry/telemetry.models'; + +export interface ToggleButtonWidgetSettings { + initialState: GetValueSettings; + disabledState: GetValueSettings; + checkState: SetValueSettings; + uncheckState: SetValueSettings; + autoScale: boolean; + horizontalFill: boolean; + verticalFill: boolean; + checkedAppearance: WidgetButtonAppearance; + uncheckedAppearance: WidgetButtonAppearance; + background: BackgroundSettings; +} + +export const toggleButtonDefaultSettings: ToggleButtonWidgetSettings = { + initialState: { + action: GetValueAction.EXECUTE_RPC, + defaultValue: false, + executeRpc: { + method: 'getState', + requestTimeout: 5000, + requestPersistent: false, + persistentPollingInterval: 1000 + }, + getAttribute: { + key: 'state', + scope: null + }, + getTimeSeries: { + key: 'state' + }, + dataToValue: { + type: DataToValueType.NONE, + compareToValue: true, + dataToValueFunction: '/* Should return boolean value */\nreturn data;' + } + }, + disabledState: { + action: GetValueAction.DO_NOTHING, + defaultValue: false, + getAttribute: { + key: 'state', + scope: null + }, + getTimeSeries: { + key: 'state' + }, + dataToValue: { + type: DataToValueType.NONE, + compareToValue: true, + dataToValueFunction: '/* Should return boolean value */\nreturn data;' + } + }, + checkState: { + action: SetValueAction.EXECUTE_RPC, + executeRpc: { + method: 'setState', + requestTimeout: 5000, + requestPersistent: false, + persistentPollingInterval: 1000 + }, + setAttribute: { + key: 'state', + scope: AttributeScope.SHARED_SCOPE + }, + putTimeSeries: { + key: 'state' + }, + valueToData: { + type: ValueToDataType.CONSTANT, + constantValue: true, + valueToDataFunction: '/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;' + } + }, + uncheckState: { + action: SetValueAction.EXECUTE_RPC, + executeRpc: { + method: 'setState', + requestTimeout: 5000, + requestPersistent: false, + persistentPollingInterval: 1000 + }, + setAttribute: { + key: 'state', + scope: AttributeScope.SHARED_SCOPE + }, + putTimeSeries: { + key: 'state' + }, + valueToData: { + type: ValueToDataType.CONSTANT, + constantValue: false, + valueToDataFunction: '/* Convert input boolean value to RPC parameters or attribute/time-series value */ \n return value;' + } + }, + autoScale: true, + horizontalFill: true, + verticalFill: false, + checkedAppearance: {...widgetButtonDefaultAppearance, + type: WidgetButtonType.outlined, mainColor: '#198038', label: 'Opened', icon: 'mdi:lock-open-variant', borderRadius: '4px'}, + uncheckedAppearance: {...widgetButtonDefaultAppearance, + type: WidgetButtonType.filled, mainColor: '#D12730', label: 'Closed', icon: 'lock', borderRadius: '4px'}, + background: { + type: BackgroundType.color, + color: '#fff', + overlay: { + enabled: false, + color: 'rgba(255,255,255,0.72)', + blur: 3 + } + } +}; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.html new file mode 100644 index 0000000000..3a7e5865c1 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.html @@ -0,0 +1,119 @@ + + +
    +
    widgets.toggle-button.behavior
    +
    +
    widgets.rpc-state.initial-state
    + +
    +
    +
    widgets.toggle-button.check
    + +
    +
    +
    widgets.toggle-button.uncheck
    + +
    +
    +
    widgets.rpc-state.disabled-state
    + +
    +
    +
    +
    widget-config.appearance
    +
    + + + + + {{ 'widgets.toggle-button.auto-scale' | translate }} + + + + +
    + + {{ 'widgets.toggle-button.horizontal-fill' | translate }} + +
    +
    + + {{ 'widgets.toggle-button.vertical-fill' | translate }} + +
    +
    +
    +
    +
    +
    {{ 'widgets.background.background' | translate }}
    + + +
    +
    +
    +
    +
    widgets.toggle-button.button-appearance
    + + {{ 'widgets.toggle-button.checked' | translate }} + {{ 'widgets.toggle-button.unchecked' | translate }} + +
    + + + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.ts new file mode 100644 index 0000000000..04788e3a14 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/button/toggle-button-widget-settings.component.ts @@ -0,0 +1,94 @@ +/// +/// 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 { TargetDevice, WidgetSettings, WidgetSettingsComponent, widgetType } from '@shared/models/widget.models'; +import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { ValueType } from '@shared/models/constants'; +import { toggleButtonDefaultSettings } from '@home/components/widget/lib/button/toggle-button-widget.models'; + +type ButtonAppearanceType = 'checked' | 'unchecked'; + +@Component({ + selector: 'tb-toggle-button-widget-settings', + templateUrl: './toggle-button-widget-settings.component.html', + styleUrls: ['./../widget-settings.scss'] +}) +export class ToggleButtonWidgetSettingsComponent extends WidgetSettingsComponent { + + get targetDevice(): TargetDevice { + return this.widgetConfig?.config?.targetDevice; + } + + get widgetType(): widgetType { + return this.widgetConfig?.widgetType; + } + + valueType = ValueType; + + buttonAppearanceType: ButtonAppearanceType = 'checked'; + + toggleButtonWidgetSettingsForm: UntypedFormGroup; + + constructor(protected store: Store, + private fb: UntypedFormBuilder) { + super(store); + } + + protected settingsForm(): UntypedFormGroup { + return this.toggleButtonWidgetSettingsForm; + } + + protected defaultSettings(): WidgetSettings { + return {...toggleButtonDefaultSettings}; + } + + protected onSettingsSet(settings: WidgetSettings) { + this.toggleButtonWidgetSettingsForm = this.fb.group({ + initialState: [settings.initialState, []], + checkState: [settings.checkState, []], + uncheckState: [settings.uncheckState, []], + disabledState: [settings.disabledState, []], + + autoScale: [settings.autoScale, []], + horizontalFill: [settings.horizontalFill, []], + verticalFill: [settings.verticalFill, []], + + checkedAppearance: [settings.checkedAppearance, []], + uncheckedAppearance: [settings.uncheckedAppearance, []], + + background: [settings.background, []] + }); + } + + protected validatorTriggers(): string[] { + return ['autoScale']; + } + + protected updateValidators(emitEvent: boolean) { + const autoScale: boolean = this.toggleButtonWidgetSettingsForm.get('autoScale').value; + + if (autoScale) { + this.toggleButtonWidgetSettingsForm.get('horizontalFill').disable(); + this.toggleButtonWidgetSettingsForm.get('verticalFill').disable(); + } else { + this.toggleButtonWidgetSettingsForm.get('horizontalFill').enable(); + this.toggleButtonWidgetSettingsForm.get('verticalFill').enable(); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings-panel.component.html index 4cf5857612..4fc8f1fdce 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/set-value-action-settings-panel.component.html @@ -97,7 +97,7 @@
    {{ (setValueSettingsFormGroup.get('action').value === setValueAction.EXECUTE_RPC ? 'widgets.value-action.parameters' : 'widgets.value-action.value') | translate }}
    - {{ 'widgets.value-action.converter-value' | translate }} + {{ 'widgets.value-action.converter-value' | translate }} {{ 'widgets.value-action.converter-constant' | translate }} {{ 'widgets.value-action.converter-function' | translate }} -
    +
    {{ 'widgets.button.auto-scale' | translate }} @@ -56,6 +56,10 @@
    +
    +
    {{ 'widgets.button.border-radius' | translate }}
    + +
    {{ 'widgets.button.color-palette' | translate }}
    @@ -88,6 +92,7 @@ [state]="state" [appearance]="this.appearanceFormGroup.value" [borderRadius]="borderRadius" + [autoScale]="autoScale" [formControlName]="state">
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.ts index d8756e3e31..f9afc0b5d1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-appearance.component.ts @@ -24,6 +24,7 @@ import { widgetButtonTypeTranslations } from '@shared/components/button/widget-button.models'; import { merge } from 'rxjs'; +import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ selector: 'tb-widget-button-appearance', @@ -46,6 +47,17 @@ export class WidgetButtonAppearanceComponent implements OnInit, ControlValueAcce @Input() borderRadius: string; + @Input() + autoScale: boolean; + + @Input() + @coerceBoolean() + withAutoScale = true; + + @Input() + @coerceBoolean() + withBorderRadius = false; + widgetButtonTypes = widgetButtonTypes; widgetButtonTypeTranslationMap = widgetButtonTypeTranslations; @@ -65,7 +77,6 @@ export class WidgetButtonAppearanceComponent implements OnInit, ControlValueAcce ngOnInit(): void { this.appearanceFormGroup = this.fb.group({ type: [null, []], - autoScale: [null, []], showLabel: [null, []], label: [null, []], showIcon: [null, []], @@ -75,6 +86,12 @@ export class WidgetButtonAppearanceComponent implements OnInit, ControlValueAcce mainColor: [null, []], backgroundColor: [null, []] }); + if (this.withAutoScale) { + this.appearanceFormGroup.addControl('autoScale', this.fb.control(null, [])); + } + if (this.withBorderRadius) { + this.appearanceFormGroup.addControl('borderRadius', this.fb.control(null, [])); + } const customStyle = this.fb.group({}); for (const state of widgetButtonStates) { customStyle.addControl(state, this.fb.control(null, [])); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.html index e5750fd4bb..86b5acde6e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.html @@ -51,6 +51,7 @@ #widgetButtonPreview [appearance]="previewAppearance" [borderRadius]="borderRadius" + [autoScale]="autoScale" disableEvents [hovered]="state === widgetButtonState.hovered" [pressed]="state === widgetButtonState.pressed" diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.ts index cab7ab8b00..5bb043b9d8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style-panel.component.ts @@ -61,6 +61,9 @@ export class WidgetButtonCustomStylePanelComponent extends PageComponent impleme @Input() borderRadius: string; + @Input() + autoScale: boolean; + @Input() state: WidgetButtonState; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style.component.html index 3b78af6d5d..dd2f43afa9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/button/widget-button-custom-style.component.html @@ -20,6 +20,7 @@
    - + - +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-size-input.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-size-input.component.ts index dcd579e071..099778e924 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-size-input.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/css-size-input.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, forwardRef, HostBinding, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, NG_VALIDATORS, @@ -48,6 +48,16 @@ import { isDefinedAndNotNull } from '@core/utils'; }) export class CssSizeInputComponent implements OnInit, ControlValueAccessor, Validator { + @HostBinding('style.width') + get hostWidth(): string { + return this.flex ? '100%' : null; + } + + @HostBinding('style.flex') + get hostFlex(): string { + return this.flex ? '1' : null; + } + @Input() disabled: boolean; @@ -62,6 +72,10 @@ export class CssSizeInputComponent implements OnInit, ControlValueAccessor, Vali @coerceBoolean() allowEmptyUnit = false; + @Input() + @coerceBoolean() + flex = false; + cssSizeFormGroup: UntypedFormGroup; modelValue: string; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts index 8fc6ef96c2..2943b4cc09 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/widget-settings.module.ts @@ -327,6 +327,9 @@ import { import { SliderWidgetSettingsComponent } from '@home/components/widget/lib/settings/control/slider-widget-settings.component'; +import { + ToggleButtonWidgetSettingsComponent +} from '@home/components/widget/lib/settings/button/toggle-button-widget-settings.component'; @NgModule({ declarations: [ @@ -444,7 +447,8 @@ import { ActionButtonWidgetSettingsComponent, CommandButtonWidgetSettingsComponent, PowerButtonWidgetSettingsComponent, - SliderWidgetSettingsComponent + SliderWidgetSettingsComponent, + ToggleButtonWidgetSettingsComponent ], imports: [ CommonModule, @@ -567,7 +571,8 @@ import { ActionButtonWidgetSettingsComponent, CommandButtonWidgetSettingsComponent, PowerButtonWidgetSettingsComponent, - SliderWidgetSettingsComponent + SliderWidgetSettingsComponent, + ToggleButtonWidgetSettingsComponent ] }) export class WidgetSettingsModule { @@ -657,5 +662,6 @@ export const widgetSettingsComponentsMap: {[key: string]: Type
    {{ appearance.icon }} diff --git a/ui-ngx/src/app/shared/components/button/widget-button.component.scss b/ui-ngx/src/app/shared/components/button/widget-button.component.scss index a0abc95731..157f6b179a 100644 --- a/ui-ngx/src/app/shared/components/button/widget-button.component.scss +++ b/ui-ngx/src/app/shared/components/button/widget-button.component.scss @@ -70,7 +70,11 @@ $boxShadowColorDisabled: var(--tb-widget-button-box-shadow-color-disabled, $defa .mat-mdc-button.mat-mdc-button-base.tb-widget-button { width: 100%; height: 100%; + min-width: 0; padding: 8px 12px; + &.tb-icon-only { + padding: 8px; + } .mdc-button__label { width: 100%; height: 100%; diff --git a/ui-ngx/src/app/shared/components/button/widget-button.component.ts b/ui-ngx/src/app/shared/components/button/widget-button.component.ts index 059f263196..db6584d96f 100644 --- a/ui-ngx/src/app/shared/components/button/widget-button.component.ts +++ b/ui-ngx/src/app/shared/components/button/widget-button.component.ts @@ -34,11 +34,12 @@ import { widgetButtonDefaultAppearance } from '@shared/components/button/widget-button.models'; import { coerceBoolean } from '@shared/decorators/coercion'; -import { ComponentStyle, iconStyle } from '@shared/models/widget-settings.models'; +import { ComponentStyle, iconStyle, validateCssSize } from '@shared/models/widget-settings.models'; import { UtilsService } from '@core/services/utils.service'; import { ResizeObserver } from '@juggle/resize-observer'; import { Observable, of } from 'rxjs'; import { WidgetContext } from '@home/models/widget-component.models'; +import { isDefinedAndNotNull, isNotEmptyStr } from '@core/utils'; const initialButtonHeight = 60; const horizontalLayoutPadding = 24; @@ -64,6 +65,9 @@ export class WidgetButtonComponent implements OnInit, AfterViewInit, OnDestroy, @Input() borderRadius = '4px'; + @Input() + autoScale: boolean; + @Input() @coerceBoolean() disabled = false; @@ -94,6 +98,8 @@ export class WidgetButtonComponent implements OnInit, AfterViewInit, OnDestroy, iconStyle: ComponentStyle = {}; + computedBorderRadius: string; + mousePressed = false; private buttonResize$: ResizeObserver; @@ -114,6 +120,10 @@ export class WidgetButtonComponent implements OnInit, AfterViewInit, OnDestroy, if (!change.firstChange) { if (propName === 'appearance') { this.updateAppearance(); + } else if (propName === 'borderRadius') { + this.updateBorderRadius(); + } else if (propName === 'autoScale') { + this.updateAutoScale(); } } } @@ -144,12 +154,22 @@ export class WidgetButtonComponent implements OnInit, AfterViewInit, OnDestroy, if (this.appearance.showLabel) { this.label$ = this.ctx ? this.ctx.registerLabelPattern(this.appearance.label, this.label$) : of(this.appearance.label); } + this.updateBorderRadius(); const appearanceCss = generateWidgetButtonAppearanceCss(this.appearance); this.appearanceCssClass = this.utils.applyCssToElement(this.renderer, this.elementRef.nativeElement, 'tb-widget-button', appearanceCss); this.updateAutoScale(); } + private updateBorderRadius(): void { + const validatedBorderRadius = validateCssSize(this.appearance.borderRadius); + if (validatedBorderRadius) { + this.computedBorderRadius = validatedBorderRadius; + } else { + this.computedBorderRadius = this.borderRadius; + } + } + private clearAppearanceCss(): void { if (this.appearanceCssClass) { this.utils.clearCssElement(this.renderer, this.appearanceCssClass, this.elementRef?.nativeElement); @@ -162,7 +182,8 @@ export class WidgetButtonComponent implements OnInit, AfterViewInit, OnDestroy, this.buttonResize$.disconnect(); } if (this.widgetButton && this.widgetButtonContent) { - if (this.appearance.autoScale) { + const autoScale = isDefinedAndNotNull(this.autoScale) ? this.autoScale : this.appearance.autoScale; + if (autoScale) { this.buttonResize$ = new ResizeObserver(() => { this.onResize(); }); diff --git a/ui-ngx/src/app/shared/components/button/widget-button.models.ts b/ui-ngx/src/app/shared/components/button/widget-button.models.ts index 34f13864a9..b81cd43f5d 100644 --- a/ui-ngx/src/app/shared/components/button/widget-button.models.ts +++ b/ui-ngx/src/app/shared/components/button/widget-button.models.ts @@ -98,6 +98,7 @@ export interface WidgetButtonAppearance { icon: string; iconSize: number; iconSizeUnit: cssUnit; + borderRadius?: string; mainColor: string; backgroundColor: string; customStyle: WidgetButtonCustomStyles; diff --git a/ui-ngx/src/app/shared/models/widget-settings.models.ts b/ui-ngx/src/app/shared/models/widget-settings.models.ts index 5bd9e26f13..8e60c0d9cb 100644 --- a/ui-ngx/src/app/shared/models/widget-settings.models.ts +++ b/ui-ngx/src/app/shared/models/widget-settings.models.ts @@ -21,7 +21,8 @@ import { Datasource, DatasourceData, DatasourceType, - TargetDevice, TargetDeviceType + TargetDevice, + TargetDeviceType } from '@shared/models/widget.models'; import { Injector } from '@angular/core'; import { DatePipe } from '@angular/common'; @@ -232,6 +233,15 @@ export const resolveCssSize = (strSize?: string): [number, cssUnit] => { return [numericSize, resolvedUnit]; }; +export const validateCssSize = (strSize?: string): string | undefined => { + const resolved = resolveCssSize(strSize); + if (!!resolved[0] && !!resolved[1]) { + return cssSizeToStrSize(resolved[0], resolved[1]); + } else { + return undefined; + } +}; + type ValueColorFunction = (value: any) => string; export abstract class ColorProcessor { 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 c71f33fca7..0bc4565bf5 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -5231,6 +5231,19 @@ "disabled-colors": "Disabled colors", "button": "Button" }, + "toggle-button": { + "behavior": "Behavior", + "checked": "Checked", + "unchecked": "Unchecked", + "check": "Check", + "check-hint": "Action performed to check the component.", + "uncheck": "Uncheck", + "uncheck-hint": "Action performed to uncheck the component.", + "auto-scale": "Auto scale", + "horizontal-fill": "Horizontal fill", + "vertical-fill": "Vertical fill", + "button-appearance": "Button appearance" + }, "button": { "layout": "Layout", "outlined": "Outlined", @@ -5240,6 +5253,7 @@ "auto-scale": "Auto scale", "label": "Label", "icon": "Icon", + "border-radius": "Border radius", "color-palette": "Color palette", "main": "Main", "background": "Background", diff --git a/ui-ngx/src/form.scss b/ui-ngx/src/form.scss index ab018a8bc6..524a4e86ac 100644 --- a/ui-ngx/src/form.scss +++ b/ui-ngx/src/form.scss @@ -651,7 +651,8 @@ &.mdc-evolution-chip--with-primary-graphic { .mdc-evolution-chip__action--primary { width: 100%; - padding-right: 0; + padding-left: 12px; + padding-right: 12px; gap: 0; .mdc-evolution-chip__graphic { padding: 0; From 03641bc486bf9bda067c4f1f1f567bab4cb3d3bc Mon Sep 17 00:00:00 2001 From: nick Date: Fri, 16 Feb 2024 13:46:08 +0200 Subject: [PATCH 257/397] fix_bug: delete deprecated Base64Utils --- .../server/controller/ImageController.java | 6 +++--- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 10 +++++----- .../lwm2m/utils/LwM2mValueConverterImpl.java | 4 ++-- .../server/common/transport/util/SslUtil.java | 10 +++++----- .../server/dao/resource/BaseImageService.java | 13 ++++++------- .../validator/DeviceProfileDataValidator.java | 4 ++-- .../thingsboard/rule/engine/rest/TbHttpClient.java | 4 ++-- 7 files changed, 25 insertions(+), 26 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/ImageController.java b/application/src/main/java/org/thingsboard/server/controller/ImageController.java index f569f49b54..c8d24d6081 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ImageController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ImageController.java @@ -27,7 +27,6 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.util.Base64Utils; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -60,6 +59,7 @@ import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; +import java.util.Base64; import java.util.concurrent.TimeUnit; import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION; @@ -196,7 +196,7 @@ public class ImageController extends BaseController { .resourceKey(imageInfo.getResourceKey()) .isPublic(imageInfo.isPublic()) .publicResourceKey(imageInfo.getPublicResourceKey()) - .data(Base64Utils.encodeToString(data)) + .data(Base64.getEncoder().encodeToString(data)) .build(); } @@ -221,7 +221,7 @@ public class ImageController extends BaseController { ImageDescriptor descriptor = new ImageDescriptor(); descriptor.setMediaType(imageData.getMediaType()); image.setDescriptorValue(descriptor); - image.setData(Base64Utils.decodeFromString(imageData.getData())); + image.setData(Base64.getDecoder().decode(imageData.getData())); return tbImageService.save(image, user); } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index 32db6538f6..ea627cbfad 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -15,19 +15,19 @@ */ package org.thingsboard.server.transport.lwm2m.security.sql; +import jakarta.servlet.http.HttpServletResponse; import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.core.util.Hex; import org.junit.Test; import org.springframework.test.web.servlet.MvcResult; -import org.springframework.util.Base64Utils; import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MDeviceCredentials; import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredential; import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; import org.thingsboard.server.transport.lwm2m.security.AbstractSecurityLwM2MIntegrationTest; -import jakarta.servlet.http.HttpServletResponse; import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.util.Base64; import static org.eclipse.leshan.client.object.Security.x509; import static org.eclipse.leshan.client.object.Security.x509Bootstrap; @@ -48,7 +48,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg PrivateKey privateKey = clientPrivateKeyFromCertTrustNo; X509ClientCredential clientCredentials = new X509ClientCredential(); clientCredentials.setEndpoint(clientEndpoint); - clientCredentials.setCert(Base64Utils.encodeToString(certificate.getEncoded())); + clientCredentials.setCert(Base64.getEncoder().encodeToString(certificate.getEncoded())); Security security = x509(SECURE_URI, shortServerId, certificate.getEncoded(), @@ -93,7 +93,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg PrivateKey privateKey = clientPrivateKeyFromCertTrustNo; X509ClientCredential clientCredentials = new X509ClientCredential(); clientCredentials.setEndpoint(clientEndpoint); - clientCredentials.setCert(Base64Utils.encodeToString(certificate.getEncoded())); + clientCredentials.setCert(Base64.getEncoder().encodeToString(certificate.getEncoded())); Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITHOUT_PARAMS, getBootstrapServerCredentialsSecure(X509, NONE)); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, X509, true); createDeviceProfile(transportConfiguration); @@ -111,7 +111,7 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg PrivateKey privateKey = clientPrivateKeyFromCertTrustNo; X509ClientCredential clientCredentials = new X509ClientCredential(); clientCredentials.setEndpoint(clientEndpoint); - clientCredentials.setCert(Base64Utils.encodeToString(certificate.getEncoded())); + clientCredentials.setCert(Base64.getEncoder().encodeToString(certificate.getEncoded())); Security security = x509Bootstrap(SECURE_URI_BS, certificate.getEncoded(), privateKey.getEncoded(), diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java index eb01c7d2a4..3125ae63f5 100644 --- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java +++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/utils/LwM2mValueConverterImpl.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.transport.lwm2m.utils; -import com.google.api.client.util.Base64; import lombok.extern.slf4j.Slf4j; import org.eclipse.leshan.core.model.ResourceModel.Type; import org.eclipse.leshan.core.node.LwM2mPath; @@ -28,6 +27,7 @@ import org.thingsboard.server.common.data.StringUtils; import java.math.BigInteger; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.Base64; import java.util.Date; import static org.eclipse.leshan.core.model.ResourceModel.Type.OPAQUE; @@ -172,7 +172,7 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { return Hex.decodeHex(((String)value).toCharArray()); } catch (IllegalArgumentException e) { try { - return Base64.decodeBase64(((String) value).getBytes()); + return Base64.getDecoder().decode(((String) value).getBytes()); } catch (IllegalArgumentException ea) { throw new CodecException("Unable to convert hexastring or base64 [%s] to byte array for resource %s", value, resourcePath); diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java index 8c75821c0d..0e02d1e161 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/util/SslUtil.java @@ -16,13 +16,11 @@ package org.thingsboard.server.common.transport.util; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.binary.Base64; import org.bouncycastle.asn1.x500.RDN; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.style.BCStyle; import org.bouncycastle.asn1.x500.style.IETFUtils; import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; -import org.springframework.util.Base64Utils; import org.thingsboard.server.common.msg.EncryptionUtil; import java.io.ByteArrayInputStream; @@ -31,6 +29,8 @@ import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import java.util.Base64; + /** * @author Valerii Sosliuk @@ -43,7 +43,7 @@ public class SslUtil { public static String getCertificateString(Certificate cert) throws CertificateEncodingException { - return EncryptionUtil.certTrimNewLines(Base64Utils.encodeToString(cert.getEncoded())); + return EncryptionUtil.certTrimNewLines(Base64.getEncoder().encodeToString(cert.getEncoded())); } public static String getCertificateChainString(Certificate[] chain) @@ -52,7 +52,7 @@ public class SslUtil { String end = "-----END CERTIFICATE-----"; StringBuilder stringBuilder = new StringBuilder(); for (Certificate cert: chain) { - stringBuilder.append(begin).append(EncryptionUtil.certTrimNewLines(Base64Utils.encodeToString(cert.getEncoded()))).append(end).append("\n"); + stringBuilder.append(begin).append(EncryptionUtil.certTrimNewLines(Base64.getEncoder().encodeToString(cert.getEncoded()))).append(end).append("\n"); } return stringBuilder.toString(); } @@ -64,7 +64,7 @@ public class SslUtil { fileContent = fileContent.replace("-----BEGIN CERTIFICATE-----", "") .replace("-----END CERTIFICATE-----", "") .replaceAll("\\s", ""); - byte[] decoded = Base64.decodeBase64(fileContent); + byte[] decoded = Base64.getDecoder().decode(fileContent); CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); try (InputStream inStream = new ByteArrayInputStream(decoded)) { certificate = (X509Certificate) certFactory.generateCertificate(inStream); diff --git a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java index c7ac699355..ef05229124 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/resource/BaseImageService.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.base.Strings; +import jakarta.annotation.PostConstruct; import lombok.Data; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -29,7 +30,6 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.tuple.Pair; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.Base64Utils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.DataConstants; @@ -60,7 +60,6 @@ import org.thingsboard.server.dao.util.JsonPathProcessingTask; import org.thingsboard.server.dao.widget.WidgetTypeDao; import org.thingsboard.server.dao.widget.WidgetsBundleDao; -import jakarta.annotation.PostConstruct; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.Collections; @@ -432,8 +431,8 @@ public class BaseImageService extends BaseResourceService implements ImageServic String mdResourceName = null; String mdMediaType; if (matches) { - mdResourceKey = new String(Base64Utils.decodeFromString(matcher.group(1)), StandardCharsets.UTF_8); - mdResourceName = new String(Base64Utils.decodeFromString(matcher.group(2)), StandardCharsets.UTF_8); + mdResourceKey = new String(Base64.getDecoder().decode(matcher.group(1)), StandardCharsets.UTF_8); + mdResourceName = new String(Base64.getDecoder().decode(matcher.group(2)), StandardCharsets.UTF_8); mdMediaType = matcher.group(3); } else if (data.startsWith(DataConstants.TB_IMAGE_PREFIX + "data:image/") || (!strict && data.startsWith("data:image/"))) { mdMediaType = StringUtils.substringBetween(data, "data:", ";base64"); @@ -623,10 +622,10 @@ public class BaseImageService extends BaseResourceService implements ImageServic ImageDescriptor descriptor = getImageDescriptor(imageInfo, key.isPreview()); String tbImagePrefix = ""; if (addTbImagePrefix) { - tbImagePrefix = "tb-image:" + Base64Utils.encodeToString(imageInfo.getResourceKey().getBytes(StandardCharsets.UTF_8)) + ":" - + Base64Utils.encodeToString(imageInfo.getName().getBytes(StandardCharsets.UTF_8)) + ";"; + tbImagePrefix = "tb-image:" + Base64.getEncoder().encodeToString(imageInfo.getResourceKey().getBytes(StandardCharsets.UTF_8)) + ":" + + Base64.getEncoder().encodeToString(imageInfo.getName().getBytes(StandardCharsets.UTF_8)) + ";"; } - return tbImagePrefix + "data:" + descriptor.getMediaType() + ";base64," + Base64Utils.encodeToString(data); + return tbImagePrefix + "data:" + descriptor.getMediaType() + ";base64," + Base64.getEncoder().encodeToString(data); } } } catch (Exception e) { diff --git a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java index 6e660e3f06..0a8d78fb86 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java +++ b/dao/src/main/java/org/thingsboard/server/dao/service/validator/DeviceProfileDataValidator.java @@ -23,7 +23,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; -import org.springframework.util.Base64Utils; import org.springframework.util.CollectionUtils; import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.DeviceProfile; @@ -64,6 +63,7 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.PKIXParameters; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; +import java.util.Base64; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -411,6 +411,6 @@ public class DeviceProfileDataValidator extends AbstractHasOtaPackageValidator Date: Fri, 16 Feb 2024 14:00:27 +0200 Subject: [PATCH 258/397] Fix the old websocket API --- .../server/service/ws/DefaultWebSocketService.java | 3 ++- .../ws/telemetry/sub/TelemetrySubscriptionUpdate.java | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java b/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java index edb2d7b7fa..0af50ff859 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/DefaultWebSocketService.java @@ -260,7 +260,8 @@ public class DefaultWebSocketService implements WebSocketService { @Override public void sendUpdate(String sessionId, int cmdId, TelemetrySubscriptionUpdate update) { - doSendUpdate(sessionId, cmdId, update); + // We substitute the subscriptionId with cmdId for old-style subscriptions. + doSendUpdate(sessionId, cmdId, update.copyWithNewSubscriptionId(cmdId)); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/ws/telemetry/sub/TelemetrySubscriptionUpdate.java b/application/src/main/java/org/thingsboard/server/service/ws/telemetry/sub/TelemetrySubscriptionUpdate.java index 1320a055cd..aa1a44096d 100644 --- a/application/src/main/java/org/thingsboard/server/service/ws/telemetry/sub/TelemetrySubscriptionUpdate.java +++ b/application/src/main/java/org/thingsboard/server/service/ws/telemetry/sub/TelemetrySubscriptionUpdate.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.service.ws.telemetry.sub; +import lombok.AllArgsConstructor; import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.service.subscription.SubscriptionErrorCode; @@ -26,8 +27,8 @@ import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; +@AllArgsConstructor public class TelemetrySubscriptionUpdate { - private final int subscriptionId; private int errorCode; private String errorMsg; @@ -93,6 +94,10 @@ public class TelemetrySubscriptionUpdate { return errorMsg; } + public TelemetrySubscriptionUpdate copyWithNewSubscriptionId(int subscriptionId){ + return new TelemetrySubscriptionUpdate(subscriptionId, errorCode, errorMsg, data); + } + @Override public String toString() { StringBuilder result = new StringBuilder("TelemetrySubscriptionUpdate [subscriptionId=" + subscriptionId + ", errorCode=" + errorCode + ", errorMsg=" + errorMsg + ", data="); From a282defeaa27b785ddb568c4d3619e7dfd1d85fb Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Fri, 16 Feb 2024 15:00:59 +0200 Subject: [PATCH 259/397] Minor code cleanup --- .../java/org/thingsboard/server/controller/BaseController.java | 2 +- .../common/data/notification/NotificationDeliveryMethod.java | 1 - .../common/data/notification/settings/NotificationSettings.java | 2 -- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 22a42064b5..c40760dda3 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -18,7 +18,6 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.ListenableFuture; import lombok.Getter; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; @@ -46,6 +45,7 @@ import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.OtaPackage; import org.thingsboard.server.common.data.OtaPackageInfo; +import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.TbResource; import org.thingsboard.server.common.data.TbResourceInfo; import org.thingsboard.server.common.data.Tenant; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java index 3254e96bd1..3e3467ca79 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationDeliveryMethod.java @@ -30,6 +30,5 @@ public enum NotificationDeliveryMethod { @Getter private final String name; - // TODO: private final boolean allowUseSystemSettings; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationSettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationSettings.java index 3654c3aa8c..8b2a2237ad 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationSettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/settings/NotificationSettings.java @@ -30,6 +30,4 @@ public class NotificationSettings implements Serializable { @Valid private Map deliveryMethodsConfigs; - // TODO: disable option, location on the screen, shown notifications count, timings of displaying - } From b008eba42cfd3fb587e610b3c5eee88f47fbad0a Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 16 Feb 2024 15:04:45 +0200 Subject: [PATCH 260/397] UI: Minor change style in notification --- .../notification/sent/sent-notification-dialog.component.scss | 3 ++- .../notification/sent/sent-notification-dialog.componet.ts | 2 +- .../template/template-notification-dialog.component.scss | 3 ++- .../template/template-notification-dialog.component.ts | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss index 1dfbd7518b..ee0c8aeedc 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss @@ -16,7 +16,7 @@ @import "../../../../../../scss/constants"; :host { - width: 850px; + width: 780px; height: 100%; max-width: 100%; max-height: 100vh; @@ -206,6 +206,7 @@ .mat-horizontal-stepper-wrapper { flex: 1 1 100%; + width: 100%; } .mat-horizontal-content-container { diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts index da95bec91d..4d2d184dbd 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts @@ -98,7 +98,7 @@ export class SentNotificationDialogComponent extends } }); - this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-xs']) + this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-sm']) .pipe(map(({matches}) => matches ? 'horizontal' : 'vertical')); this.notificationRequestForm = this.fb.group({ diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.scss index 536c5842a9..8583731629 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.scss @@ -17,7 +17,7 @@ @import "../../../../../../theme"; :host { - width: 850px; + width: 780px; height: 100%; max-width: 100%; max-height: 100vh; @@ -83,6 +83,7 @@ .mat-horizontal-stepper-wrapper { flex: 1 1 100%; + width: 100%; } .mat-horizontal-content-container { diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts index a2d62c023a..b34e5e5c4f 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts @@ -78,7 +78,7 @@ export class TemplateNotificationDialogComponent this.notificationTypes = this.allowNotificationType(); - this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-xs']) + this.stepperOrientation = this.breakpointObserver.observe(MediaBreakpoints['gt-sm']) .pipe(map(({matches}) => matches ? 'horizontal' : 'vertical')); if (isDefinedAndNotNull(this.data?.predefinedType)) { From 45443d98fc7b64393e57e09a4a9a3eddc2ed245f Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Fri, 16 Feb 2024 15:57:50 +0200 Subject: [PATCH 261/397] Rewrite for clarity --- .../queue/discovery/HashPartitionService.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java index e7034143fe..a8763c0428 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java @@ -225,33 +225,33 @@ public class HashPartitionService implements PartitionService { boolean isManaged; Set assignedTenantProfiles = serviceInfoProvider.getAssignedTenantProfiles(); - if (assignedTenantProfiles.isEmpty()) { // if this is regular rule engine - if (tenantId.isSysTenantId()) { - isManaged = true; + boolean isRegular = assignedTenantProfiles.isEmpty(); + if (tenantId.isSysTenantId()) { + // All system queues are always processed on regular rule engines. + return isRegular; + } + TenantRoutingInfo routingInfo = getRoutingInfo(tenantId); + if (isRegular) { + if (routingInfo.isIsolated()) { + isManaged = hasDedicatedService(routingInfo.getProfileId()); } else { - TenantRoutingInfo routingInfo = getRoutingInfo(tenantId); - if (routingInfo.isIsolated()) { - isManaged = CollectionsUtil.isEmpty(responsibleServices.get(routingInfo.getProfileId())); - } else { - isManaged = true; - } + isManaged = true; } } else { - if (tenantId.isSysTenantId()) { - isManaged = false; + if (routingInfo.isIsolated()) { + isManaged = assignedTenantProfiles.contains(routingInfo.getProfileId().getId()); } else { - TenantRoutingInfo routingInfo = getRoutingInfo(tenantId); - if (routingInfo.isIsolated()) { - isManaged = assignedTenantProfiles.contains(routingInfo.getProfileId().getId()); - } else { - isManaged = false; - } + isManaged = false; } } log.trace("[{}] Tenant {} managed by this service", tenantId, isManaged ? "is" : "is not"); return isManaged; } + private boolean hasDedicatedService(TenantProfileId profileId) { + return CollectionsUtil.isEmpty(responsibleServices.get(profileId)); + } + @Override public TopicPartitionInfo resolve(ServiceType serviceType, String queueName, TenantId tenantId, EntityId entityId) { TenantId isolatedOrSystemTenantId = getIsolatedOrSystemTenantId(serviceType, tenantId); From 6dd28b0134fb4d7da07af818298440edf5a3a394 Mon Sep 17 00:00:00 2001 From: okolesnyk Date: Fri, 16 Feb 2024 17:26:37 +0200 Subject: [PATCH 262/397] UI:fix. Change the link to the documentation (wrong urls)(PROD-2559) --- ui-ngx/src/app/shared/models/constants.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui-ngx/src/app/shared/models/constants.ts b/ui-ngx/src/app/shared/models/constants.ts index e57ab758e0..0092a679f6 100644 --- a/ui-ngx/src/app/shared/models/constants.ts +++ b/ui-ngx/src/app/shared/models/constants.ts @@ -159,12 +159,12 @@ export const HelpLinks = { otaUpdates: helpBaseUrl + '/docs/user-guide/ota-updates', widgetTypes: helpBaseUrl + '/docs/user-guide/ui/widget-library/#widget-types', widgetsBundles: helpBaseUrl + '/docs/user-guide/ui/widget-library/#widgets-library-bundles', - widgetsConfig: helpBaseUrl + '/docs/user-guide/widgets', - widgetsConfigTimeseries: helpBaseUrl + '/docs/user-guide/widgets', - widgetsConfigLatest: helpBaseUrl + '/docs/user-guide/widgets', - widgetsConfigRpc: helpBaseUrl + '/docs/user-guide/widgets', - widgetsConfigAlarm: helpBaseUrl + '/docs/user-guide/widgets', - widgetsConfigStatic: helpBaseUrl + '/docs/user-guide/widgets', + widgetsConfig: helpBaseUrl + '/docs/user-guide/ui/widget-library', + widgetsConfigTimeseries: helpBaseUrl + '/docs/user-guide/ui/widget-library#time-series', + widgetsConfigLatest: helpBaseUrl + '/docs/user-guide/ui/widget-library#latest-values', + widgetsConfigRpc: helpBaseUrl + '/docs/user-guide/ui/widget-library#control-widget', + widgetsConfigAlarm: helpBaseUrl + '/docs/user-guide/ui/widget-library#alarm-widget', + widgetsConfigStatic: helpBaseUrl + '/docs/user-guide/ui/widget-library#static', ruleNodePushToCloud: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/action-nodes/#push-to-cloud', ruleNodePushToEdge: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/action-nodes/#push-to-edge', queue: helpBaseUrl + '/docs/user-guide/queue', From ecca3ee708748f6cda14378ea95214599d736e97 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 16 Feb 2024 17:45:46 +0200 Subject: [PATCH 263/397] UI: Optimized updated image in Image Gallery --- .../image/image-dialog.component.ts | 19 +++++++----- .../image/upload-image-dialog.component.ts | 30 +++++++++++-------- .../src/app/shared/models/resource.models.ts | 4 +++ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/ui-ngx/src/app/shared/components/image/image-dialog.component.ts b/ui-ngx/src/app/shared/components/image/image-dialog.component.ts index 1a777d1bf7..b140c6bf32 100644 --- a/ui-ngx/src/app/shared/components/image/image-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/image/image-dialog.component.ts @@ -14,8 +14,7 @@ /// limitations under the License. /// -import { Component, Inject, OnInit, SkipSelf } from '@angular/core'; -import { ErrorStateMatcher } from '@angular/material/core'; +import { Component, Inject, OnInit } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @@ -23,7 +22,7 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; import { ImageService } from '@core/http/image.service'; -import { ImageResourceInfo, imageResourceType } from '@shared/models/resource.models'; +import { ImageResource, ImageResourceInfo, imageResourceType } from '@shared/models/resource.models'; import { UploadImageDialogComponent, UploadImageDialogData @@ -143,7 +142,7 @@ export class ImageDialogComponent extends $event.stopPropagation(); } this.dialog.open(UploadImageDialogComponent, { + ImageResource>(UploadImageDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { @@ -153,9 +152,15 @@ export class ImageDialogComponent extends if (result) { this.imageChanged = true; this.image = result; - this.imagePreviewData = { - url: this.image.public ? `${this.image.publicLink}?ts=${new Date().getTime()}` : this.image.link - }; + let url; + if (result.base64) { + url = result.base64; + } else if (this.image.public) { + url = `${this.image.publicLink}?ts=${new Date().getTime()}`; + } else { + url = this.image.link; + } + this.imagePreviewData = {url}; } }); } diff --git a/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts b/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts index ae022615a1..b61ef03eef 100644 --- a/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/image/upload-image-dialog.component.ts @@ -30,8 +30,10 @@ import { import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; import { ImageService } from '@core/http/image.service'; -import { ImageResourceInfo, imageResourceType } from '@shared/models/resource.models'; +import { ImageResource, ImageResourceInfo, imageResourceType } from '@shared/models/resource.models'; import { getCurrentAuthState } from '@core/auth/auth.selectors'; +import { forkJoin } from 'rxjs'; +import { blobToBase64 } from '@core/utils'; export interface UploadImageDialogData { image?: ImageResourceInfo; @@ -44,7 +46,7 @@ export interface UploadImageDialogData { styleUrls: [] }) export class UploadImageDialogComponent extends - DialogComponent implements OnInit, ErrorStateMatcher { + DialogComponent implements OnInit, ErrorStateMatcher { uploadImageFormGroup: UntypedFormGroup; @@ -59,7 +61,7 @@ export class UploadImageDialogComponent extends private imageService: ImageService, @Inject(MAT_DIALOG_DATA) public data: UploadImageDialogData, @SkipSelf() private errorStateMatcher: ErrorStateMatcher, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, public fb: UntypedFormBuilder) { super(store, router, dialogRef); } @@ -98,18 +100,20 @@ export class UploadImageDialogComponent extends const file: File = this.uploadImageFormGroup.get('file').value; if (this.uploadImage) { const title: string = this.uploadImageFormGroup.get('title').value; - this.imageService.uploadImage(file, title).subscribe( - (res) => { - this.dialogRef.close(res); - } - ); + forkJoin([ + this.imageService.uploadImage(file, title), + blobToBase64(file) + ]).subscribe(([imageInfo, base64]) => { + this.dialogRef.close(Object.assign(imageInfo, {base64})); + }); } else { const image = this.data.image; - this.imageService.updateImage(imageResourceType(image), image.resourceKey, file).subscribe( - (res) => { - this.dialogRef.close(res); - } - ); + forkJoin([ + this.imageService.updateImage(imageResourceType(image), image.resourceKey, file), + blobToBase64(file) + ]).subscribe(([imageInfo, base64]) => { + this.dialogRef.close(Object.assign(imageInfo, {base64})); + }); } } } diff --git a/ui-ngx/src/app/shared/models/resource.models.ts b/ui-ngx/src/app/shared/models/resource.models.ts index 86b7c50553..a35e87864e 100644 --- a/ui-ngx/src/app/shared/models/resource.models.ts +++ b/ui-ngx/src/app/shared/models/resource.models.ts @@ -86,6 +86,10 @@ export interface ImageResourceInfo extends TbResourceInfo { publicLink?: string; } +export interface ImageResource extends ImageResourceInfo { + base64?: string; +} + export interface ImageExportData { mediaType: string; fileName: string; From 3a4ffa213fc17520a3f01003a25a438b4ccea1c9 Mon Sep 17 00:00:00 2001 From: okolesnyk Date: Mon, 19 Feb 2024 12:58:00 +0200 Subject: [PATCH 264/397] UI. Signal Strength widget (PROD-2773)(move "No signal" field into advanced form) --- .../indicator/signal-strength-basic-config.component.html | 7 ------- .../indicator/signal-strength-basic-config.component.ts | 2 -- .../signal-strength-widget-settings.component.html | 7 +++++++ .../indicator/signal-strength-widget-settings.component.ts | 3 ++- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/signal-strength-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/signal-strength-basic-config.component.html index a31685430c..9d6c7d9b05 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/signal-strength-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/signal-strength-basic-config.component.html @@ -109,13 +109,6 @@ formControlName="inactiveBarsColor">
    -
    -
    widgets.signal-strength.no-signal-rssi-value
    - - - -
    +
    +
    widgets.signal-strength.no-signal-rssi-value
    + + + +
    Date: Mon, 19 Feb 2024 13:02:31 +0200 Subject: [PATCH 265/397] UI: Fixed background settings panel jump when edit content --- .../background-settings-panel.component.html | 87 ++++++++++--------- .../background-settings-panel.component.scss | 8 ++ .../common/background-settings.component.ts | 2 +- 3 files changed, 55 insertions(+), 42 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.html index 6cca169f5a..9038f2a22f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.html @@ -17,49 +17,54 @@ -->
    widgets.background.background-settings
    -
    -
    -
    widgets.background.background
    - - - {{ backgroundTypeTranslationsMap.get(type) | translate }} - - -
    - -
    -
    widgets.color.color
    - - -
    -
    -
    -
    widgets.background.overlay
    - - {{ 'widgets.background.enable-overlay' | translate }} - -
    -
    widgets.color.color
    - - -
    -
    -
    widgets.background.blur
    - - -
    px
    -
    +
    +
    +
    +
    widgets.background.background
    + + + {{ backgroundTypeTranslationsMap.get(type) | translate }} + + +
    + +
    +
    widgets.color.color
    + + +
    -
    -
    -
    - widgets.background.preview +
    +
    widgets.background.overlay
    + + {{ 'widgets.background.enable-overlay' | translate }} + +
    +
    widgets.color.color
    + + +
    +
    +
    widgets.background.blur
    + + +
    px
    +
    +
    -
    -
    +
    +
    + widgets.background.preview +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.scss index 01297b9d12..6bc83fe967 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings-panel.component.scss @@ -67,6 +67,14 @@ left: 7.998px; right: 7.998px; } + .tb-background-settings-panel-content { + display: flex; + flex-direction: column; + gap: 16px; + overflow: auto; + margin: -10px; + padding: 10px; + } .tb-background-settings-panel-buttons { height: 40px; display: flex; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts index 5ac54cbbe3..66dd774a21 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/background-settings.component.ts @@ -110,7 +110,7 @@ export class BackgroundSettingsComponent implements OnInit, ControlValueAccessor backgroundSettings: this.modelValue }; const backgroundSettingsPanelPopover = this.popoverService.displayPopover(trigger, this.renderer, - this.viewContainerRef, BackgroundSettingsPanelComponent, 'left', true, null, + this.viewContainerRef, BackgroundSettingsPanelComponent, ['leftOnly', 'leftTopOnly', 'leftBottomOnly'], true, null, ctx, {}, {}, {}, true); From 2013cb36217392c5ed98c4854a54267fd279de59 Mon Sep 17 00:00:00 2001 From: okolesnyk Date: Mon, 19 Feb 2024 13:51:56 +0200 Subject: [PATCH 266/397] UI. Device profile > Alarm rules (corrections)(PROD-3051) --- ui-ngx/src/assets/locale/locale.constant-en_US.json | 4 ++-- ui-ngx/src/assets/locale/locale.constant-ko_KR.json | 4 ++-- ui-ngx/src/assets/locale/locale.constant-sl_SI.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) 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 f8cacb7b29..ca895fb5e5 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1665,8 +1665,8 @@ "alarm-rule-mobile-dashboard-hint": "Used by mobile application as an alarm details dashboard", "alarm-rule-no-mobile-dashboard": "No dashboard selected", "propagate-alarm": "Propagate alarm to related entities", - "alarm-rule-relation-types-list": "Relation types to propagate", - "alarm-rule-relation-types-list-hint": "If propagate relation types are not entered, alarms will be propagated without filtering by relation type.", + "alarm-rule-relation-types-list": "Relation types", + "alarm-rule-relation-types-list-hint": "Defines relation types to filter the related entities. If not set, the alarm will be propagated to all related entities.", "propagate-alarm-to-owner": "Propagate alarm to entity owner (Customer or Tenant)", "propagate-alarm-to-tenant": "Propagate alarm to Tenant", "alarm-rule-condition": "Alarm rule condition", diff --git a/ui-ngx/src/assets/locale/locale.constant-ko_KR.json b/ui-ngx/src/assets/locale/locale.constant-ko_KR.json index 39d1e6311f..646981659d 100644 --- a/ui-ngx/src/assets/locale/locale.constant-ko_KR.json +++ b/ui-ngx/src/assets/locale/locale.constant-ko_KR.json @@ -1007,8 +1007,8 @@ "condition-duration-time-unit-required": "Time unit is required.", "advanced-settings": "Advanced settings", "propagate-alarm": "Propagate alarm", - "alarm-rule-relation-types-list": "Relation types to propagate", - "alarm-rule-relation-types-list-hint": "If propagate relation types are not entered, alarms will be propagated without filtering by relation type.", + "alarm-rule-relation-types-list": "Relation types", + "alarm-rule-relation-types-list-hint": "Defines relation types to filter the related entities. If not set, the alarm will be propagated to all related entities.", "alarm-rule-condition": "Alarm rule condition", "enter-alarm-rule-condition-prompt": "Please add alarm rule condition", "edit-alarm-rule-condition": "Edit alarm rule condition", diff --git a/ui-ngx/src/assets/locale/locale.constant-sl_SI.json b/ui-ngx/src/assets/locale/locale.constant-sl_SI.json index c4b1643a53..2135a7cbd3 100644 --- a/ui-ngx/src/assets/locale/locale.constant-sl_SI.json +++ b/ui-ngx/src/assets/locale/locale.constant-sl_SI.json @@ -1007,8 +1007,8 @@ "condition-duration-time-unit-required": "Time unit is required.", "advanced-settings": "Advanced settings", "propagate-alarm": "Propagate alarm", - "alarm-rule-relation-types-list": "Relation types to propagate", - "alarm-rule-relation-types-list-hint": "If propagate relation types are not entered, alarms will be propagated without filtering by relation type.", + "alarm-rule-relation-types-list": "Relation types", + "alarm-rule-relation-types-list-hint": "Defines relation types to filter the related entities. If not set, the alarm will be propagated to all related entities.", "alarm-rule-condition": "Alarm rule condition", "enter-alarm-rule-condition-prompt": "Please add alarm rule condition", "edit-alarm-rule-condition": "Edit alarm rule condition", From 927efe35f15f57f817ad9436508f0d66a4fae5b4 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 19 Feb 2024 14:15:18 +0200 Subject: [PATCH 267/397] UI: Typo in send notification component --- .../notification/sent/sent-notification-dialog.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html index 8f5d41de34..128b37313e 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html @@ -36,7 +36,7 @@ check - {{ 'notification.compose' | translate }} + {{ 'notification.setup' | translate }}
    From 8763e85e3f615b5db801e59a22f99552e399a9db Mon Sep 17 00:00:00 2001 From: nick Date: Mon, 19 Feb 2024 15:23:10 +0200 Subject: [PATCH 268/397] lwm2m: refactoring tests --- .../lwm2m/AbstractLwM2MIntegrationTest.java | 20 +++++++------------ .../lwm2m/client/LwM2MTestClient.java | 3 +-- .../ota/sql/OtaLwM2MIntegrationTest.java | 6 +++--- .../rpc/AbstractRpcLwM2MIntegrationTest.java | 2 +- .../AbstractSecurityLwM2MIntegrationTest.java | 9 ++------- ...rityLwM2MIntegrationDtlsCidLengthTest.java | 2 +- .../AbstractLwM2MIntegrationDiffPortTest.java | 2 +- .../sql/NoSecLwM2MIntegrationTest.java | 4 ++-- .../security/sql/PskLwm2mIntegrationTest.java | 2 -- .../security/sql/RpkLwM2MIntegrationTest.java | 2 -- .../sql/X509_NoTrustLwM2MIntegrationTest.java | 2 -- .../sql/X509_TrustLwM2MIntegrationTest.java | 2 -- 12 files changed, 18 insertions(+), 38 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java index 1eedd74608..a44d2b6a62 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java @@ -21,7 +21,6 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; -import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.LeshanClient; import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.core.ResponseCode; @@ -86,8 +85,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import static org.awaitility.Awaitility.await; -import static org.eclipse.californium.core.config.CoapConfig.COAP_PORT; -import static org.eclipse.californium.core.config.CoapConfig.COAP_SECURE_PORT; import static org.eclipse.leshan.client.object.Security.noSec; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertEquals; @@ -135,8 +132,6 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte public static final String SECURE_URI = COAPS + host + ":" + securityPort; public static final String URI_BS = COAP + hostBs + ":" + portBs; public static final String SECURE_URI_BS = COAPS + hostBs + ":" + securityPortBs; - public static final Configuration COAP_CONFIG = new Configuration().set(COAP_PORT, port).set(COAP_SECURE_PORT, securityPort); - public static Configuration COAP_CONFIG_BS = new Configuration().set(COAP_PORT, portBs).set(COAP_SECURE_PORT, securityPortBs); public static final Security SECURITY_NO_SEC = noSec(URI, shortServerId); protected final String OBSERVE_ATTRIBUTES_WITHOUT_PARAMS = @@ -219,7 +214,6 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte public void basicTestConnectionObserveTelemetry(Security security, LwM2MDeviceCredentials deviceCredentials, - Configuration coapConfig, String endpoint, boolean queueMode) throws Exception { Lwm2mDeviceProfileTransportConfiguration transportConfiguration = getTransportConfiguration(OBSERVE_ATTRIBUTES_WITH_PARAMS, getBootstrapServerCredentialsNoSec(NONE)); @@ -238,7 +232,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte getWsClient().waitForReply(); getWsClient().registerWaitForUpdate(); - createNewClient(security, null, coapConfig, false, endpoint, null, queueMode); + createNewClient(security, null, false, endpoint, null, queueMode); deviceId = device.getId().getId().toString(); awaitObserveReadAll(0, deviceId); String msg = getWsClient().waitForUpdate(); @@ -306,24 +300,24 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractTransportInte this.resources = resources; } - public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, + public void createNewClient(Security security, Security securityBs, boolean isRpc, String endpoint) throws Exception { - this.createNewClient(security, securityBs, coapConfig, isRpc, endpoint, null, false); + this.createNewClient(security, securityBs, isRpc, endpoint, null, false); } - public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, + public void createNewClient(Security security, Security securityBs, boolean isRpc, String endpoint, Integer clientDtlsCidLength) throws Exception { - this.createNewClient(security, securityBs, coapConfig, isRpc, endpoint, clientDtlsCidLength, false); + this.createNewClient(security, securityBs, isRpc, endpoint, clientDtlsCidLength, false); } - public void createNewClient(Security security, Security securityBs, Configuration coapConfig, boolean isRpc, + public void createNewClient(Security security, Security securityBs, boolean isRpc, String endpoint, Integer clientDtlsCidLength, boolean queueMode) throws Exception { this.clientDestroy(); lwM2MTestClient = new LwM2MTestClient(this.executor, endpoint); try (ServerSocket socket = new ServerSocket(0)) { int clientPort = socket.getLocalPort(); - lwM2MTestClient.init(security, securityBs, coapConfig, clientPort, isRpc, + lwM2MTestClient.init(security, securityBs, clientPort, isRpc, this.defaultLwM2mUplinkMsgHandlerTest, this.clientContextTest, isWriteAttribute , clientDtlsCidLength, queueMode); } diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index 4363bca41c..3f2e281b73 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -127,7 +127,7 @@ public class LwM2MTestClient { private LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandlerTest; private LwM2mClientContext clientContext; - public void init(Security security, Security securityBs,Configuration coapConfig, int port, boolean isRpc, + public void init(Security security, Security securityBs, int port, boolean isRpc, LwM2mUplinkMsgHandler defaultLwM2mUplinkMsgHandler, LwM2mClientContext clientContext, boolean isWriteAttribute, Integer cIdLength, boolean queueMode) throws InvalidDDFFileException, IOException { Assert.assertNull("client already initialized", leshanClient); @@ -218,7 +218,6 @@ public class LwM2MTestClient { // Create Californium Configuration Configuration clientCoapConfig = endpointsBuilder.createDefaultConfiguration(); - DtlsConnectorConfig.Builder dtlsConfig = new DtlsConnectorConfig.Builder(coapConfig); // Set some DTLS stuff // These configuration values are always overwritten by CLI therefore set them to transient. diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java index 7e812f9846..c7027ed42a 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/ota/sql/OtaLwM2MIntegrationTest.java @@ -59,7 +59,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_WITHOUT_FW_INFO)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); + createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_WITHOUT_FW_INFO); awaitObserveReadAll(0, device.getId().getId().toString()); device.setFirmwareId(createFirmware().getId()); @@ -84,7 +84,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA5)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA5); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA5); + createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_OTA5); awaitObserveReadAll(9, device.getId().getId().toString()); device.setFirmwareId(createFirmware().getId()); @@ -114,7 +114,7 @@ public class OtaLwM2MIntegrationTest extends AbstractOtaLwM2MIntegrationTest { createDeviceProfile(transportConfiguration); LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(this.CLIENT_ENDPOINT_OTA9)); final Device device = createDevice(deviceCredentials, this.CLIENT_ENDPOINT_OTA9); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, false, this.CLIENT_ENDPOINT_OTA9); + createNewClient(SECURITY_NO_SEC, null, false, this.CLIENT_ENDPOINT_OTA9); awaitObserveReadAll(9, device.getId().getId().toString()); device.setSoftwareId(createSoftware().getId()); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java index 1c83bed8eb..1c6e384ae1 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/rpc/AbstractRpcLwM2MIntegrationTest.java @@ -91,7 +91,7 @@ public abstract class AbstractRpcLwM2MIntegrationTest extends AbstractLwM2MInteg private void initRpc () throws Exception { String endpoint = DEVICE_ENDPOINT_RPC_PREF + endpointSequence.incrementAndGet(); - createNewClient(SECURITY_NO_SEC, null, COAP_CONFIG, true, endpoint); + createNewClient(SECURITY_NO_SEC, null, true, endpoint); expectedObjects = ConcurrentHashMap.newKeySet(); expectedObjectIdVers = ConcurrentHashMap.newKeySet(); expectedInstances = ConcurrentHashMap.newKeySet(); diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java index f66d4ef4b8..e787d26265 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/AbstractSecurityLwM2MIntegrationTest.java @@ -18,7 +18,6 @@ package org.thingsboard.server.transport.lwm2m.security; import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; -import org.eclipse.californium.elements.config.Configuration; import org.eclipse.leshan.client.object.Security; import org.eclipse.leshan.core.ResponseCode; import org.eclipse.leshan.core.util.Hex; @@ -186,7 +185,6 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); this.basicTestConnection(null , SECURITY_NO_SEC_BS, deviceCredentials, - COAP_CONFIG_BS, clientEndpoint, transportConfiguration, awaitAlias, @@ -198,7 +196,6 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M protected void basicTestConnection(Security security, Security securityBs, LwM2MDeviceCredentials deviceCredentials, - Configuration coapConfig, String endpoint, Lwm2mDeviceProfileTransportConfiguration transportConfiguration, String awaitAlias, @@ -208,7 +205,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M boolean isStartLw) throws Exception { createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); - createNewClient(security, securityBs, coapConfig, true, endpoint); + createNewClient(security, securityBs, true, endpoint); lwM2MTestClient.start(isStartLw); if (isAwaitObserveReadAll) { awaitObserveReadAll(0, device.getId().getId().toString()); @@ -236,7 +233,6 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M SECURITY_NO_SEC, SECURITY_NO_SEC_BS, deviceCredentials, - COAP_CONFIG, clientEndpoint, transportConfiguration, awaitAlias, @@ -246,7 +242,6 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M private void basicTestConnectionBootstrapRequestTrigger(Security security, Security securityBs, LwM2MDeviceCredentials deviceCredentials, - Configuration coapConfig, String endpoint, Lwm2mDeviceProfileTransportConfiguration transportConfiguration, String awaitAlias, @@ -256,7 +251,7 @@ public abstract class AbstractSecurityLwM2MIntegrationTest extends AbstractLwM2M createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, endpoint); String deviceIdStr = device.getId().getId().toString(); - createNewClient(security, securityBs, coapConfig, true, endpoint); + createNewClient(security, securityBs, true, endpoint); lwM2MTestClient.start(true); awaitObserveReadAll(0, deviceIdStr); await(awaitAlias) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java index f44a2b1874..291149b7e8 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/cid/AbstractSecurityLwM2MIntegrationDtlsCidLengthTest.java @@ -52,7 +52,7 @@ public abstract class AbstractSecurityLwM2MIntegrationDtlsCidLengthTest extends createDeviceProfile(transportConfiguration); final Device device = createDevice(deviceCredentials, clientEndpoint); device.getId().getId().toString(); - createNewClient(security, null, COAP_CONFIG, true, clientEndpoint, clientDtlsCidLength); + createNewClient(security, null, true, clientEndpoint, clientDtlsCidLength); lwM2MTestClient.start(true); await(awaitAlias) .atMost(40, TimeUnit.SECONDS) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java index 89ff598bc2..e61b1afb6c 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/diffPort/AbstractLwM2MIntegrationDiffPortTest.java @@ -52,7 +52,7 @@ public abstract class AbstractLwM2MIntegrationDiffPortTest extends AbstractSecur createDeviceProfile(transportConfiguration); createDevice(deviceCredentials, clientEndpoint); - createNewClient(security, null, COAP_CONFIG, true, clientEndpoint); + createNewClient(security, null, true, clientEndpoint); lwM2MTestClient.start(true); await(awaitAlias) .atMost(40, TimeUnit.SECONDS) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java index 7a34ec4283..a5296a16b1 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/NoSecLwM2MIntegrationTest.java @@ -32,13 +32,13 @@ public class NoSecLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationT public void testWithNoSecConnectLwm2mSuccessAndObserveTelemetry() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC; LwM2MDeviceCredentials clientCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); - super.basicTestConnectionObserveTelemetry(SECURITY_NO_SEC, clientCredentials, COAP_CONFIG, clientEndpoint, false); + super.basicTestConnectionObserveTelemetry(SECURITY_NO_SEC, clientCredentials, clientEndpoint, false); } @Test public void testWithNoSecQueueModeConnectLwm2mSuccessAndObserveTelemetry() throws Exception { String clientEndpoint = CLIENT_ENDPOINT_NO_SEC + "_QueueMode"; LwM2MDeviceCredentials clientCredentials = getDeviceCredentialsNoSec(createNoSecClientCredentials(clientEndpoint)); - super.basicTestConnectionObserveTelemetry(SECURITY_NO_SEC, clientCredentials, COAP_CONFIG, clientEndpoint, true); + super.basicTestConnectionObserveTelemetry(SECURITY_NO_SEC, clientCredentials, clientEndpoint, true); } // Bootstrap + Lwm2m diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java index 64d4080ab4..2684f210ca 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/PskLwm2mIntegrationTest.java @@ -57,7 +57,6 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes this.basicTestConnection(security, null, deviceCredentials, - COAP_CONFIG, clientEndpoint, transportConfiguration, "await on client state (Psk_Lwm2m)", @@ -103,7 +102,6 @@ public class PskLwm2mIntegrationTest extends AbstractSecurityLwM2MIntegrationTes LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, null, null, PSK, false); this.basicTestConnection(null, securityBs, deviceCredentials, - COAP_CONFIG_BS, clientEndpoint, transportConfiguration, "await on client state (PskBS two section)", diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java index 1f48375cdd..b6ebfc442e 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/RpkLwM2MIntegrationTest.java @@ -58,7 +58,6 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, privateKey, certificate, RPK, false); this.basicTestConnection(security, null, deviceCredentials, - COAP_CONFIG, clientEndpoint, transportConfiguration, "await on client state (Rpk_Lwm2m)", @@ -119,7 +118,6 @@ public class RpkLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegrationTes LwM2MDeviceCredentials deviceCredentials = getDeviceCredentialsSecure(clientCredentials, clientPrivateKeyFromCertTrust, certificate, RPK, false); this.basicTestConnection(null, securityBs, deviceCredentials, - COAP_CONFIG_BS, clientEndpoint, transportConfiguration, "await on client state (RpkBS two section)", diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java index ea627cbfad..072dea9a6e 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_NoTrustLwM2MIntegrationTest.java @@ -59,7 +59,6 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg this.basicTestConnection(security, null, deviceCredentials, - COAP_CONFIG, clientEndpoint, transportConfiguration, "await on client state (X509_Trust_Lwm2m)", @@ -121,7 +120,6 @@ public class X509_NoTrustLwM2MIntegrationTest extends AbstractSecurityLwM2MInteg this.basicTestConnection(security, null, deviceCredentials, - COAP_CONFIG_BS, clientEndpoint, transportConfiguration, "await on client state (X509NoTrust two section)", diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java index b3357a5a9b..9bc1643902 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/security/sql/X509_TrustLwM2MIntegrationTest.java @@ -53,7 +53,6 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra this.basicTestConnection(security, null, deviceCredentials, - COAP_CONFIG, clientEndpoint, transportConfiguration, "await on client state (X509_Trust_Lwm2m)", @@ -81,7 +80,6 @@ public class X509_TrustLwM2MIntegrationTest extends AbstractSecurityLwM2MIntegra this.basicTestConnection(security, null, deviceCredentials, - COAP_CONFIG_BS, clientEndpoint, transportConfiguration, "await on client state (X509Trust two section)", From d78b349dc39a803bfa828ec4cf8fb513b25458c6 Mon Sep 17 00:00:00 2001 From: nick Date: Mon, 19 Feb 2024 15:33:56 +0200 Subject: [PATCH 269/397] lwm2m: refactoring2 tests --- .../server/transport/lwm2m/client/LwM2MTestClient.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java index 3f2e281b73..54a21da51e 100644 --- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java +++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/client/LwM2MTestClient.java @@ -209,8 +209,7 @@ public class LwM2MTestClient { /** * "Use java-coap for CoAP protocol instead of Californium." */ - boolean useJavaCoap = false; - if (!useJavaCoap) protocolProvider.add(new CoapOscoreProtocolProvider()); + protocolProvider.add(new CoapOscoreProtocolProvider()); protocolProvider.add(customCoapsProtocolProvider); CaliforniumClientEndpointsProvider.Builder endpointsBuilder = new CaliforniumClientEndpointsProvider.Builder( protocolProvider.toArray(new ClientProtocolProvider[protocolProvider.size()])); From 64f4b586a90bf549b6aec5839b04ec5ad9de660d Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Mon, 19 Feb 2024 15:44:45 +0200 Subject: [PATCH 270/397] Add rate limits for edge uplink message --- .../server/service/edge/EdgeContextComponent.java | 4 ++++ .../server/service/edge/rpc/EdgeGrpcSession.java | 9 +++++++++ .../server/service/limits/RateLimitServiceTest.java | 6 +++++- .../thingsboard/server/common/data/limit/LimitedApi.java | 2 ++ .../profile/DefaultTenantProfileConfiguration.java | 2 ++ .../default-tenant-profile-configuration.component.html | 8 ++++++++ .../default-tenant-profile-configuration.component.ts | 4 +++- .../profile/tenant/rate-limits/rate-limits.models.ts | 8 +++++++- ui-ngx/src/app/shared/models/limited-api.models.ts | 6 +++++- ui-ngx/src/assets/help/en_US/notification/rate_limits.md | 2 +- ui-ngx/src/assets/locale/locale.constant-en_US.json | 8 +++++++- 11 files changed, 53 insertions(+), 6 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java index 2f157af70e..f5b769e568 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java @@ -19,6 +19,7 @@ import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; +import org.thingsboard.server.cache.limits.RateLimitService; import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.common.msg.notification.NotificationRuleProcessor; import org.thingsboard.server.dao.asset.AssetProfileService; @@ -150,6 +151,9 @@ public class EdgeContextComponent { @Autowired private ResourceService resourceService; + @Autowired + private RateLimitService rateLimitService; + @Autowired private NotificationRuleProcessor notificationRuleProcessor; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index e5038d3b3a..7a5d94bcdb 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -27,6 +27,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.data.util.Pair; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EdgeUtils; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.id.EdgeId; @@ -35,11 +36,13 @@ import org.thingsboard.server.common.data.kv.AttributeKvEntry; import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.kv.StringDataEntry; +import org.thingsboard.server.common.data.limit.LimitedApi; import org.thingsboard.server.common.data.notification.rule.trigger.EdgeCommunicationFailureTrigger; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.SortOrder; import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.common.msg.tools.TbRateLimitsException; import org.thingsboard.server.gen.edge.v1.AlarmCommentUpdateMsg; import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg; @@ -264,6 +267,12 @@ public final class EdgeGrpcSession implements Closeable { } private void onUplinkMsg(UplinkMsg uplinkMsg) { + if (!ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES, tenantId)) { + throw new TbRateLimitsException(EntityType.TENANT); + } + if (!ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES_PER_EDGE, tenantId, edge.getId())) { + throw new TbRateLimitsException(EntityType.EDGE); + } ListenableFuture> future = processUplinkMsg(uplinkMsg); Futures.addCallback(future, new FutureCallback<>() { @Override diff --git a/application/src/test/java/org/thingsboard/server/service/limits/RateLimitServiceTest.java b/application/src/test/java/org/thingsboard/server/service/limits/RateLimitServiceTest.java index 2570b80f9f..95a2c63f52 100644 --- a/application/src/test/java/org/thingsboard/server/service/limits/RateLimitServiceTest.java +++ b/application/src/test/java/org/thingsboard/server/service/limits/RateLimitServiceTest.java @@ -71,6 +71,8 @@ public class RateLimitServiceTest { profileConfiguration.setCassandraQueryTenantRateLimitsConfiguration(rateLimit); profileConfiguration.setEdgeEventRateLimits(rateLimit); profileConfiguration.setEdgeEventRateLimitsPerEdge(rateLimit); + profileConfiguration.setEdgeUplinkMessagesRateLimits(rateLimit); + profileConfiguration.setEdgeUplinkMessagesRateLimitsPerEdge(rateLimit); updateTenantProfileConfiguration(profileConfiguration); for (LimitedApi limitedApi : List.of( @@ -80,7 +82,9 @@ public class RateLimitServiceTest { LimitedApi.REST_REQUESTS_PER_CUSTOMER, LimitedApi.CASSANDRA_QUERIES, LimitedApi.EDGE_EVENTS, - LimitedApi.EDGE_EVENTS_PER_EDGE + LimitedApi.EDGE_EVENTS_PER_EDGE, + LimitedApi.EDGE_UPLINK_MESSAGES, + LimitedApi.EDGE_UPLINK_MESSAGES_PER_EDGE )) { testRateLimits(limitedApi, max, tenantId); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/limit/LimitedApi.java b/common/data/src/main/java/org/thingsboard/server/common/data/limit/LimitedApi.java index 980eb880a0..1a0f038c90 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/limit/LimitedApi.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/limit/LimitedApi.java @@ -33,6 +33,8 @@ public enum LimitedApi { CASSANDRA_QUERIES(DefaultTenantProfileConfiguration::getCassandraQueryTenantRateLimitsConfiguration, "Cassandra queries", true), EDGE_EVENTS(DefaultTenantProfileConfiguration::getEdgeEventRateLimits, "Edge events", true), EDGE_EVENTS_PER_EDGE(DefaultTenantProfileConfiguration::getEdgeEventRateLimitsPerEdge, "Edge events per edge", false), + EDGE_UPLINK_MESSAGES(DefaultTenantProfileConfiguration::getEdgeUplinkMessagesRateLimits, "Edge uplink messages", true), + EDGE_UPLINK_MESSAGES_PER_EDGE(DefaultTenantProfileConfiguration::getEdgeUplinkMessagesRateLimitsPerEdge, "Edge uplink messages per edge", false), PASSWORD_RESET(false, true), TWO_FA_VERIFICATION_CODE_SEND(false, true), TWO_FA_VERIFICATION_CODE_CHECK(false, true), diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java index 3fe110de0b..a0cfbfe1e1 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java @@ -83,6 +83,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura private String edgeEventRateLimits; private String edgeEventRateLimitsPerEdge; + private String edgeUplinkMessagesRateLimits; + private String edgeUplinkMessagesRateLimitsPerEdge; private int defaultStorageTtlDays; private int alarmsTtlDays; diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html index 867cd74f3b..ef024fe0a2 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html @@ -571,6 +571,14 @@ [type]="rateLimitsType.EDGE_EVENTS_PER_EDGE_RATE_LIMIT">
    +
    + + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts index 0c95324d85..c13eed9c03 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.ts @@ -108,7 +108,9 @@ export class DefaultTenantProfileConfigurationComponent implements ControlValueA wsUpdatesPerSessionRateLimit: [null, []], cassandraQueryTenantRateLimitsConfiguration: [null, []], edgeEventRateLimits: [null, []], - edgeEventRateLimitsPerEdge: [null, []] + edgeEventRateLimitsPerEdge: [null, []], + edgeUplinkMessagesRateLimits: [null, []], + edgeUplinkMessagesRateLimitsPerEdge: [null, []] }); this.defaultTenantProfileConfigurationFormGroup.get('smsEnabled').valueChanges.pipe( diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.models.ts b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.models.ts index 8924682aa1..ee13ea9b23 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.models.ts +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/rate-limits/rate-limits.models.ts @@ -37,7 +37,9 @@ export enum RateLimitsType { TENANT_NOTIFICATION_REQUEST_RATE_LIMIT = 'TENANT_NOTIFICATION_REQUEST_RATE_LIMIT', TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT = 'TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT', EDGE_EVENTS_RATE_LIMIT = 'EDGE_EVENTS_RATE_LIMIT', - EDGE_EVENTS_PER_EDGE_RATE_LIMIT = 'EDGE_EVENTS_PER_EDGE_RATE_LIMIT' + EDGE_EVENTS_PER_EDGE_RATE_LIMIT = 'EDGE_EVENTS_PER_EDGE_RATE_LIMIT', + EDGE_UPLINK_MESSAGES_RATE_LIMIT = 'EDGE_UPLINK_MESSAGES_RATE_LIMIT', + EDGE_UPLINK_MESSAGES_PER_EDGE_RATE_LIMIT = 'EDGE_UPLINK_MESSAGES_PER_EDGE_RATE_LIMIT' } export const rateLimitsLabelTranslationMap = new Map( @@ -58,6 +60,8 @@ export const rateLimitsLabelTranslationMap = new Map( [RateLimitsType.TENANT_NOTIFICATION_REQUESTS_PER_RULE_RATE_LIMIT, 'tenant-profile.tenant-notification-requests-per-rule-rate-limit'], [RateLimitsType.EDGE_EVENTS_RATE_LIMIT, 'tenant-profile.rate-limits.edge-events-rate-limit'], [RateLimitsType.EDGE_EVENTS_PER_EDGE_RATE_LIMIT, 'tenant-profile.rate-limits.edge-events-per-edge-rate-limit'], + [RateLimitsType.EDGE_UPLINK_MESSAGES_RATE_LIMIT, 'tenant-profile.rate-limits.edge-uplink-messages-rate-limit'], + [RateLimitsType.EDGE_UPLINK_MESSAGES_PER_EDGE_RATE_LIMIT, 'tenant-profile.rate-limits.edge-uplink-messages-per-edge-rate-limit'], ] ); @@ -79,6 +83,8 @@ export const rateLimitsDialogTitleTranslationMap = new Map( @@ -43,5 +45,7 @@ export const LimitedApiTranslationMap = new Map( [LimitedApi.TRANSPORT_MESSAGES_PER_DEVICE, 'api-limit.transport-messages-per-device'], [LimitedApi.EDGE_EVENTS, 'api-limit.edge-events'], [LimitedApi.EDGE_EVENTS_PER_EDGE, 'api-limit.edge-events-per-edge'], + [LimitedApi.EDGE_UPLINK_MESSAGES, 'api-limit.edge-uplink-messages'], + [LimitedApi.EDGE_UPLINK_MESSAGES_PER_EDGE, 'api-limit.edge-uplink-messages-per-edge'] ] ); diff --git a/ui-ngx/src/assets/help/en_US/notification/rate_limits.md b/ui-ngx/src/assets/help/en_US/notification/rate_limits.md index d314e681c2..c17610f39a 100644 --- a/ui-ngx/src/assets/help/en_US/notification/rate_limits.md +++ b/ui-ngx/src/assets/help/en_US/notification/rate_limits.md @@ -11,7 +11,7 @@ Available template parameters: * `api` - rate-limited API label; one of: 'REST API requests', 'REST API requests per customer', 'transport messages', 'transport messages per device', 'Cassandra queries', 'WS updates per session', 'notification requests', 'notification requests per rule', - 'entity version creation', 'entity version load', 'Edge events', 'Edge events per edge'; + 'entity version creation', 'entity version load', 'Edge events', 'Edge events per edge', 'Edge uplink messages', 'Edge uplink messages per edge'; * `limitLevelEntityType` - entity type of the limit level entity, e.g. 'Tenant', 'Device', 'Notification rule', 'Customer', etc.; * `limitLevelEntityId` - id of the limit level entity; * `limitLevelEntityName` - name of the limit level entity; 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 288db8c9d2..122bf74d29 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -861,7 +861,9 @@ "transport-messages-per-device": "Transport messages per device", "ws-updates-per-session": "WS updates per session", "edge-events": "Edge events", - "edge-events-per-edge": "Edge events per edge" + "edge-events-per-edge": "Edge events per edge", + "edge-uplink-messages": "Edge uplink messages", + "edge-uplink-messages-per-edge": "Edge uplink messages per edge" }, "audit-log": { "audit": "Audit", @@ -4209,6 +4211,10 @@ "edit-edge-events-per-edge-rate-limit": "Edit edge events per edge rate limits", "edge-events-rate-limit": "Edge events", "edge-events-per-edge-rate-limit": "Edge events per edge", + "edit-edge-uplink-messages-rate-limit": "Edit edge uplink messages rate limits", + "edit-edge-uplink-messages-per-edge-rate-limit": "Edit edge uplink messages per edge rate limits", + "edge-uplink-messages-rate-limit": "Edge uplink messages", + "edge-uplink-messages-per-edge-rate-limit": "Edge uplink messages per edge", "messages-per": "messages per", "not-set": "Not set", "number-of-messages": "Number of messages", From 73bef368de96ca2074c14792c124c09f2a659fba Mon Sep 17 00:00:00 2001 From: Dmitriymush Date: Mon, 19 Feb 2024 15:58:42 +0200 Subject: [PATCH 271/397] UI: refactoring of widget action component --- .../common/action/widget-action.component.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts index 3fa353623f..b7183a5b80 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/action/widget-action.component.ts @@ -34,7 +34,7 @@ import { import { WidgetService } from '@core/http/widget.service'; import { WidgetActionCallbacks } from '@home/components/widget/action/manage-widget-actions.component.models'; import { map, mergeMap, share, startWith, takeUntil, tap } from 'rxjs/operators'; -import { Observable, of, Subject, Subscription } from 'rxjs'; +import { Observable, of, ReplaySubject, Subject, Subscription } from 'rxjs'; import { Dashboard } from '@shared/models/dashboard.models'; import { DashboardService } from '@core/http/dashboard.service'; import { DashboardUtilsService } from '@core/services/dashboard-utils.service'; @@ -186,7 +186,7 @@ export class WidgetActionComponent implements ControlValueAccessor, OnInit, Vali } onDashboardStateInputFocus(): void { - this.actionTypeFormGroup.get('targetDashboardId').updateValueAndValidity({onlySelf: true, emitEvent: true}); + this.actionTypeFormGroup.get('targetDashboardStateId').updateValueAndValidity({onlySelf: true, emitEvent: true}); } stateDisplayTypeName(displayType: stateDisplayType): string { @@ -228,16 +228,16 @@ export class WidgetActionComponent implements ControlValueAccessor, OnInit, Vali this.fb.control(action ? action.stateEntityParamName : null, []) ); if (type === WidgetActionType.openDashboard) { + const targetDashboardId = action ? action.targetDashboardId : null; this.actionTypeFormGroup.addControl( 'openNewBrowserTab', this.fb.control(action ? action.openNewBrowserTab : false, []) ); this.actionTypeFormGroup.addControl( 'targetDashboardId', - this.fb.control(action ? action.targetDashboardId : null, - [Validators.required]) + this.fb.control(targetDashboardId, [Validators.required]) ); - this.setupSelectedDashboardStateIds(); + this.setupSelectedDashboardStateIds(targetDashboardId); } else { if (type === WidgetActionType.openDashboardState) { const displayType = this.getStateDisplayType(action); @@ -367,9 +367,10 @@ export class WidgetActionComponent implements ControlValueAccessor, OnInit, Vali ); } - private setupSelectedDashboardStateIds() { + private setupSelectedDashboardStateIds(targetDashboardId: string | null) { this.selectedDashboardStateIds = this.actionTypeFormGroup.get('targetDashboardId').valueChanges.pipe( + startWith(targetDashboardId), tap((dashboardId) => { if (!dashboardId) { this.actionTypeFormGroup.get('targetDashboardStateId') @@ -400,7 +401,12 @@ export class WidgetActionComponent implements ControlValueAccessor, OnInit, Vali return []; } }), - share() + share({ + connector: () => new ReplaySubject(1), + resetOnError: false, + resetOnComplete: false, + resetOnRefCountZero: false + }) ); } From 7d634c2ee0f4648ff62c1e4a6d6e7ffd0fb1d5c5 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Tue, 20 Feb 2024 14:37:06 +0200 Subject: [PATCH 272/397] Improve handling rate limit and send response of failure to edge --- .../service/edge/rpc/EdgeGrpcSession.java | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java index 7a5d94bcdb..86a5af2a61 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java @@ -27,7 +27,6 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.springframework.data.util.Pair; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EdgeUtils; -import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEvent; import org.thingsboard.server.common.data.id.EdgeId; @@ -42,7 +41,6 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.SortOrder; import org.thingsboard.server.common.data.page.TimePageLink; -import org.thingsboard.server.common.msg.tools.TbRateLimitsException; import org.thingsboard.server.gen.edge.v1.AlarmCommentUpdateMsg; import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.v1.AssetProfileUpdateMsg; @@ -112,6 +110,7 @@ public final class EdgeGrpcSession implements Closeable { private static final String QUEUE_START_TS_ATTR_KEY = "queueStartTs"; private static final String QUEUE_START_SEQ_ID_ATTR_KEY = "queueStartSeqId"; + private static final String RATE_LIMIT_REACHED = "Rate limit reached"; private final UUID sessionId; private final BiConsumer sessionOpenListener; @@ -267,42 +266,51 @@ public final class EdgeGrpcSession implements Closeable { } private void onUplinkMsg(UplinkMsg uplinkMsg) { - if (!ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES, tenantId)) { - throw new TbRateLimitsException(EntityType.TENANT); - } - if (!ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES_PER_EDGE, tenantId, edge.getId())) { - throw new TbRateLimitsException(EntityType.EDGE); + if (isRateLimitViolated(uplinkMsg)) { + return; } ListenableFuture> future = processUplinkMsg(uplinkMsg); Futures.addCallback(future, new FutureCallback<>() { @Override public void onSuccess(@Nullable List result) { - UplinkResponseMsg uplinkResponseMsg = UplinkResponseMsg.newBuilder() - .setUplinkMsgId(uplinkMsg.getUplinkMsgId()) - .setSuccess(true).build(); - sendDownlinkMsg(ResponseMsg.newBuilder() - .setUplinkResponseMsg(uplinkResponseMsg) - .build()); + sendResponseMessage(uplinkMsg.getUplinkMsgId(), true, null); } @Override public void onFailure(Throwable t) { String errorMsg = EdgeUtils.createErrorMsgFromRootCauseAndStackTrace(t); - UplinkResponseMsg uplinkResponseMsg = UplinkResponseMsg.newBuilder() - .setUplinkMsgId(uplinkMsg.getUplinkMsgId()) - .setSuccess(false).setErrorMsg(errorMsg).build(); - sendDownlinkMsg(ResponseMsg.newBuilder() - .setUplinkResponseMsg(uplinkResponseMsg) - .build()); + sendResponseMessage(uplinkMsg.getUplinkMsgId(), false, errorMsg); } }, ctx.getGrpcCallbackExecutorService()); } + private boolean isRateLimitViolated(UplinkMsg uplinkMsg) { + if (!ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES, tenantId) || + !ctx.getRateLimitService().checkRateLimit(LimitedApi.EDGE_UPLINK_MESSAGES_PER_EDGE, tenantId, edge.getId())) { + String errorMsg = String.format("Failed to process uplink message. %s", RATE_LIMIT_REACHED); + sendResponseMessage(uplinkMsg.getUplinkMsgId(), false, errorMsg); + return true; + } + return false; + } + + private void sendResponseMessage(int uplinkMsgId, boolean success, String errorMsg) { + UplinkResponseMsg.Builder responseBuilder = UplinkResponseMsg.newBuilder() + .setUplinkMsgId(uplinkMsgId) + .setSuccess(success); + if (errorMsg != null) { + responseBuilder.setErrorMsg(errorMsg); + } + sendDownlinkMsg(ResponseMsg.newBuilder() + .setUplinkResponseMsg(responseBuilder.build()) + .build()); + } + private void onDownlinkResponse(DownlinkResponseMsg msg) { try { if (msg.getSuccess()) { sessionState.getPendingMsgsMap().remove(msg.getDownlinkMsgId()); - log.debug("[{}][{}] Msg has been processed successfully!Msg Id: [{}], Msg: {}", this.tenantId, edge.getRoutingKey(), msg.getDownlinkMsgId(), msg); + log.debug("[{}][{}] Msg has been processed successfully! Msg Id: [{}], Msg: {}", this.tenantId, edge.getRoutingKey(), msg.getDownlinkMsgId(), msg); } else { log.error("[{}][{}] Msg processing failed! Msg Id: [{}], Error msg: {}", this.tenantId, edge.getRoutingKey(), msg.getDownlinkMsgId(), msg.getErrorMsg()); } From e6ffb22d6f20c7b12a702a1c2fe70ef2f43ceca8 Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Wed, 21 Feb 2024 14:32:20 +0200 Subject: [PATCH 273/397] Add ui part of oauth edge enabled. Add test --- .../main/data/upgrade/3.6.3/schema_update.sql | 22 ++++ .../install/ThingsboardInstallService.java | 3 + .../edge/EdgeEventSourcingListener.java | 3 + .../rpc/fetch/CustomerEdgeEventFetcher.java | 2 +- .../edge/rpc/fetch/EdgeEventFetcher.java | 2 +- .../rpc/fetch/OAuth2EdgeEventFetcher.java | 22 ++-- .../install/SqlDatabaseUpgradeService.java | 3 + .../server/controller/HomePageApiTest.java | 2 +- .../server/edge/OAuth2EdgeTest.java | 110 ++++++++++++++++++ .../server/edge/imitator/EdgeImitator.java | 6 + .../server/common/data/oauth2/OAuth2Info.java | 2 + .../common/data/oauth2/OAuth2Params.java | 2 + .../server/dao/model/ModelConstants.java | 1 + .../dao/model/sql/OAuth2ParamsEntity.java | 5 + .../server/dao/oauth2/OAuth2ServiceImpl.java | 1 + .../server/dao/oauth2/OAuth2Utils.java | 1 + .../main/resources/sql/schema-entities.sql | 1 + .../server/dao/service/OAuth2ServiceTest.java | 25 ++-- .../admin/oauth2-settings.component.html | 5 +- .../pages/admin/oauth2-settings.component.ts | 3 +- .../assets/locale/locale.constant-en_US.json | 1 + 21 files changed, 196 insertions(+), 26 deletions(-) create mode 100644 application/src/main/data/upgrade/3.6.3/schema_update.sql create mode 100644 application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java diff --git a/application/src/main/data/upgrade/3.6.3/schema_update.sql b/application/src/main/data/upgrade/3.6.3/schema_update.sql new file mode 100644 index 0000000000..98edcbcddf --- /dev/null +++ b/application/src/main/data/upgrade/3.6.3/schema_update.sql @@ -0,0 +1,22 @@ +-- +-- Copyright © 2016-2024 The Thingsboard Authors +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + +-- OAUTH2 PARAMS ALTER TABLE START + +ALTER TABLE oauth2_params + ADD COLUMN IF NOT EXISTS edge_enabled boolean DEFAULT false; + +-- OAUTH2 PARAMS ALTER TABLE END diff --git a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java index 44d81902a8..400d1eda27 100644 --- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java +++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java @@ -127,6 +127,9 @@ public class ThingsboardInstallService { log.info("Upgrading ThingsBoard from version 3.6.2 to 3.6.3 ..."); databaseEntitiesUpgradeService.upgradeDatabase("3.6.2"); systemDataLoaderService.updateDefaultNotificationConfigs(); + case "3.6.3": + log.info("Upgrading ThingsBoard from version 3.6.3 to 3.6.4 ..."); + databaseEntitiesUpgradeService.upgradeDatabase("3.6.3"); //TODO DON'T FORGET to update switch statement in the CacheCleanupService if you need to clear the cache break; default: diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java index f2dac98d47..7be800afb3 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java @@ -165,6 +165,9 @@ public class EdgeEventSourcingListener { } } else if (entity instanceof AlarmApiCallResult || entity instanceof Alarm) { return false; + } else if (entity instanceof OAuth2Info) { + OAuth2Info oAuth2Info = (OAuth2Info) entity; + return oAuth2Info.isEdgeEnabled(); } // Default: If the entity doesn't match any of the conditions, consider it as valid. return true; diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/CustomerEdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/CustomerEdgeEventFetcher.java index 57596a76de..ff34e618bc 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/CustomerEdgeEventFetcher.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/CustomerEdgeEventFetcher.java @@ -46,7 +46,7 @@ public class CustomerEdgeEventFetcher implements EdgeEventFetcher { List result = new ArrayList<>(); result.add(EdgeUtils.constructEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, EdgeEventActionType.ADDED, customerId, null)); - // @voba - returns PageData object to be in sync with other fetchers + // returns PageData object to be in sync with other fetchers return new PageData<>(result, 1, result.size(), false); } } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/EdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/EdgeEventFetcher.java index 6f1fa1ae7b..81eb83b76a 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/EdgeEventFetcher.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/EdgeEventFetcher.java @@ -25,5 +25,5 @@ public interface EdgeEventFetcher { PageLink getPageLink(int pageSize); - PageData fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) throws Exception; + PageData fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink); } diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java index 60b10e6a17..e4ef6cfdb6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/OAuth2EdgeEventFetcher.java @@ -29,25 +29,29 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.oauth2.OAuth2Service; +import java.util.ArrayList; import java.util.List; @AllArgsConstructor @Slf4j -public class OAuth2EdgeEventFetcher extends BasePageableEdgeEventFetcher { +public class OAuth2EdgeEventFetcher implements EdgeEventFetcher { private final OAuth2Service oAuth2Service; @Override - PageData fetchPageData(TenantId tenantId, Edge edge, PageLink pageLink) { - OAuth2Info result = oAuth2Service.findOAuth2Info(); - - // return PageData object to be in sync with other fetchers - return new PageData<>(List.of(result), 1, 1, false); + public PageLink getPageLink(int pageSize) { + return null; } @Override - EdgeEvent constructEdgeEvent(TenantId tenantId, Edge edge, OAuth2Info entity) { - return EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.OAUTH2, - EdgeEventActionType.ADDED, null, JacksonUtil.valueToTree(entity)); + public PageData fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) { + List result = new ArrayList<>(); + OAuth2Info oAuth2Info = oAuth2Service.findOAuth2Info(); + if (oAuth2Info.isEdgeEnabled()) { + result.add(EdgeUtils.constructEdgeEvent(tenantId, edge.getId(), EdgeEventType.OAUTH2, + EdgeEventActionType.ADDED, null, JacksonUtil.valueToTree(oAuth2Info))); + } + // returns PageData object to be in sync with other fetchers + return new PageData<>(result, 1, result.size(), false); } } diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java index 436c2fcc84..bf281b8571 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java @@ -115,6 +115,9 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService case "3.6.2": updateSchema("3.6.2", 3006002, "3.6.3", 3006003, null); break; + case "3.6.3": + updateSchema("3.6.3", 3006003, "3.6.4", 3006004, null); + break; default: throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); } diff --git a/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java b/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java index 8b0854983a..717c17d437 100644 --- a/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/HomePageApiTest.java @@ -494,7 +494,7 @@ public class HomePageApiTest extends AbstractControllerTest { } private OAuth2Info createDefaultOAuth2Info() { - return new OAuth2Info(true, Lists.newArrayList( + return new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("domain").scheme(SchemeType.MIXED).build() diff --git a/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java new file mode 100644 index 0000000000..f10338b37b --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/edge/OAuth2EdgeTest.java @@ -0,0 +1,110 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.edge; + +import com.google.common.collect.Lists; +import com.google.protobuf.AbstractMessage; +import org.junit.Assert; +import org.junit.Test; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.oauth2.MapperType; +import org.thingsboard.server.common.data.oauth2.OAuth2CustomMapperConfig; +import org.thingsboard.server.common.data.oauth2.OAuth2DomainInfo; +import org.thingsboard.server.common.data.oauth2.OAuth2Info; +import org.thingsboard.server.common.data.oauth2.OAuth2MapperConfig; +import org.thingsboard.server.common.data.oauth2.OAuth2ParamsInfo; +import org.thingsboard.server.common.data.oauth2.OAuth2RegistrationInfo; +import org.thingsboard.server.common.data.oauth2.SchemeType; +import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg; + +import java.util.Arrays; +import java.util.Collections; +import java.util.UUID; + +@DaoSqlTest +public class OAuth2EdgeTest extends AbstractEdgeTest { + + @Test + public void testOAuth2Support() throws Exception { + loginSysAdmin(); + + // enable oauth, verify nothing sent to edge + edgeImitator.expectMessageAmount(1); + OAuth2Info oAuth2Info = createDefaultOAuth2Info(); + oAuth2Info = doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class); + Assert.assertFalse(edgeImitator.waitForMessages(10)); + + // enable edge support + edgeImitator.expectMessageAmount(1); + oAuth2Info.setEdgeEnabled(true); + oAuth2Info = doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class); + Assert.assertTrue(edgeImitator.waitForMessages()); + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); + Assert.assertTrue(latestMessage instanceof OAuth2UpdateMsg); + OAuth2UpdateMsg oAuth2UpdateMsg = (OAuth2UpdateMsg) latestMessage; + OAuth2Info result = JacksonUtil.fromString(oAuth2UpdateMsg.getEntity(), OAuth2Info.class, true); + Assert.assertEquals(oAuth2Info, result); + + // disable oauth suppor + oAuth2Info.setEnabled(false); + oAuth2Info.setEdgeEnabled(false); + doPost("/api/oauth2/config", oAuth2Info, OAuth2Info.class); + + loginTenantAdmin(); + } + + private OAuth2Info createDefaultOAuth2Info() { + return new OAuth2Info(true, false, Lists.newArrayList( + OAuth2ParamsInfo.builder() + .domainInfos(Lists.newArrayList( + OAuth2DomainInfo.builder().name("domain").scheme(SchemeType.MIXED).build() + )) + .mobileInfos(Collections.emptyList()) + .clientRegistrations(Lists.newArrayList( + validRegistrationInfo() + )) + .build() + )); + } + + private OAuth2RegistrationInfo validRegistrationInfo() { + return OAuth2RegistrationInfo.builder() + .clientId(UUID.randomUUID().toString()) + .clientSecret(UUID.randomUUID().toString()) + .authorizationUri(UUID.randomUUID().toString()) + .accessTokenUri(UUID.randomUUID().toString()) + .scope(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString())) + .platforms(Collections.emptyList()) + .userInfoUri(UUID.randomUUID().toString()) + .userNameAttributeName(UUID.randomUUID().toString()) + .jwkSetUri(UUID.randomUUID().toString()) + .clientAuthenticationMethod(UUID.randomUUID().toString()) + .loginButtonLabel(UUID.randomUUID().toString()) + .mapperConfig( + OAuth2MapperConfig.builder() + .type(MapperType.CUSTOM) + .custom( + OAuth2CustomMapperConfig.builder() + .url(UUID.randomUUID().toString()) + .build() + ) + .build() + ) + .build(); + } + +} diff --git a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java index 916e5790e9..12405a7d5f 100644 --- a/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java +++ b/application/src/test/java/org/thingsboard/server/edge/imitator/EdgeImitator.java @@ -44,6 +44,7 @@ import org.thingsboard.server.gen.edge.v1.DownlinkResponseMsg; import org.thingsboard.server.gen.edge.v1.EdgeConfiguration; import org.thingsboard.server.gen.edge.v1.EntityDataProto; import org.thingsboard.server.gen.edge.v1.EntityViewUpdateMsg; +import org.thingsboard.server.gen.edge.v1.OAuth2UpdateMsg; import org.thingsboard.server.gen.edge.v1.OtaPackageUpdateMsg; import org.thingsboard.server.gen.edge.v1.QueueUpdateMsg; import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg; @@ -314,6 +315,11 @@ public class EdgeImitator { result.add(saveDownlinkMsg(resourceUpdateMsg)); } } + if (downlinkMsg.getOAuth2UpdateMsgCount() > 0) { + for (OAuth2UpdateMsg oAuth2UpdateMsg : downlinkMsg.getOAuth2UpdateMsgList()) { + result.add(saveDownlinkMsg(oAuth2UpdateMsg)); + } + } if (downlinkMsg.hasEdgeConfiguration()) { result.add(saveDownlinkMsg(downlinkMsg.getEdgeConfiguration())); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Info.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Info.java index b25ac56544..bee624c9cb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Info.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Info.java @@ -36,6 +36,8 @@ import java.util.List; public class OAuth2Info { @ApiModelProperty("Whether OAuth2 settings are enabled or not") private boolean enabled; + @ApiModelProperty("Whether OAuth2 settings are enabled on Edge or not") + private boolean edgeEnabled; @ApiModelProperty(value = "List of configured OAuth2 clients. Cannot contain null values", required = true) private List oauth2ParamsInfos; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Params.java b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Params.java index 3f847c2f9e..70020fc7cd 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Params.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/oauth2/OAuth2Params.java @@ -30,11 +30,13 @@ import org.thingsboard.server.common.data.id.TenantId; public class OAuth2Params extends BaseData { private boolean enabled; + private boolean edgeEnabled; private TenantId tenantId; public OAuth2Params(OAuth2Params oauth2Params) { super(oauth2Params); this.enabled = oauth2Params.enabled; + this.edgeEnabled = oauth2Params.edgeEnabled; this.tenantId = oauth2Params.tenantId; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 2fe56f5d1f..d5c120393c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -427,6 +427,7 @@ public class ModelConstants { */ public static final String OAUTH2_PARAMS_TABLE_NAME = "oauth2_params"; public static final String OAUTH2_PARAMS_ENABLED_PROPERTY = "enabled"; + public static final String OAUTH2_PARAMS_EDGE_ENABLED_PROPERTY = "edge_enabled"; public static final String OAUTH2_PARAMS_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; public static final String OAUTH2_REGISTRATION_TABLE_NAME = "oauth2_registration"; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ParamsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ParamsEntity.java index 142e7c3828..9c6db56854 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ParamsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/OAuth2ParamsEntity.java @@ -39,6 +39,9 @@ public class OAuth2ParamsEntity extends BaseSqlEntity { @Column(name = ModelConstants.OAUTH2_PARAMS_ENABLED_PROPERTY) private Boolean enabled; + @Column(name = ModelConstants.OAUTH2_PARAMS_EDGE_ENABLED_PROPERTY) + private Boolean edgeEnabled; + @Column(name = ModelConstants.OAUTH2_PARAMS_TENANT_ID_PROPERTY) private UUID tenantId; @@ -48,6 +51,7 @@ public class OAuth2ParamsEntity extends BaseSqlEntity { } this.setCreatedTime(oauth2Params.getCreatedTime()); this.enabled = oauth2Params.isEnabled(); + this.edgeEnabled = oauth2Params.isEdgeEnabled(); if (oauth2Params.getTenantId() != null) { this.tenantId = oauth2Params.getTenantId().getId(); } @@ -60,6 +64,7 @@ public class OAuth2ParamsEntity extends BaseSqlEntity { oauth2Params.setCreatedTime(createdTime); oauth2Params.setTenantId(TenantId.fromUUID(tenantId)); oauth2Params.setEnabled(enabled); + oauth2Params.setEdgeEnabled(edgeEnabled); return oauth2Params; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java index f85a684e72..5a5aa315fa 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ServiceImpl.java @@ -127,6 +127,7 @@ public class OAuth2ServiceImpl extends AbstractEntityService implements OAuth2Se OAuth2Info oauth2Info = new OAuth2Info(); List oauth2ParamsList = oauth2ParamsDao.find(TenantId.SYS_TENANT_ID); oauth2Info.setEnabled(oauth2ParamsList.stream().anyMatch(OAuth2Params::isEnabled)); + oauth2Info.setEdgeEnabled(oauth2ParamsList.stream().anyMatch(OAuth2Params::isEdgeEnabled)); List oauth2ParamsInfos = new ArrayList<>(); oauth2Info.setOauth2ParamsInfos(oauth2ParamsInfos); oauth2ParamsList.stream().sorted(Comparator.comparing(BaseData::getUuidId)).forEach(oauth2Params -> { diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java index 4e22ea858b..8d30fc905d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2Utils.java @@ -88,6 +88,7 @@ public class OAuth2Utils { public static OAuth2Params infoToOAuth2Params(OAuth2Info oauth2Info) { OAuth2Params oauth2Params = new OAuth2Params(); oauth2Params.setEnabled(oauth2Info.isEnabled()); + oauth2Params.setEdgeEnabled(oauth2Info.isEdgeEnabled()); oauth2Params.setTenantId(TenantId.SYS_TENANT_ID); return oauth2Params; } diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 2352ea2eb3..a5a8d4e37d 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -560,6 +560,7 @@ CREATE TABLE IF NOT EXISTS ts_kv_dictionary CREATE TABLE IF NOT EXISTS oauth2_params ( id uuid NOT NULL CONSTRAINT oauth2_params_pkey PRIMARY KEY, enabled boolean, + edge_enabled boolean, tenant_id uuid, created_time bigint NOT NULL ); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/OAuth2ServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/OAuth2ServiceTest.java index ae9aa72be9..281709c9af 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/OAuth2ServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/OAuth2ServiceTest.java @@ -47,7 +47,7 @@ import java.util.stream.Collectors; @DaoSqlTest public class OAuth2ServiceTest extends AbstractServiceTest { - private static final OAuth2Info EMPTY_PARAMS = new OAuth2Info(false, Collections.emptyList()); + private static final OAuth2Info EMPTY_PARAMS = new OAuth2Info(false, false, Collections.emptyList()); @Autowired protected OAuth2Service oAuth2Service; @@ -66,7 +66,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { @Test public void testSaveHttpAndMixedDomainsTogether() { - OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), @@ -87,7 +87,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { @Test public void testSaveHttpsAndMixedDomainsTogether() { - OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTPS).build(), @@ -153,7 +153,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { Assert.assertNotNull(foundOAuth2Info); Assert.assertEquals(oAuth2Info, foundOAuth2Info); - OAuth2Info newOAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info newOAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("another-domain").scheme(SchemeType.HTTPS).build() @@ -194,7 +194,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { List thirdGroup = Lists.newArrayList( validRegistrationInfo() ); - OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), @@ -318,7 +318,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { validRegistrationInfo(), validRegistrationInfo() ); - OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), @@ -363,7 +363,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { @Test public void testGetDisabledOAuth2Clients() { - OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), @@ -402,7 +402,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { @Test public void testFindAllRegistrations() { - OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), @@ -451,7 +451,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { @Test public void testFindRegistrationById() { - OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), @@ -495,7 +495,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { @Test public void testFindAppSecret() { - OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), @@ -547,7 +547,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { @Test public void testFindClientsByPackageAndPlatform() { - OAuth2Info oAuth2Info = new OAuth2Info(true, Lists.newArrayList( + OAuth2Info oAuth2Info = new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), @@ -596,7 +596,7 @@ public class OAuth2ServiceTest extends AbstractServiceTest { } private OAuth2Info createDefaultOAuth2Info() { - return new OAuth2Info(true, Lists.newArrayList( + return new OAuth2Info(true, false, Lists.newArrayList( OAuth2ParamsInfo.builder() .domainInfos(Lists.newArrayList( OAuth2DomainInfo.builder().name("first-domain").scheme(SchemeType.HTTP).build(), @@ -664,4 +664,5 @@ public class OAuth2ServiceTest extends AbstractServiceTest { .appSecret(appSecret != null ? appSecret : StringUtils.randomAlphanumeric(24)) .build(); } + } diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html index b01f37a717..0414a5dff7 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.html @@ -29,10 +29,13 @@
    -
    +
    {{ 'admin.oauth2.enable' | translate }} + + {{ 'admin.oauth2.edge-enable' | translate }} +
    diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts index 1d346c70f1..b742c5281d 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts @@ -204,7 +204,8 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha private buildOAuth2SettingsForm(): void { this.oauth2SettingsForm = this.fb.group({ oauth2ParamsInfos: this.fb.array([]), - enabled: [false] + enabled: [false], + edgeEnabled: [false] }); } 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 19981797f8..0aa1c63119 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -283,6 +283,7 @@ "domain-schema-https": "HTTPS", "domain-schema-mixed": "HTTP+HTTPS", "enable": "Enable OAuth2 settings", + "edge-enable": "Propagate OAuth2 setting to Edge", "domains": "Domains", "mobile-apps": "Mobile applications", "no-mobile-apps": "No applications configured", From f92f86e4eb21c5d247ac0f46a31243ee57b972fa Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Wed, 21 Feb 2024 15:11:18 +0200 Subject: [PATCH 274/397] Fix locale.constant for oauth.edge.enabled --- .../server/service/edge/rpc/fetch/EdgeEventFetcher.java | 2 +- ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/EdgeEventFetcher.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/EdgeEventFetcher.java index 81eb83b76a..6f1fa1ae7b 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/EdgeEventFetcher.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/fetch/EdgeEventFetcher.java @@ -25,5 +25,5 @@ public interface EdgeEventFetcher { PageLink getPageLink(int pageSize); - PageData fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink); + PageData fetchEdgeEvents(TenantId tenantId, Edge edge, PageLink pageLink) throws Exception; } 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 0aa1c63119..3b55cf7be2 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -283,7 +283,7 @@ "domain-schema-https": "HTTPS", "domain-schema-mixed": "HTTP+HTTPS", "enable": "Enable OAuth2 settings", - "edge-enable": "Propagate OAuth2 setting to Edge", + "edge-enable": "Propagate OAuth2 settings to Edge", "domains": "Domains", "mobile-apps": "Mobile applications", "no-mobile-apps": "No applications configured", From 43c830e1029724bbe58fb90d54e8ec5ab99ed1eb Mon Sep 17 00:00:00 2001 From: Andrii Landiak Date: Wed, 21 Feb 2024 15:45:55 +0200 Subject: [PATCH 275/397] Fix ui when clicked edge enabled for oauth2 --- .../app/modules/home/pages/admin/oauth2-settings.component.ts | 2 +- ui-ngx/src/app/shared/models/oauth2.models.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts index b742c5281d..9cbf6368e6 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2-settings.component.ts @@ -211,7 +211,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha private initOAuth2Settings(oauth2Info: OAuth2Info): void { if (oauth2Info) { - this.oauth2SettingsForm.patchValue({enabled: oauth2Info.enabled}, {emitEvent: false}); + this.oauth2SettingsForm.patchValue({enabled: oauth2Info.enabled, edgeEnabled: oauth2Info.edgeEnabled}, {emitEvent: false}); oauth2Info.oauth2ParamsInfos.forEach((oauth2ParamsInfo) => { this.oauth2ParamsInfos.push(this.buildOAuth2ParamsInfoForm(oauth2ParamsInfo)); }); diff --git a/ui-ngx/src/app/shared/models/oauth2.models.ts b/ui-ngx/src/app/shared/models/oauth2.models.ts index b77a5f5888..9e3d3fa1c5 100644 --- a/ui-ngx/src/app/shared/models/oauth2.models.ts +++ b/ui-ngx/src/app/shared/models/oauth2.models.ts @@ -18,6 +18,7 @@ import { HasUUID } from '@shared/models/id/has-uuid'; export interface OAuth2Info { enabled: boolean; + edgeEnabled: boolean; oauth2ParamsInfos: OAuth2ParamsInfo[]; } From 3f48b2a0ee42691bfff77538373b1c37de686030 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 21 Feb 2024 18:24:00 +0200 Subject: [PATCH 276/397] UI: Minor fixed in notification dialog --- .../sent-notification-dialog.component.html | 26 +++++++++++-------- .../sent-notification-dialog.component.scss | 9 +++++++ .../sent/sent-notification-dialog.componet.ts | 2 ++ ...tion-template-configuration.component.scss | 2 +- ...emplate-notification-dialog.component.html | 18 +++++++------ .../template-notification-dialog.component.ts | 1 + 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html index 8f5d41de34..bf59950953 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.html @@ -140,20 +140,24 @@ {{ 'notification.compose' | translate }} - - - - + +
    + + +
    +
    {{ 'notification.review' | translate }} - - +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss index ee0c8aeedc..a6e8def974 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.component.scss @@ -110,6 +110,15 @@ margin-bottom: 16px; } + .tb-loader { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 400px; + max-height: 100%; + } + .preview-group { &.notification { background-color: #F3F6FA; diff --git a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts index 4d2d184dbd..7060baf5cc 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/sent/sent-notification-dialog.componet.ts @@ -147,6 +147,7 @@ export class SentNotificationDialogComponent extends this.notificationRequestForm.reset({}, {emitEvent: false}); this.notificationRequestForm.patchValue(this.data.request, {emitEvent: false}); this.notificationRequestForm.get('template.name').setValue(guid()); + this.notificationRequestForm.get('template.notificationType').setValue(NotificationType.GENERAL); let useTemplate = true; if (isDefinedAndNotNull(this.data.request.template)) { useTemplate = false; @@ -155,6 +156,7 @@ export class SentNotificationDialogComponent extends }, {emitEvent: false}); } this.notificationRequestForm.get('useTemplate').setValue(useTemplate, {onlySelf : true}); + this.deliveryConfiguration = this.templateNotificationForm.get('configuration.deliveryMethodsTemplates').value; } this.refreshAllowDeliveryMethod(); } diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.scss b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.scss index 312f69bdc7..eed548f07b 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.scss +++ b/ui-ngx/src/app/modules/home/pages/notification/template/configuration/notification-template-configuration.component.scss @@ -17,7 +17,7 @@ .tb-template-header { position: sticky; top: 0; - z-index: 1; + z-index: 5; padding-bottom: 12px; background-color: var(--mdc-dialog-container-color, white); diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html index 73618fd939..2d3e642dd2 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.html @@ -71,14 +71,16 @@ {{ 'notification.compose' | translate }} -
    - - -
    + +
    + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts index b34e5e5c4f..c0ae4f1abb 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/notification/template/template-notification-dialog.component.ts @@ -102,6 +102,7 @@ export class TemplateNotificationDialogComponent this.notificationTemplateConfigurationForm.patchValue({ deliveryMethodsTemplates: this.templateNotification.configuration.deliveryMethodsTemplates }, {emitEvent: false}); + this.deliveryConfiguration = this.templateNotificationForm.get('configuration.deliveryMethodsTemplates').value; } } From d815e8a1185a30032566d264c387947147633178 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 21 Feb 2024 18:33:08 +0200 Subject: [PATCH 277/397] UI: Add hint to setting notification rule Edge communication failure --- .../notification/rule/rule-notification-dialog.component.html | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.html index f4ae83143f..6a50a857a4 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.html @@ -453,6 +453,7 @@
    notification.filter From 27a42eac1494fb2a296489b9d974c446998feb1f Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 22 Feb 2024 10:22:46 +0200 Subject: [PATCH 278/397] UI: Required mark and error text were changed in the recipients' field of the notification rule dialog --- .../notification/rule/rule-notification-dialog.component.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.html b/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.html index f4ae83143f..f89bad912a 100644 --- a/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/notification/rule/rule-notification-dialog.component.html @@ -70,6 +70,8 @@ formControlName="targets" subType="{{ ruleNotificationForm.get('triggerType').value }}" entityType="{{ entityType.NOTIFICATION_TARGET }}" + labelText="{{ 'notification.recipients' | translate }}" + requiredText="{{ 'notification.recipients-required' | translate }}" placeholderText="{{ 'notification.recipient' | translate }}">
    {{ label | translate }} + {{ legendData.data[legendKey.dataIndex][type] }} +